diff --git a/.env.template b/.env.template index a413646..8e3b110 100644 --- a/.env.template +++ b/.env.template @@ -18,6 +18,8 @@ SHOULD_START_MONITORING_UI=boolean # Optional. If true, the app will start the m VISIBILITY_THRESHOLD_BLOCK_NUMBER=number # Optional. The block number to start indexing Project and Drip List visibility data from. Defaults to 0. +ECOSYSTEM_DEPLOYER=string # Optional. The address of the ecosystem deployer. If specified, NFT transfers will not be hidden by default. + ### INDEXING OPTIONS POLLING_INTERVAL=number # Optional. The interval in milliseconds to poll the blockchain for new events. Defaults to 5000. diff --git a/.gitignore b/.gitignore index 43f6a48..4fa7e32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # vscode -.vscode/settings.json +.vscode/* # Generated code contracts diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..645a59e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,40 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "💧Build Contracts", + "type": "shell", + "command": "npm run build:contracts", + "group": "build" + }, + { + "label": "💧Build Project", + "type": "shell", + "command": "npm run build", + "group": "build" + }, + { + "label": "💧Start Dev Server", + "type": "shell", + "command": "npm run dev", + "isBackground": true, + "problemMatcher": [] + }, + { + "label": "💧Start Production", + "type": "shell", + "command": "npm run start" + }, + { + "label": "💧Compile", + "type": "shell", + "command": "npm run check", + "group": "build" + }, + { + "label": "💧Clean Docker Volumes", + "type": "shell", + "command": "npm run docker:clean" + } + ] +} diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..a8933c9 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,88 @@ +# 🗂️ Database Migrations + +## 🛠️ Creating a New Migration + +To generate a new migration, run: + +```bash +npm run db:create-migration -- --name your_migration_name +``` + +This will create a new file in `src/db/migrations`. + +Rename the file extension from `.js` to `.ts`, and implement your migration using the following structure: + +```ts +import { QueryInterface } from 'sequelize'; + +export async function up({ context: sequelize }: any): Promise { + const queryInterface: QueryInterface = sequelize.getQueryInterface(); + + // Add your migration changes here. +} + +export async function down({ context: sequelize }: any): Promise { + const queryInterface: QueryInterface = sequelize.getQueryInterface(); + + // Add your revert logic here. +} +``` + +Sequelize does not fully support TypeScript out of the box. Manual steps like renaming and typing are required... + +> ⚠️ Make sure the project is built before running this scripts, as it uses the compiled .js files under dist. + +--- + +## 🚀 Running Migrations + +Migrations do **not** run automatically. To apply them: + +1. **Clean the project** + + ```bash + npm run clean + ``` + +2. **Build the project** + + ```bash + npm run build + ``` + +3. **Run pending migrations** + + ```bash + npm run db:run-migrations + ``` + +🤓 Alternatively, use: + +```bash +npm run dev:db:run-migrations +``` + +This runs all the above steps in one go. + +## 🔁 Reverting the Last Migration + +To undo the most recently applied migration: + +```bash +npm run db:revert-migration +``` + +> ⚠️ Make sure the project is built before running this script, as it uses the compiled .js files under dist. + +## 📋 Checking Migration Status + +To view the status of all migrations (which ones have been applied and which are pending), run: + +```bash +npm run dev:db:log-pending-migrations +``` + +This will output a list of migrations with their current status: + +- `up` indicates the migration has been applied. +- `down` indicates the migration is still pending. diff --git a/package-lock.json b/package-lock.json index 9d62e2d..5891dbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,9 @@ "license": "ISC", "dependencies": { "@efstajas/versioned-parser": "^0.1.4", + "@types/umzug": "^2.3.9", "bee-queue": "^1.5.0", - "bull-arena": "^4.0.0", + "bull-arena": "^4.4.2", "dotenv": "^16.3.1", "dotenv-expand": "^11.0.6", "ethers": "^6.7.1", @@ -20,12 +21,13 @@ "pg": "^8.11.3", "redis": "^4.6.10", "sequelize": "^6.32.1", + "umzug": "^3.8.2", "winston": "^3.10.0", - "zod": "^3.22.2" + "zod": "^3.24.2" }, "devDependencies": { "@typechain/ethers-v6": "^0.5.0", - "@types/bull-arena": "^3.0.7", + "@types/bull-arena": "^3.0.10", "@types/jest": "^29.5.11", "@types/node": "^20.5.9", "@types/pg": "^8.10.2", @@ -41,6 +43,7 @@ "jest": "^29.7.0", "nodemon": "^3.0.1", "prettier": "^3.0.3", + "sequelize-cli": "^6.6.2", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "typechain": "^8.3.1", @@ -67,1606 +70,2009 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", - "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=14.0.0" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true }, - "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/types": "^7.25.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" + "tslib": "^2.6.2" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/client-cognito-identity": { + "version": "3.768.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.768.0.tgz", + "integrity": "sha512-h/WOvKhuXVIhNKjDcsF6oY2oJuBusspnmEaX20h+GUzIrNMlf6qkJrWziT58KzzESyzeYZcGNWjcOfbVRpH6NA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-node": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz", + "integrity": "sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/core": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz", + "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/core": "^3.1.5", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } + "node_modules/@aws-sdk/core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-cognito-identity": { + "version": "3.768.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.768.0.tgz", + "integrity": "sha512-nNBN+lb2N8Odi0abHln60HqA4z0+UsBw8j7XU+ElEi5E2qOBCJSkLIFDIcYfn+j88FP2oLiQlOPe7H8pav5ayQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.768.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } + "node_modules/@aws-sdk/credential-provider-cognito-identity/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true }, - "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz", + "integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz", + "integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/property-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.1.2", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-http/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz", + "integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/types": "^7.25.2" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz", + "integrity": "sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-ini": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.758.0.tgz", + "integrity": "sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.758.0.tgz", + "integrity": "sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@aws-sdk/client-sso": "3.758.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/token-providers": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.758.0.tgz", + "integrity": "sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/core": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/credential-providers": { + "version": "3.768.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.768.0.tgz", + "integrity": "sha512-uEAtcdHArZxq7dbpgI4ofDclefNYnYWrT9bJn2Q6rf7VlQnoD37ptzVLQBLomXnRaBiQB/sRV2MJaugFqwOEQA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@aws-sdk/client-cognito-identity": "3.768.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/credential-provider-cognito-identity": "3.768.0", + "@aws-sdk/credential-provider-env": "3.758.0", + "@aws-sdk/credential-provider-http": "3.758.0", + "@aws-sdk/credential-provider-ini": "3.758.0", + "@aws-sdk/credential-provider-node": "3.758.0", + "@aws-sdk/credential-provider-process": "3.758.0", + "@aws-sdk/credential-provider-sso": "3.758.0", + "@aws-sdk/credential-provider-web-identity": "3.758.0", + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/core": "^3.1.5", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-providers/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz", + "integrity": "sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.734.0.tgz", + "integrity": "sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/types": "3.734.0", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.734.0.tgz", + "integrity": "sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.734.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.758.0.tgz", + "integrity": "sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@aws-sdk/core": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@smithy/core": "^3.1.5", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz", + "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.758.0", + "@aws-sdk/middleware-host-header": "3.734.0", + "@aws-sdk/middleware-logger": "3.734.0", + "@aws-sdk/middleware-recursion-detection": "3.734.0", + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/region-config-resolver": "3.734.0", + "@aws-sdk/types": "3.734.0", + "@aws-sdk/util-endpoints": "3.743.0", + "@aws-sdk/util-user-agent-browser": "3.734.0", + "@aws-sdk/util-user-agent-node": "3.758.0", + "@smithy/config-resolver": "^4.0.1", + "@smithy/core": "^3.1.5", + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/hash-node": "^4.0.1", + "@smithy/invalid-dependency": "^4.0.1", + "@smithy/middleware-content-length": "^4.0.1", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-retry": "^4.0.7", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/protocol-http": "^5.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.7", + "@smithy/util-defaults-mode-node": "^4.0.7", + "@smithy/util-endpoints": "^3.0.1", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz", + "integrity": "sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.734.0", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/region-config-resolver/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz", + "integrity": "sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/nested-clients": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/token-providers/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/types": { + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.734.0.tgz", + "integrity": "sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.743.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz", + "integrity": "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.734.0", + "@smithy/types": "^4.1.0", + "@smithy/util-endpoints": "^3.0.1", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.723.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.723.0.tgz", + "integrity": "sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.734.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.734.0.tgz", + "integrity": "sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-sdk/types": "3.734.0", + "@smithy/types": "^4.1.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.758.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.758.0.tgz", + "integrity": "sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/middleware-user-agent": "3.758.0", + "@aws-sdk/types": "3.734.0", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "node_modules/@babel/compat-data": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", - "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dev": true, "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.14.0" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/template": { + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", - "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.2", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, - "node_modules/@babel/types": { + "node_modules/@babel/helper-module-transforms": { "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true, - "license": "MIT" - }, - "node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "license": "MIT", "engines": { - "node": ">=0.1.90" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/config-validator": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", - "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@commitlint/types": "^19.0.3", - "ajv": "^8.11.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { - "node": ">=v18" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/execute-rule": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", - "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=v18" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/load": { - "version": "19.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.4.0.tgz", - "integrity": "sha512-I4lCWaEZYQJ1y+Y+gdvbGAx9pYPavqZAZ3/7/8BpWh+QjscAn8AjsUpLV2PycBsEx7gupq5gM4BViV9xwTIJuw==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "@commitlint/config-validator": "^19.0.3", - "@commitlint/execute-rule": "^19.0.0", - "@commitlint/resolve-extends": "^19.1.0", - "@commitlint/types": "^19.0.3", - "chalk": "^5.3.0", - "cosmiconfig": "^9.0.0", - "cosmiconfig-typescript-loader": "^5.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0" - }, "engines": { - "node": ">=v18" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/load/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/resolve-extends": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz", - "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==", + "node_modules/@babel/helpers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@commitlint/config-validator": "^19.0.3", - "@commitlint/types": "^19.0.3", - "global-directory": "^4.0.1", - "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { - "node": ">=v18" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/types": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", - "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "@types/conventional-commits-parser": "^5.0.0", - "chalk": "^5.3.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=v18" + "node": ">=6.9.0" } }, - "node_modules/@commitlint/types/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/@babel/parser": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", "dev": true, "license": "MIT", - "optional": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "dependencies": { + "@babel/types": "^7.25.2" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "license": "MIT", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@efstajas/versioned-parser": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@efstajas/versioned-parser/-/versioned-parser-0.1.4.tgz", - "integrity": "sha512-R/MUEOeMGvegThqacHCasp03RtE66szRqt9d6Qa+LI2lNweyV1SyAk66JlgRppoJHXwmcIDJ5hAUEws0g/Xx2Q==", - "license": "Apache-2.0" - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@babel/helper-plugin-utils": "^7.10.4" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": "*" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=10.10.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "*" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@babel/helper-plugin-utils": "^7.24.7" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, + "node_modules/@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "regenerator-runtime": "^0.14.0" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@babel/traverse": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", + "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } + "license": "MIT" }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.1.90" } }, - "node_modules/@jest/console/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@commitlint/config-validator": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", + "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "color-name": "~1.1.4" + "@commitlint/types": "^19.0.3", + "ajv": "^8.11.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=v18" } }, - "node_modules/@jest/console/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@commitlint/execute-rule": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", + "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": ">=8" + "node": ">=v18" } }, - "node_modules/@jest/console/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==", + "node_modules/@commitlint/load": { + "version": "19.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.4.0.tgz", + "integrity": "sha512-I4lCWaEZYQJ1y+Y+gdvbGAx9pYPavqZAZ3/7/8BpWh+QjscAn8AjsUpLV2PycBsEx7gupq5gM4BViV9xwTIJuw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "has-flag": "^4.0.0" + "@commitlint/config-validator": "^19.0.3", + "@commitlint/execute-rule": "^19.0.0", + "@commitlint/resolve-extends": "^19.1.0", + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^5.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" }, "engines": { - "node": ">=8" + "node": ">=v18" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@commitlint/load/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, + "optional": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@commitlint/resolve-extends": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz", + "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "color-convert": "^2.0.1" + "@commitlint/config-validator": "^19.0.3", + "@commitlint/types": "^19.0.3", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=v18" } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@commitlint/types": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", + "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" }, "engines": { - "node": ">=10" + "node": ">=v18" + } + }, + "node_modules/@commitlint/types/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@efstajas/versioned-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@efstajas/versioned-parser/-/versioned-parser-0.1.4.tgz", + "integrity": "sha512-R/MUEOeMGvegThqacHCasp03RtE66szRqt9d6Qa+LI2lNweyV1SyAk66JlgRppoJHXwmcIDJ5hAUEws0g/Xx2Q==", + "license": "Apache-2.0" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } + "license": "MIT" }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "*" } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "color-name": "~1.1.4" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=7.0.0" + "node": ">=10.10.0" } }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@jest/reporters/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==", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "license": "Apache-2.0", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "BSD-3-Clause" }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/@jest/transform/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==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { + "node_modules/@jest/console/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -1682,7 +2088,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/types/node_modules/chalk": { + "node_modules/@jest/console/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -1699,7 +2105,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/types/node_modules/color-convert": { + "node_modules/@jest/console/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==", @@ -1712,14 +2118,14 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/types/node_modules/color-name": { + "node_modules/@jest/console/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, - "node_modules/@jest/types/node_modules/has-flag": { + "node_modules/@jest/console/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==", @@ -1729,7 +2135,7 @@ "node": ">=8" } }, - "node_modules/@jest/types/node_modules/supports-color": { + "node_modules/@jest/console/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==", @@ -1742,297 +2148,1934 @@ "node": ">=8" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "license": "MIT" }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "engines": { + "node": ">=8" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.3.2" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 16" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "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/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz", + "integrity": "sha512-+ywrb0AqkfaYuhHs6LxKWgqbh3I72EpEgESCw37o+9qPx9WTCkgDm2B+eMrwehGtHBWHFU4GXvnSCNiFhhausg==", + "license": "MIT", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@noble/curves": { + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@redis/bloom": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/client": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz", + "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", + "yallist": "4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@redis/client/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/@redis/graph": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", + "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/json": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", + "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/search": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", + "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/time-series": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", + "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@rushstack/node-core-library": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.12.0.tgz", + "integrity": "sha512-QSwwzgzWoil1SCQse+yCHwlhRxNv2dX9siPnAb9zR/UmMhac4mjMrlMZpk64BlCeOFi1kJKgXRkihSwRMbboAQ==", + "license": "MIT", + "dependencies": { + "ajv": "~8.13.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", + "fs-extra": "~11.3.0", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.5.4" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@rushstack/node-core-library/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==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/@rushstack/terminal": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.15.1.tgz", + "integrity": "sha512-3vgJYwumcjoDOXU3IxZfd616lqOdmr8Ezj4OWgJZfhmiBK4Nh7eWcv8sU8N/HdzXcuHDXCRGn/6O2Q75QvaZMA==", + "license": "MIT", + "dependencies": { + "@rushstack/node-core-library": "5.12.0", + "supports-color": "~8.1.1" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/terminal/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@rushstack/terminal/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@rushstack/ts-command-line": { + "version": "4.23.6", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.6.tgz", + "integrity": "sha512-7WepygaF3YPEoToh4MAL/mmHkiIImQq3/uAkQX46kVoKTNOOlCtFGyNnze6OYuWw2o9rxsyrHVfIBKxq/am2RA==", + "license": "MIT", + "dependencies": { + "@rushstack/terminal": "0.15.1", + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "string-argv": "~0.3.1" + } + }, + "node_modules/@rushstack/ts-command-line/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/abort-controller/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/config-resolver": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz", + "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/core": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.5.tgz", + "integrity": "sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/middleware-serde": "^4.0.2", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-stream": "^4.1.2", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz", + "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz", + "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-base64": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/hash-node": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz", + "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz", + "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", + "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz", + "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.6.tgz", + "integrity": "sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^3.1.5", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-middleware": "^4.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.7.tgz", + "integrity": "sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/service-error-classification": "^4.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz", + "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz", + "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz", + "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/property-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz", + "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz", + "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz", + "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz", + "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/signature-v4": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz", + "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-uri-escape": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/smithy-client": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.6.tgz", + "integrity": "sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^3.1.5", + "@smithy/middleware-endpoint": "^4.0.6", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/url-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", + "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/querystring-parser": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-base64": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", + "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", + "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", + "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", + "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", + "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "tslib": "^2.6.2" }, "engines": { - "node": ">= 8" + "node": ">=18.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-config-provider/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.7.tgz", + "integrity": "sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/property-provider": "^4.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">= 8" + "node": ">=18.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-defaults-mode-browser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.7.tgz", + "integrity": "sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@smithy/config-resolver": "^4.0.1", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/smithy-client": "^4.1.6", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 8" + "node": ">=18.0.0" } }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } + "node_modules/@smithy/util-defaults-mode-node/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true }, - "node_modules/@redis/client": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz", - "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==", - "license": "MIT", + "node_modules/@smithy/util-endpoints": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz", + "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14" + "node": ">=18.0.0" } }, - "node_modules/@redis/client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "node_modules/@smithy/util-endpoints/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true }, - "node_modules/@redis/graph": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", - "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" + "node_modules/@smithy/util-hex-encoding": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", + "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@redis/json": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", - "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" + "node_modules/@smithy/util-hex-encoding/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-middleware": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", + "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@redis/search": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", - "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" + "node_modules/@smithy/util-middleware/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-retry": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz", + "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/service-error-classification": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@redis/time-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", - "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" + "node_modules/@smithy/util-retry/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-stream": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", + "integrity": "sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.3", + "@smithy/types": "^4.1.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" + "node_modules/@smithy/util-stream/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "type-detect": "4.0.8" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@smithy/util-uri-escape/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@smithy/util-utf8": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", + "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@smithy/util-buffer-from": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, + "node_modules/@smithy/util-utf8/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -2077,6 +4120,12 @@ "typescript": ">=4.7.0" } }, + "node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2122,6 +4171,12 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/bluebird": { + "version": "3.5.42", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.42.tgz", + "integrity": "sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==", + "license": "MIT" + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -2157,6 +4212,15 @@ "@types/node": "*" } }, + "node_modules/@types/continuation-local-storage": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@types/continuation-local-storage/-/continuation-local-storage-3.2.7.tgz", + "integrity": "sha512-Q7dPOymVpRG5Zpz90/o26+OAqOG2Sw+FED7uQmTrJNCF/JAPTylclZofMxZKd6W7g1BDPmT9/C/jX0ZcSNTQwQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/conventional-commits-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", @@ -2282,6 +4346,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", + "license": "MIT" + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -2365,6 +4435,18 @@ "@types/node": "*" } }, + "node_modules/@types/sequelize": { + "version": "4.28.20", + "resolved": "https://registry.npmjs.org/@types/sequelize/-/sequelize-4.28.20.tgz", + "integrity": "sha512-XaGOKRhdizC87hDgQ0u3btxzbejlF+t6Hhvkek1HyphqCI4y7zVBIVAGmuc4cWJqGpxusZ1RiBToHHnNK/Edlw==", + "license": "MIT", + "dependencies": { + "@types/bluebird": "*", + "@types/continuation-local-storage": "*", + "@types/lodash": "*", + "@types/validator": "*" + } + }, "node_modules/@types/serve-static": { "version": "1.15.7", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", @@ -2390,12 +4472,39 @@ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", "license": "MIT" }, + "node_modules/@types/umzug": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/umzug/-/umzug-2.3.9.tgz", + "integrity": "sha512-YIA3UL9MgOVP2RC7yF6z6Mrp1hrLFccDuXYxKuXdr/+Qqy8awWnDK1RHNy5Rp+sHQ7qwke85dp+SZTGfS+MqPg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/sequelize": "*", + "mongodb": "^4.1.4" + } + }, "node_modules/@types/validator": { "version": "13.12.0", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==", "license": "MIT" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -2618,6 +4727,16 @@ "dev": true, "license": "ISC" }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2677,9 +4796,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", - "optional": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -2691,6 +4808,37 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -3158,7 +5306,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -3242,6 +5389,13 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -3281,6 +5435,13 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "license": "MIT", + "optional": true + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -3295,7 +5456,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -3360,11 +5520,22 @@ "node-int64": "^0.4.0" } }, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "license": "Apache-2.0", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -3601,6 +5772,23 @@ "dev": true, "license": "MIT" }, + "node_modules/cli-color": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", + "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.64", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3786,6 +5974,16 @@ "node": ">=8" } }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/commitizen": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.0.tgz", @@ -3823,6 +6021,24 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", @@ -4046,9 +6262,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -4081,6 +6297,20 @@ "@commitlint/load": ">6.1.1" } }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -4379,6 +6609,48 @@ "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==", "license": "MIT" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4412,7 +6684,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4598,6 +6869,62 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -5045,6 +7372,22 @@ "node": ">=8" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -5166,6 +7509,17 @@ "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", "license": "MIT" }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -5280,6 +7634,16 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -5299,14 +7663,12 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -5323,7 +7685,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -5350,15 +7711,35 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], "license": "MIT", - "optional": true + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -5436,7 +7817,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -5579,6 +7959,36 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6131,7 +8541,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -6192,6 +8601,15 @@ "node": ">=4" } }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -6413,6 +8831,25 @@ "url": "https://opencollective.com/ioredis" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -6502,7 +8939,6 @@ "version": "2.15.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -6548,7 +8984,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6578,7 +9013,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -6613,7 +9047,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -6644,6 +9077,13 @@ "node": ">=8" } }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -6881,6 +9321,22 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jake": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", @@ -8753,6 +11209,81 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "license": "MIT" + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -8780,6 +11311,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -8811,9 +11348,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -8839,7 +11374,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -9123,6 +11657,16 @@ "yallist": "^3.0.2" } }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, "node_modules/luxon": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", @@ -9175,6 +11719,33 @@ "node": ">= 0.6" } }, + "node_modules/memoizee": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", + "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "es5-ext": "^0.10.64", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT", + "optional": true + }, "node_modules/merge": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", @@ -9202,7 +11773,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -9221,7 +11791,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -9299,6 +11868,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -9333,6 +11912,34 @@ "node": "*" } }, + "node_modules/mongodb": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz", + "integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==", + "license": "Apache-2.0", + "dependencies": { + "bson": "^4.7.2", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "@aws-sdk/credential-providers": "^3.186.0", + "@mongodb-js/saslprep": "^1.1.0" + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9401,6 +12008,13 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true, + "license": "ISC" + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", @@ -9484,6 +12098,22 @@ "node": "*" } }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9848,6 +12478,13 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9932,9 +12569,32 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -10119,7 +12779,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -10207,6 +12866,15 @@ "node": ">=8" } }, + "node_modules/pony-cause": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz", + "integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==", + "license": "0BSD", + "engines": { + "node": ">=12.0.0" + } + }, "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", @@ -10347,6 +13015,13 @@ "node": ">= 6" } }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -10371,7 +13046,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -10413,7 +13087,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -10580,9 +13253,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==", - "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=0.10.0" } @@ -10591,7 +13262,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", @@ -10676,7 +13346,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -10714,7 +13383,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -10942,6 +13610,83 @@ } } }, + "node_modules/sequelize-cli": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.2.tgz", + "integrity": "sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-color": "^2.0.3", + "fs-extra": "^9.1.0", + "js-beautify": "^1.14.5", + "lodash": "^4.17.21", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + }, + "bin": { + "sequelize": "lib/sequelize", + "sequelize-cli": "lib/sequelize" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sequelize-cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/sequelize-cli/node_modules/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/sequelize-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sequelize-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/sequelize-pool": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", @@ -11097,6 +13842,30 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11117,6 +13886,16 @@ "source-map": "^0.6.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -11130,7 +13909,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/stack-trace": { @@ -11190,6 +13968,15 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-format": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", @@ -11226,6 +14013,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", @@ -11288,6 +14091,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -11311,6 +14128,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -11328,7 +14158,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -11438,6 +14267,20 @@ "dev": true, "license": "MIT" }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -11472,7 +14315,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -11506,6 +14348,18 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/triple-beam": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", @@ -11765,6 +14619,13 @@ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "license": "0BSD" }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "dev": true, + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -12046,6 +14907,34 @@ "node": ">=0.8.0" } }, + "node_modules/umzug": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-3.8.2.tgz", + "integrity": "sha512-BEWEF8OJjTYVC56GjELeHl/1XjFejrD7aHzn+HldRJTx+pL1siBrKHZC8n4K/xL3bEzVA9o++qD1tK2CpZu4KA==", + "license": "MIT", + "dependencies": { + "@rushstack/ts-command-line": "^4.12.2", + "emittery": "^0.13.0", + "fast-glob": "^3.3.2", + "pony-cause": "^2.1.4", + "type-fest": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/umzug/node_modules/type-fest": { + "version": "4.37.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.37.0.tgz", + "integrity": "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -12078,7 +14967,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -12128,7 +15016,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -12218,6 +15105,28 @@ "defaults": "^1.0.3" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -12372,6 +15281,61 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -12528,9 +15492,9 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 3e5f86f..532e4a0 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,18 @@ "test": "jest --detectOpenHandles --config=jest.config.ts", "test:coverage": "jest --coverage", "build": "npm run build:contracts && tsc", + "clean": "rm -rf dist", "build:contracts": "./scripts/build-contracts.sh && ts-node ./scripts/codegen-any-chain-types.ts", "postbuild": "rm -rf ./dist/src/config/chainConfigs && cp -r ./src/config/chainConfigs ./dist/src/config/chainConfigs", + "check": "tsc --noEmit", "dev": "npx nodemon", "start": "node dist/src/index.js", - "check": "tsc --noEmit" + "sequelize": "ts-node --transpile-only node_modules/sequelize-cli/lib/sequelize", + "db:run-migrations": "ts-node scripts/run-migrations.ts", + "db:revert-migration": "ts-node scripts/revert-migration.ts", + "db:create-migration": "npm run sequelize migration:generate -- --migrations-path src/db/migrations", + "db:log-pending-migrations": "npm run sequelize -- db:migrate:status --migrations-path src/db/migrations --config dist/src/config/sequelizeConfig.js", + "dev:db:run-migrations": "npm run clean && npm run build && ts-node scripts/run-migrations.ts" }, "keywords": [], "author": "", @@ -27,7 +34,7 @@ }, "devDependencies": { "@typechain/ethers-v6": "^0.5.0", - "@types/bull-arena": "^3.0.7", + "@types/bull-arena": "^3.0.10", "@types/jest": "^29.5.11", "@types/node": "^20.5.9", "@types/pg": "^8.10.2", @@ -43,6 +50,7 @@ "jest": "^29.7.0", "nodemon": "^3.0.1", "prettier": "^3.0.3", + "sequelize-cli": "^6.6.2", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "typechain": "^8.3.1", @@ -50,8 +58,9 @@ }, "dependencies": { "@efstajas/versioned-parser": "^0.1.4", + "@types/umzug": "^2.3.9", "bee-queue": "^1.5.0", - "bull-arena": "^4.0.0", + "bull-arena": "^4.4.2", "dotenv": "^16.3.1", "dotenv-expand": "^11.0.6", "ethers": "^6.7.1", @@ -60,7 +69,8 @@ "pg": "^8.11.3", "redis": "^4.6.10", "sequelize": "^6.32.1", + "umzug": "^3.8.2", "winston": "^3.10.0", - "zod": "^3.22.2" + "zod": "^3.24.2" } } diff --git a/scripts/codegen-any-chain-types.ts b/scripts/codegen-any-chain-types.ts index 97b5a08..08a43be 100644 --- a/scripts/codegen-any-chain-types.ts +++ b/scripts/codegen-any-chain-types.ts @@ -40,7 +40,9 @@ function generateTypeImports(chainNames: string[]) { import { Drips as ${chainName}Drips } from './${chainName}/'; import { NftDriver as ${chainName}NftDriver } from './${chainName}/'; import { RepoDriver as ${chainName}RepoDriver } from './${chainName}/'; +import { RepoSubAccountDriver as ${chainName}RepoSubAccountDriver } from './${chainName}/'; import { AddressDriver as ${chainName}AddressDriver } from './${chainName}/'; +import { ImmutableSplitsDriver as ${chainName}ImmutableSplitsDriver } from './${chainName}/'; import { TypedContractEvent as ${chainName}TypedContractEvent } from './${chainName}/common'; import { TypedLogDescription as ${chainName}TypedLogDescription } from './${chainName}/common';`; } @@ -53,12 +55,16 @@ function generateAnyChainTypes(chainNames: string[]) { export type AnyChainDrips = ${chainNames.map((name) => `${name}Drips`).join(' | ')}; export type AnyChainNftDriver = ${chainNames.map((name) => `${name}NftDriver`).join(' | ')}; export type AnyChainRepoDriver = ${chainNames.map((name) => `${name}RepoDriver`).join(' | ')}; +export type AnyChainRepoSubAccountDriver = ${chainNames.map((name) => `${name}RepoSubAccountDriver`).join(' | ')}; export type AnyChainAddressDriver = ${chainNames.map((name) => `${name}AddressDriver`).join(' | ')}; +export type AnyChainImmutableSplitsDriver = ${chainNames.map((name) => `${name}ImmutableSplitsDriver`).join(' | ')}; export type AnyChainDripsFilters = ${chainNames.map((name) => `${name}Drips['filters']`).join(' & ')}; export type AnyChainNftDriverFilters = ${chainNames.map((name) => `${name}NftDriver['filters']`).join(' & ')}; export type AnyChainRepoDriverFilters = ${chainNames.map((name) => `${name}RepoDriver['filters']`).join(' & ')}; +export type AnyChainRepoSubAccountDriverFilters = ${chainNames.map((name) => `${name}RepoSubAccountDriver['filters']`).join(' & ')}; export type AnyChainAddressDriverFilters = ${chainNames.map((name) => `${name}AddressDriver['filters']`).join(' & ')}; +export type AnyChainImmutableSplitsDriverFilters = ${chainNames.map((name) => `${name}ImmutableSplitsDriver['filters']`).join(' & ')}; export type AnyChainTypedContractEvent = ${chainNames.map((name) => `${name}TypedContractEvent`).join(' | ')}; export type AnyChainTypedLogDescription = ${chainNames.map((name) => `${name}TypedLogDescription`).join(' | ')};`; @@ -70,7 +76,7 @@ function generateContractGetters() { return ` import type { Provider } from 'ethers'; -import { Drips__factory, NftDriver__factory, RepoDriver__factory, AddressDriver__factory } from './${process.env.NETWORK}'; +import { Drips__factory, NftDriver__factory, RepoDriver__factory, AddressDriver__factory, ImmutableSplitsDriver__factory, RepoSubAccountDriver__factory } from './${process.env.NETWORK}'; export const getDripsContract: (contractAddress: string, provider: Provider) => AnyChainDrips = (contractAddress, provider) => Drips__factory.connect( contractAddress, @@ -87,9 +93,19 @@ export const getRepoDriverContract: (contractAddress: string, provider: Provider provider ); +export const getRepoSubAccountDriverContract: (contractAddress: string, provider: Provider) => AnyChainRepoSubAccountDriver = (contractAddress, provider) => RepoSubAccountDriver__factory.connect( + contractAddress, + provider +); + export const getAddressDriverContract: (contractAddress: string, provider: Provider) => AnyChainAddressDriver = (contractAddress, provider) => AddressDriver__factory.connect( contractAddress, provider +); + +export const getImmutableSplitsDriverContract: (contractAddress: string, provider: Provider) => AnyChainImmutableSplitsDriver = (contractAddress, provider) => ImmutableSplitsDriver__factory.connect( + contractAddress, + provider );`; } diff --git a/scripts/revert-migration.ts b/scripts/revert-migration.ts new file mode 100644 index 0000000..bcda50a --- /dev/null +++ b/scripts/revert-migration.ts @@ -0,0 +1,59 @@ +/* eslint-disable no-console */ + +import { Sequelize } from 'sequelize'; +import { Umzug, SequelizeStorage } from 'umzug'; +import getSchema from '../src/utils/getSchema'; + +export async function revertLastMigration(): Promise { + const connectionString = process.env.POSTGRES_CONNECTION_STRING; + if (!connectionString) { + throw new Error( + "'POSTGRES_CONNECTION_STRING' environment variable is missing.", + ); + } + + const sequelize = new Sequelize(connectionString, { + dialect: 'postgres', + logging: false, + }); + + const schema = getSchema(); + + await sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`); + + const migrator = new Umzug({ + migrations: { + glob: './dist/src/db/migrations/*.js', // Migrations must be built before running. + }, + context: sequelize, + storage: new SequelizeStorage({ + sequelize, + schema, + tableName: 'sequelize_meta', + }), + logger: console, + }); + + try { + const reverted = await migrator.down(); + + if (reverted.length) { + console.info(`🔁 Reverted migration: ${reverted[0]?.name}`); + } else { + console.info( + 'No migration was reverted. The database is already at the base state.', + ); + } + } finally { + sequelize.close(); + } +} + +revertLastMigration().catch((error) => { + console.error(`❌ Migration revert error: ${error.message}`, { + stack: error.stack, + cause: (error as any).cause, + }); + + process.exitCode = 1; +}); diff --git a/scripts/run-migrations.ts b/scripts/run-migrations.ts new file mode 100644 index 0000000..8f03857 --- /dev/null +++ b/scripts/run-migrations.ts @@ -0,0 +1,65 @@ +/* eslint-disable no-console */ + +import { Sequelize } from 'sequelize'; +import { Umzug, SequelizeStorage } from 'umzug'; +import getSchema from '../src/utils/getSchema'; + +export async function runMigrations(): Promise { + const connectionString = process.env.POSTGRES_CONNECTION_STRING; + if (!connectionString) { + throw new Error( + "'POSTGRES_CONNECTION_STRING' environment variable is missing.", + ); + } + + const sequelize = new Sequelize(connectionString, { + dialect: 'postgres', + logging: false, + define: { + underscored: true, + }, + }); + + const schema = getSchema(); + + await sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`); + + const migrator = new Umzug({ + migrations: { + glob: './dist/src/db/migrations/*.js', // Migrations must be built before running. + }, + context: sequelize, + storage: new SequelizeStorage({ + sequelize, + schema, + tableName: 'sequelize_meta', + }), + logger: console, + }); + + try { + const migrations = await migrator.up(); + + if (migrations.length > 0) { + const appliedNames = migrations.map((m) => m.name).join(', '); + console.info( + `✅ Applied ${migrations.length} migration${migrations.length > 1 ? 's' : ''}:\n - ${appliedNames.split(', ').join('\n - ')}`, + ); + } else { + console.info( + 'No migrations were applied. The database is already up-to-date. If you expected migrations to be applied, ensure that you run "npm run build" before starting the server.', + ); + } + } finally { + sequelize.close(); + } +} + +runMigrations().catch((error) => { + console.error(`❌ Migration error: ${error.message}`, { + stack: error.stack, + cause: (error as any).cause, + }); + + process.exitCode = 1; +}); diff --git a/servers.json b/scripts/servers.json similarity index 100% rename from servers.json rename to scripts/servers.json diff --git a/src/abi/filecoin/ImmutableSplitsDriver.json b/src/abi/filecoin/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/filecoin/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/filecoin/RepoSubAccountDriver.json b/src/abi/filecoin/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/filecoin/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/goerli/ImmutableSplitsDriver.json b/src/abi/goerli/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/goerli/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/goerli/RepoSubAccountDriver.json b/src/abi/goerli/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/goerli/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/localtestnet/ImmutableSplitsDriver.json b/src/abi/localtestnet/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/localtestnet/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/localtestnet/RepoSubAccountDriver.json b/src/abi/localtestnet/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/localtestnet/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/mainnet/ImmutableSplitsDriver.json b/src/abi/mainnet/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/mainnet/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/mainnet/RepoSubAccountDriver.json b/src/abi/mainnet/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/mainnet/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/metis/ImmutableSplitsDriver.json b/src/abi/metis/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/metis/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/metis/RepoSubAccountDriver.json b/src/abi/metis/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/metis/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/optimism/ImmutableSplitsDriver.json b/src/abi/optimism/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/optimism/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/optimism/RepoSubAccountDriver.json b/src/abi/optimism/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/optimism/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/optimism_sepolia/ImmutableSplitsDriver.json b/src/abi/optimism_sepolia/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/optimism_sepolia/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/optimism_sepolia/RepoSubAccountDriver.json b/src/abi/optimism_sepolia/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/optimism_sepolia/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/polygon_amoy/ImmutableSplitsDriver.json b/src/abi/polygon_amoy/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/polygon_amoy/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/polygon_amoy/RepoSubAccountDriver.json b/src/abi/polygon_amoy/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/polygon_amoy/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/sepolia/ImmutableSplitsDriver.json b/src/abi/sepolia/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/sepolia/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/sepolia/RepoSubAccountDriver.json b/src/abi/sepolia/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/sepolia/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/zksync_era_sepolia/AddressDriver.json b/src/abi/zksync_era_sepolia/AddressDriver.json new file mode 100644 index 0000000..cc1b059 --- /dev/null +++ b/src/abi/zksync_era_sepolia/AddressDriver.json @@ -0,0 +1,414 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "drips_", "type": "address" }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "addr", "type": "address" } + ], + "name": "calcAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/zksync_era_sepolia/Drips.json b/src/abi/zksync_era_sepolia/Drips.json new file mode 100644 index 0000000..341b9f8 --- /dev/null +++ b/src/abi/zksync_era_sepolia/Drips.json @@ -0,0 +1,1221 @@ +[ + { + "inputs": [ + { "internalType": "uint32", "name": "cycleSecs_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "AccountMetadataEmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amt", + "type": "uint128" + } + ], + "name": "Collectable", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "collected", + "type": "uint128" + } + ], + "name": "Collected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "driverId", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oldDriverAddr", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newDriverAddr", + "type": "address" + } + ], + "name": "DriverAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "driverId", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "driverAddr", + "type": "address" + } + ], + "name": "DriverRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "receiver", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amt", + "type": "uint128" + } + ], + "name": "Given", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amt", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "receivableCycles", + "type": "uint32" + } + ], + "name": "ReceivedStreams", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "receiver", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amt", + "type": "uint128" + } + ], + "name": "Split", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "weight", + "type": "uint32" + } + ], + "name": "SplitsReceiverSeen", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "SplitsSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "senderId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "amt", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "bytes32[]", + "name": "streamsHistoryHashes", + "type": "bytes32[]" + } + ], + "name": "SqueezedStreams", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "name": "StreamReceiverSeen", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "streamsHistoryHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "balance", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxEnd", + "type": "uint32" + } + ], + "name": "StreamsSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amt", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [], + "name": "AMT_PER_SEC_EXTRA_DECIMALS", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "AMT_PER_SEC_MULTIPLIER", + "outputs": [{ "internalType": "uint160", "name": "", "type": "uint160" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DRIVER_ID_OFFSET", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_SPLITS_RECEIVERS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_STREAMS_RECEIVERS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_TOTAL_BALANCE", + "outputs": [{ "internalType": "uint128", "name": "", "type": "uint128" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOTAL_SPLITS_WEIGHT", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "name": "balanceAt", + "outputs": [ + { "internalType": "uint128", "name": "balance", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "erc20", "type": "address" } + ], + "name": "balances", + "outputs": [ + { + "internalType": "uint128", + "name": "streamsBalance", + "type": "uint128" + }, + { "internalType": "uint128", "name": "splitsBalance", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" } + ], + "name": "collectable", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cycleSecs", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint32", "name": "driverId", "type": "uint32" } + ], + "name": "driverAddress", + "outputs": [ + { "internalType": "address", "name": "driverAddr", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "hashSplits", + "outputs": [ + { "internalType": "bytes32", "name": "receiversHash", "type": "bytes32" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "hashStreams", + "outputs": [ + { "internalType": "bytes32", "name": "streamsHash", "type": "bytes32" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "oldStreamsHistoryHash", + "type": "bytes32" + }, + { "internalType": "bytes32", "name": "streamsHash", "type": "bytes32" }, + { "internalType": "uint32", "name": "updateTime", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEnd", "type": "uint32" } + ], + "name": "hashStreamsHistory", + "outputs": [ + { + "internalType": "bytes32", + "name": "streamsHistoryHash", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minAmtPerSec", + "outputs": [{ "internalType": "uint160", "name": "", "type": "uint160" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextDriverId", + "outputs": [ + { "internalType": "uint32", "name": "driverId", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" } + ], + "name": "receivableStreamsCycles", + "outputs": [ + { "internalType": "uint32", "name": "cycles", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint32", "name": "maxCycles", "type": "uint32" } + ], + "name": "receiveStreams", + "outputs": [ + { "internalType": "uint128", "name": "receivedAmt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint32", "name": "maxCycles", "type": "uint32" } + ], + "name": "receiveStreamsResult", + "outputs": [ + { "internalType": "uint128", "name": "receivableAmt", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "driverAddr", "type": "address" } + ], + "name": "registerDriver", + "outputs": [ + { "internalType": "uint32", "name": "driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + } + ], + "name": "split", + "outputs": [ + { + "internalType": "uint128", + "name": "collectableAmt", + "type": "uint128" + }, + { "internalType": "uint128", "name": "splitAmt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "uint128", "name": "amount", "type": "uint128" } + ], + "name": "splitResult", + "outputs": [ + { + "internalType": "uint128", + "name": "collectableAmt", + "type": "uint128" + }, + { "internalType": "uint128", "name": "splitAmt", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "splitsHash", + "outputs": [ + { "internalType": "bytes32", "name": "currSplitsHash", "type": "bytes32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" } + ], + "name": "splittable", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint256", "name": "senderId", "type": "uint256" }, + { "internalType": "bytes32", "name": "historyHash", "type": "bytes32" }, + { + "components": [ + { + "internalType": "bytes32", + "name": "streamsHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "updateTime", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEnd", "type": "uint32" } + ], + "internalType": "struct StreamsHistory[]", + "name": "streamsHistory", + "type": "tuple[]" + } + ], + "name": "squeezeStreams", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint256", "name": "senderId", "type": "uint256" }, + { "internalType": "bytes32", "name": "historyHash", "type": "bytes32" }, + { + "components": [ + { + "internalType": "bytes32", + "name": "streamsHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "updateTime", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEnd", "type": "uint32" } + ], + "internalType": "struct StreamsHistory[]", + "name": "streamsHistory", + "type": "tuple[]" + } + ], + "name": "squeezeStreamsResult", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" } + ], + "name": "streamsState", + "outputs": [ + { "internalType": "bytes32", "name": "streamsHash", "type": "bytes32" }, + { + "internalType": "bytes32", + "name": "streamsHistoryHash", + "type": "bytes32" + }, + { "internalType": "uint32", "name": "updateTime", "type": "uint32" }, + { "internalType": "uint128", "name": "balance", "type": "uint128" }, + { "internalType": "uint32", "name": "maxEnd", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint32", "name": "driverId", "type": "uint32" }, + { "internalType": "address", "name": "newDriverAddr", "type": "address" } + ], + "name": "updateDriverAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "uint256", "name": "amt", "type": "uint256" } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/zksync_era_sepolia/ImmutableSplitsDriver.json b/src/abi/zksync_era_sepolia/ImmutableSplitsDriver.json new file mode 100644 index 0000000..9879574 --- /dev/null +++ b/src/abi/zksync_era_sepolia/ImmutableSplitsDriver.json @@ -0,0 +1,358 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "_drips", "type": "address" }, + { "internalType": "uint32", "name": "_driverId", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "receiversHash", + "type": "bytes32" + } + ], + "name": "CreatedSplits", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "createSplits", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextAccountId", + "outputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSplitsWeight", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/zksync_era_sepolia/NftDriver.json b/src/abi/zksync_era_sepolia/NftDriver.json new file mode 100644 index 0000000..a764c14 --- /dev/null +++ b/src/abi/zksync_era_sepolia/NftDriver.json @@ -0,0 +1,728 @@ +[ + { + "inputs": [ + { "internalType": "contract Drips", "name": "drips_", "type": "address" }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "minter", "type": "address" }, + { "internalType": "uint64", "name": "salt", "type": "uint64" } + ], + "name": "calcTokenIdWithSalt", + "outputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "getApproved", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "operator", "type": "address" } + ], + "name": "isApprovedForAll", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "minter", "type": "address" }, + { "internalType": "uint64", "name": "salt", "type": "uint64" } + ], + "name": "isSaltUsed", + "outputs": [{ "internalType": "bool", "name": "isUsed", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "mint", + "outputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint64", "name": "salt", "type": "uint64" }, + { "internalType": "address", "name": "to", "type": "address" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "mintWithSalt", + "outputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "nextTokenId", + "outputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "safeMint", + "outputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint64", "name": "salt", "type": "uint64" }, + { "internalType": "address", "name": "to", "type": "address" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "safeMintWithSalt", + "outputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "operator", "type": "address" }, + { "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" } + ], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "tokenURI", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/abi/zksync_era_sepolia/RepoDriver.json b/src/abi/zksync_era_sepolia/RepoDriver.json new file mode 100644 index 0000000..7fecd71 --- /dev/null +++ b/src/abi/zksync_era_sepolia/RepoDriver.json @@ -0,0 +1,966 @@ +[ + { + "inputs": [ + { + "internalType": "contract Drips", + "name": "drips_", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "internalType": "uint32", + "name": "driverId_", + "type": "uint32" + }, + { + "internalType": "contract IAutomate", + "name": "gelatoAutomate_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "userFundsUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "commonFundsUsed", + "type": "uint256" + } + ], + "name": "GelatoFeePaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract GelatoTasksOwner", + "name": "gelatoTasksOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "taskId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "ipfsCid", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxRequestsPerBlock", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxRequestsPer31Days", + "type": "uint32" + } + ], + "name": "GelatoTaskUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum Forge", + "name": "forge", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "OwnerUpdateRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "UserFundsDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address payable", + "name": "receiver", + "type": "address" + } + ], + "name": "UserFundsWithdrawn", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum Forge", + "name": "forge", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "internalType": "address", + "name": "transferTo", + "type": "address" + } + ], + "name": "collect", + "outputs": [ + { + "internalType": "uint128", + "name": "amt", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "commonFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "depositUserFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { + "internalType": "contract Drips", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gelatoAutomate", + "outputs": [ + { + "internalType": "contract IAutomate", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gelatoTasksOwner", + "outputs": [ + { + "internalType": "contract GelatoTasksOwner", + "name": "tasksOwner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receiver", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "internalType": "uint128", + "name": "amt", + "type": "uint128" + } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "isPauser", + "outputs": [ + { + "internalType": "bool", + "name": "isAddrPauser", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum Forge", + "name": "forge", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "requestUpdateOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "requestUpdateOwnerGasPenalty", + "outputs": [ + { + "internalType": "uint256", + "name": "gasPenalty", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "erc20", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { + "internalType": "int128", + "name": "balanceDelta", + "type": "int128" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { + "internalType": "uint32", + "name": "maxEndHint1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxEndHint2", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transferTo", + "type": "address" + } + ], + "name": "setStreams", + "outputs": [ + { + "internalType": "int128", + "name": "realBalanceDelta", + "type": "int128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "ipfsCid", + "type": "string" + }, + { + "internalType": "uint32", + "name": "maxRequestsPerBlock", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRequestsPer31Days", + "type": "uint32" + } + ], + "name": "updateGelatoTask", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "accountId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "updateOwnerByGelato", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "userFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "receiver", + "type": "address" + } + ], + "name": "withdrawUserFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawnAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/src/abi/zksync_era_sepolia/RepoSubAccountDriver.json b/src/abi/zksync_era_sepolia/RepoSubAccountDriver.json new file mode 100644 index 0000000..05e3034 --- /dev/null +++ b/src/abi/zksync_era_sepolia/RepoSubAccountDriver.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "contract RepoDriver", + "name": "repoDriver_", + "type": "address" + }, + { "internalType": "address", "name": "forwarder", "type": "address" }, + { "internalType": "uint32", "name": "driverId_", "type": "uint32" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "currentAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdminProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "PauserRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPausers", + "outputs": [ + { + "internalType": "address[]", + "name": "pausersList", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "calcAccountId", + "outputs": [ + { + "internalType": "uint256", + "name": "resultAccountId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "collect", + "outputs": [ + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "drips", + "outputs": [ + { "internalType": "contract Drips", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "driverId", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "bytes32", "name": "key", "type": "bytes32" }, + { "internalType": "bytes", "name": "value", "type": "bytes" } + ], + "internalType": "struct AccountMetadata[]", + "name": "accountMetadata", + "type": "tuple[]" + } + ], + "name": "emitAccountMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint256", "name": "receiver", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { "internalType": "uint128", "name": "amt", "type": "uint128" } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "grantPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "isPauser", + "outputs": [ + { "internalType": "bool", "name": "isAddrPauser", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "forwarder", "type": "address" } + ], + "name": "isTrustedForwarder", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" } + ], + "name": "ownerOf", + "outputs": [ + { "internalType": "address", "name": "owner", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "proposeNewAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proposedAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repoDriver", + "outputs": [ + { "internalType": "contract RepoDriver", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pauser", "type": "address" } + ], + "name": "revokePauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "uint32", "name": "weight", "type": "uint32" } + ], + "internalType": "struct SplitsReceiver[]", + "name": "receivers", + "type": "tuple[]" + } + ], + "name": "setSplits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { "internalType": "contract IERC20", "name": "erc20", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "currReceivers", + "type": "tuple[]" + }, + { "internalType": "int128", "name": "balanceDelta", "type": "int128" }, + { + "components": [ + { "internalType": "uint256", "name": "accountId", "type": "uint256" }, + { + "internalType": "StreamConfig", + "name": "config", + "type": "uint256" + } + ], + "internalType": "struct StreamReceiver[]", + "name": "newReceivers", + "type": "tuple[]" + }, + { "internalType": "uint32", "name": "maxEndHint1", "type": "uint32" }, + { "internalType": "uint32", "name": "maxEndHint2", "type": "uint32" }, + { "internalType": "address", "name": "transferTo", "type": "address" } + ], + "name": "setStreams", + "outputs": [ + { "internalType": "int128", "name": "realBalanceDelta", "type": "int128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/src/config/appSettings.schema.ts b/src/config/appSettings.schema.ts new file mode 100644 index 0000000..7911d0f --- /dev/null +++ b/src/config/appSettings.schema.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; +import { SUPPORTED_NETWORKS } from '../core/constants'; + +const loggingConfigSchema = z.object({ + level: z.enum(['trace', 'debug', 'info', 'warn', 'error']).default('info'), + format: z.enum(['json', 'pretty']).default('pretty'), + destination: z.enum(['console', 'file']).default('console'), + filename: z.string().optional(), +}); + +export const appSettingsSchema = z.object({ + network: z.enum(SUPPORTED_NETWORKS), + primaryRpcUrl: z.string().url(), + primaryRpcAccessToken: z.string().optional(), + fallbackRpcUrl: z.string().url().optional(), + fallbackRpcAccessToken: z.string().optional(), + logger: loggingConfigSchema, + pollingInterval: z.number().positive().optional().default(5000), + chunkSize: z.number().positive().optional().default(1000), + confirmations: z.number().optional().default(1), + ipfsGatewayUrl: z + .string() + .url() + .optional() + .default('https://drips.mypinata.cloud'), + queueUiPort: z.number().positive().optional().default(3000), + redisConnectionString: z.string(), + postgresConnectionString: z.string(), + shouldStartMonitoringUI: z.boolean().optional().default(false), + cacheInvalidationEndpoint: z.string(), + visibilityThresholdBlockNumber: z.number().optional().default(0), + ecosystemDeployer: z.string().optional(), +}); + +export type LoggingConfig = z.infer; +export type AppSettings = z.infer; diff --git a/src/config/appSettings.ts b/src/config/appSettings.ts index dc27170..6de8d46 100644 --- a/src/config/appSettings.ts +++ b/src/config/appSettings.ts @@ -1,35 +1,67 @@ import dotenv from 'dotenv'; import dotenvExpand from 'dotenv-expand'; +import { ZodError } from 'zod'; +import { appSettingsSchema, type AppSettings } from './appSettings.schema'; dotenvExpand.expand(dotenv.config()); -function missingEnvVar(name: string): never { - throw new Error(`Missing ${name} in .env file.`); -} +function loadAppSettings(): AppSettings { + const appSettings = { + network: process.env.NETWORK, + primaryRpcUrl: process.env.PRIMARY_RPC_URL, + fallbackRpcUrl: process.env.FALLBACK_RPC_URL, + primaryRpcAccessToken: process.env.PRIMARY_RPC_ACCESS_TOKEN, + fallbackRpcAccessToken: process.env.FALLBACK_RPC_ACCESS_TOKEN, + logger: { + level: process.env.LOG_LEVEL, + format: process.env.LOG_FORMAT, + destination: process.env.LOG_DESTINATION, + filename: process.env.LOG_FILE, + }, + pollingInterval: process.env.POLLING_INTERVAL + ? parseInt(process.env.POLLING_INTERVAL, 10) + : undefined, + chunkSize: process.env.CHUNK_SIZE + ? parseInt(process.env.CHUNK_SIZE, 10) + : undefined, + confirmations: process.env.CONFIRMATIONS + ? parseInt(process.env.CONFIRMATIONS, 10) + : undefined, + ipfsGatewayUrl: process.env.IPFS_GATEWAY_URL, + queueUiPort: process.env.MONITORING_UI_PORT + ? parseInt(process.env.MONITORING_UI_PORT, 10) + : undefined, + redisConnectionString: process.env.REDIS_CONNECTION_STRING, + postgresConnectionString: process.env.POSTGRES_CONNECTION_STRING, + shouldStartMonitoringUI: + (process.env.SHOULD_START_MONITORING_UI as unknown as string) === 'true', + cacheInvalidationEndpoint: process.env.CACHE_INVALIDATION_ENDPOINT, + visibilityThresholdBlockNumber: process.env + .VISIBILITY_THRESHOLD_BLOCK_NUMBER + ? parseInt(process.env.VISIBILITY_THRESHOLD_BLOCK_NUMBER, 10) + : undefined, + ecosystemDeployer: process.env.ECOSYSTEM_DEPLOYER, + }; + + try { + return appSettingsSchema.parse(appSettings); + } catch (error) { + if (error instanceof ZodError) { + const details = error.errors + .map((err) => { + const path = err.path.join('.'); + const { message } = err; + return `- ${path ? `'${path}': ` : ''}${message}`; + }) + .join('\n'); -const appSettings = { - network: process.env.NETWORK || missingEnvVar('NETWORK.'), - primaryRpcUrl: - process.env.PRIMARY_RPC_URL || missingEnvVar('PRIMARY_RPC_URL is not set.'), - fallbackRpcUrl: process.env.FALLBACK_RPC_URL, - primaryRpcAccessToken: process.env.PRIMARY_RPC_ACCESS_TOKEN, - fallbackRpcAccessToken: process.env.FALLBACK_RPC_ACCESS_TOKEN, - logLevel: process.env.LOG_LEVEL || 'debug', - pollingInterval: Number(process.env.POLLING_INTERVAL) || 5000, - chunkSize: Number(process.env.CHUNK_SIZE) || 1000, - confirmations: process.env.CONFIRMATIONS - ? Number(process.env.CONFIRMATIONS) - : 1, - ipfsGatewayUrl: - process.env.IPFS_GATEWAY_URL || 'https://drips.mypinata.cloud', - monitoringUiPort: process.env.MONITORING_UI_PORT || 3000, - redisConnectionString: process.env.REDIS_CONNECTION_STRING, - postgresConnectionString: process.env.POSTGRES_CONNECTION_STRING, - shouldStartMonitoringUI: - (process.env.SHOULD_START_MONITORING_UI as unknown as string) !== 'false', - cacheInvalidationEndpoint: process.env.CACHE_INVALIDATION_ENDPOINT, - visibilityThresholdBlockNumber: - Number(process.env.VISIBILITY_THRESHOLD_BLOCK_NUMBER) || 0, -} as const; + throw new Error(`Invalid configuration:\n\n${details}\n`); + } + + throw error; + } +} +// Singleton app settings instance +const appSettings = loadAppSettings(); export default appSettings; diff --git a/src/config/chainConfigs/localtestnet.json b/src/config/chainConfigs/localtestnet.json index beb8a16..12087ab 100644 --- a/src/config/chainConfigs/localtestnet.json +++ b/src/config/chainConfigs/localtestnet.json @@ -8,6 +8,9 @@ "repoDriver": { "address": "0x971e08fc533d2A5f228c7944E511611dA3B56B24" }, + "repoSubAccountDriver": { + "address": "0xB8743C2bB8DF7399273aa7EE4cE8d4109Bec327F" + }, "drips": { "address": "0x7CBbD3FdF9E5eb359E6D9B12848c5Faa81629944" }, diff --git a/src/config/chainConfigs/optimism_sepolia.json b/src/config/chainConfigs/optimism_sepolia.json index 341db77..9cc9523 100644 --- a/src/config/chainConfigs/optimism_sepolia.json +++ b/src/config/chainConfigs/optimism_sepolia.json @@ -14,6 +14,9 @@ "repoDriver": { "address": "0xa71bdf410D48d4AA9aE1517A69D7E1Ef0c179b2B" }, + "repoSubAccountDriver": { + "address": "0x5cEB4E59A1f91caC75017163B4D0663F155e9B77" + }, "addressDriver": { "address": "0x70E1E1437AeFe8024B6780C94490662b45C3B567" } diff --git a/src/config/chainConfigs/zksync_era_sepolia.json b/src/config/chainConfigs/zksync_era_sepolia.json new file mode 100644 index 0000000..93a1520 --- /dev/null +++ b/src/config/chainConfigs/zksync_era_sepolia.json @@ -0,0 +1,24 @@ +{ + "network": "zksync_era_sepolia", + "block": 5023276, + "contracts": { + "drips": { + "address": "0xe190AB5e92F937751c5ECec9416349666e8C54b9" + }, + "repoDriver": { + "address": "0x8bDC23877A23Ce59fEF1712A1486810d9A6E2B94" + }, + "repoSubAccountDriver": { + "address": "0x0000000000000000000000000000000000000000" + }, + "addressDriver": { + "address": "0x0557b6BA791A24df0Fa6167E1Dc304F403ee777A" + }, + "nftDriver": { + "address": "0xB6B3b6a24cB9A9E2De4c6f2Ea54870E411bFc30d" + }, + "immutableSplitsDriver": { + "address": "0x47A51E1b8BcB885D0fE6b47d514EEf1E28F0ae95" + } + } +} diff --git a/src/config/sequelizeConfig.ts b/src/config/sequelizeConfig.ts new file mode 100644 index 0000000..e02efd9 --- /dev/null +++ b/src/config/sequelizeConfig.ts @@ -0,0 +1,12 @@ +/* eslint-disable import/no-import-module-exports */ +import appSettings from './appSettings'; + +const config = { + url: appSettings.postgresConnectionString, + dialect: 'postgres', + define: { + schema: appSettings.network, + }, +}; + +module.exports = config; diff --git a/src/core/LogManager.ts b/src/core/LogManager.ts deleted file mode 100644 index b7441d6..0000000 --- a/src/core/LogManager.ts +++ /dev/null @@ -1,118 +0,0 @@ -import type { UUID } from 'crypto'; -import type { Model } from 'sequelize'; -import logger from './logger'; - -export type ChangedProperties = { - [key: string]: { old: any; new: any }; -}; - -export default class LogManager { - private readonly _logs: string[] = []; - private readonly _requestId: UUID; - - public constructor(requestId: UUID) { - this._requestId = requestId; - } - - public static nameOfType(type: { new (): T }) { - return type.prototype.constructor.name; - } - - public static getChangedProperties( - instance: T, - ): ChangedProperties | null { - const changedKeys = instance.changed(); - - if (!changedKeys) { - return null; - } - - const changedProps: ChangedProperties = {}; - - if (changedKeys && changedKeys.length > 0) { - for (const key of changedKeys) { - changedProps[key] = { - old: instance.previous(key), - new: instance.get(key), - }; - } - } - - return changedProps; - } - - public appendFindOrCreateLog( - type: { new (): T }, - isCreated: boolean, - id: string, - ): this { - this._logs.push( - `${ - isCreated - ? `Created a new ${LogManager.nameOfType(type)} with ID ${id}.` - : `${LogManager.nameOfType( - type, - )} with ID ${id} already exists. Probably it was created by another event. Skipping creation.` - }`, - ); - - return this; - } - - public appendIsLatestEventLog(): this { - this._logs.push( - 'Handled event is the latest event. Models will be updated.', - ); - - return this; - } - - public appendLog(log: string): this { - this._logs.push(log); - - return this; - } - - public appendUpdateLog( - instance: T, - type: { new (): T }, - id: string, - ): this { - this._logs.push( - `Updated ${LogManager.nameOfType(type)} with ID ${id}:${ - LogManager.getChangedProperties(instance) - ? `\n\t - ${JSON.stringify( - LogManager.getChangedProperties(instance), - )}` - : '' - }`, - ); - - return this; - } - - public logAllInfo(): void { - LogManager.logRequestInfo( - `Completed successfully. The following happened:\n\t - ${this._logs.join( - '\n\t - ', - )}`, - this._requestId, - ); - } - - public static logRequestDebug(message: string, requestId: UUID): void { - logger.debug(`${message}`, { requestId }); - } - - public static logRequestInfo(message: string, requestId: UUID): void { - logger.info(`${message}`, { requestId }); - } - - public static logRequestWarn(message: string, requestId: UUID): void { - logger.warn(`${message}`, { requestId }); - } - - public static logRequestError(message: string, requestId: UUID): void { - logger.error(`${message}`, { requestId }); - } -} diff --git a/src/core/ScopedLogger.ts b/src/core/ScopedLogger.ts new file mode 100644 index 0000000..75ee23b --- /dev/null +++ b/src/core/ScopedLogger.ts @@ -0,0 +1,161 @@ +import type { Model } from 'sequelize'; +import logger from './logger'; + +export type ChangedProperties = { + [key: string]: { old: any; new: any }; +}; + +/** + * ScopedLogger buffers context-aware messages for a single handler/request. + */ +export default class ScopedLogger { + private readonly _handler: string; + private readonly _requestId: string; + private readonly _buffer: string[] = []; + + constructor(handler: string, requestId: string) { + this._handler = handler; + this._requestId = requestId; + } + + /** + * Buffer a plain text message. + */ + public bufferMessage(message: string): this { + this._buffer.push(`[${this._requestId}] ${message}`); + return this; + } + + /** + * Buffer a creation event for a Sequelize model instance. + */ + public bufferCreation(opts: { + input: T; + type: abstract new (...args: any[]) => T; + id: string; + }): this { + const typeName = this._getClassName(opts.type); + this._buffer.push( + `[${this._requestId}] Created new ${typeName} (ID: ${opts.id}).`, + ); + + return this; + } + + /** + * Buffer an update event for a Sequelize model instance, including change details. + */ + public bufferUpdate(opts: { + input: T; + type: abstract new (...args: any[]) => T; + id: string; + }): this { + const changes = this._extractChanges(opts.input) ?? {}; + const changeKeys = Object.keys(changes); + const typeName = this._getClassName(opts.type); + + let summary: string; + if (changeKeys.length > 0) { + summary = `Updated ${typeName} with ${changeKeys.length} change${changeKeys.length > 1 ? 's' : ''}.`; + } else { + summary = `No changes detected on ${typeName}.`; + } + + const formattedChanges = this._formatChanges(changes); + this._buffer.push( + `[${this._requestId}] Processed ${typeName} (ID: ${opts.id}) — ${summary}${formattedChanges}`, + ); + + return this; + } + + /** + * Immediately log a single message at the given level (bypassing buffer). + */ + public log( + message: string, + level: 'info' | 'debug' | 'warn' | 'error' = 'info', + ): void { + const formatted = `[${this._requestId}] ${message}`; + switch (level) { + case 'debug': + logger.debug(formatted); + break; + case 'warn': + logger.warn(formatted); + break; + case 'error': + logger.error(formatted); + break; + case 'info': + default: + logger.info(formatted); + break; + } + } + + /** + * Flush all buffered messages as a single multi-line log entry. + */ + public flush(level: 'info' | 'debug' | 'warn' | 'error' = 'info'): void { + const content = this._buffer.map((line) => `\t - ${line}`).join('\n'); + const message = `[${this._requestId}] ${this._handler} completed successfully:\n${content}`; + + switch (level) { + case 'debug': + logger.debug(message); + break; + case 'warn': + logger.warn(message); + break; + case 'error': + logger.error(message); + break; + case 'info': + default: + logger.info(message); + break; + } + } + + private _formatChanges(changes: ChangedProperties | null): string { + if (!changes || Object.keys(changes).length === 0) { + return ''; + } + + const safe = Object.fromEntries( + Object.entries(changes).map(([key, { old, new: _new }]) => [ + key, + { + old: old === undefined ? null : old, + new: _new === undefined ? null : _new, + }, + ]), + ) as ChangedProperties; + + return `\n\tChanged properties:\n${JSON.stringify(safe, null, 2) + .split('\n') + .map((line) => `\t ${line}`) + .join('\n')}.`; + } + + private _extractChanges( + instance: T, + ): ChangedProperties | null { + const changedKeys = instance.changed(); + if (!changedKeys) return null; + + return changedKeys.reduce((acc, key) => { + acc[key] = { + old: instance.previous(key), + new: instance.get(key), + }; + + return acc; + }, {} as ChangedProperties); + } + + private _getClassName(ctor: abstract new (...args: any[]) => T): string { + return ctor.prototype.constructor.name; + } +} diff --git a/src/core/constants.ts b/src/core/constants.ts index c66ae43..3fe5170 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -1,4 +1,4 @@ -import { ethers } from 'ethers'; +import { encodeBytes32String } from 'ethers'; import { DataTypes } from 'sequelize'; export const SUPPORTED_NETWORKS = [ @@ -10,40 +10,45 @@ export const SUPPORTED_NETWORKS = [ 'filecoin', 'metis', 'optimism', + 'zksync_era_sepolia', ] as const; -export const FORGES_MAP = { - 0: 'GitHub', - 1: 'GitLab', -} as const; - export const DRIPS_CONTRACTS = [ 'drips', 'nftDriver', 'repoDriver', + 'repoSubAccountDriver', 'addressDriver', 'immutableSplitsDriver', ] as const; -export const DRIPS_APP_USER_METADATA_KEY = ethers.encodeBytes32String('ipfs'); +export const DRIPS_APP_USER_METADATA_KEY = encodeBytes32String('ipfs'); export const COMMON_EVENT_INIT_ATTRIBUTES = { transactionHash: { - type: DataTypes.STRING, - allowNull: false, primaryKey: true, + allowNull: false, + type: DataTypes.STRING, }, logIndex: { - type: DataTypes.INTEGER, - allowNull: false, primaryKey: true, + allowNull: false, + type: DataTypes.INTEGER, }, blockTimestamp: { - type: DataTypes.DATE, allowNull: false, + type: DataTypes.DATE, }, blockNumber: { + allowNull: false, type: DataTypes.INTEGER, + }, + createdAt: { allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, }, } as const; diff --git a/src/core/contractClients.ts b/src/core/contractClients.ts index b5f1cc8..1e0ff55 100644 --- a/src/core/contractClients.ts +++ b/src/core/contractClients.ts @@ -3,12 +3,14 @@ import { getAddressDriverContract, getNftDriverContract, getRepoDriverContract, + getRepoSubAccountDriverContract, } from '../../contracts/contract-types'; import loadChainConfig from '../config/loadChainConfig'; import getProvider from './getProvider'; const { contracts } = loadChainConfig(); -const { drips, addressDriver, nftDriver, repoDriver } = contracts; +const { drips, addressDriver, nftDriver, repoDriver, repoSubAccountDriver } = + contracts; const provider = getProvider(); @@ -28,3 +30,8 @@ export const repoDriverContract = getRepoDriverContract( repoDriver.address, provider, ); + +export const repoSubAccountDriverContract = getRepoSubAccountDriverContract( + repoSubAccountDriver.address, + provider, +); diff --git a/src/core/environment.d.ts b/src/core/environment.d.ts deleted file mode 100644 index 1c5ca93..0000000 --- a/src/core/environment.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { SupportedNetwork } from './types'; - -declare global { - namespace NodeJS { - interface ProcessEnv { - NETWORK: SupportedNetwork; - PRIMARY_RPC_URL: string; - PRIMARY_RPC_ACCESS_TOKEN: string | undefined; - FALLBACK_RPC_URL: string | undefined; - FALLBACK_RPC_ACCESS_TOKEN: string | undefined; - NODE_ENV: 'development' | 'production'; - LOG_LEVEL: 'debug' | 'info' | 'warn' | 'error'; - POLLING_INTERVAL: number; - IPFS_GATEWAY_URL: string; - MONITORING_UI_PORT: number; - REDIS_CONNECTION_STRING: string; - POSTGRES_CONNECTION_STRING: string; - SHOULD_START_MONITORING_UI: boolean; - SHOULD_PROCESS_PAST_EVENTS: boolean; - CACHE_INVALIDATION_ENDPOINT: string; - VISIBILITY_THRESHOLD_BLOCK_NUMBER: number; - } - } -} - -export {}; diff --git a/src/core/logger.ts b/src/core/logger.ts index dabf505..364387b 100644 --- a/src/core/logger.ts +++ b/src/core/logger.ts @@ -1,35 +1,60 @@ import winston from 'winston'; +import type { LoggingConfig } from '../config/appSettings.schema'; import appSettings from '../config/appSettings'; -const format = winston.format.combine( - winston.format.timestamp(), - winston.format.colorize(), - winston.format.errors({ stack: true }), - winston.format.printf( - ({ timestamp, level, message, requestId }) => - `${timestamp} ${level}${requestId ? ` [${requestId}]` : ''}: ${message}`, - ), -); +function createLogger(config: LoggingConfig): winston.Logger { + const formats = [ + winston.format.timestamp(), + winston.format.errors({ stack: true }), + ]; -const developmentLogger = winston.createLogger({ - level: appSettings.logLevel, - format, - transports: [new winston.transports.Console()], -}); + // Add pretty printing for console if configured. + if (config.format === 'pretty' && config.destination === 'console') { + formats.push( + winston.format.colorize(), + winston.format.printf((info: winston.Logform.TransformableInfo) => { + const { level, message, timestamp, metadata, ...rest } = info; + const metaStr = + metadata || Object.keys(rest).length + ? `\n${JSON.stringify(metadata || rest, null, 2)}` + : ''; -const productionLogger = winston.createLogger({ - level: appSettings.logLevel, - format, - transports: [ - new winston.transports.Console(), - // Logs are stored on Railways, so we don't need to store them locally. - // new winston.transports.File({ - // filename: `logs/${new Date().toISOString().slice(0, 10)}.log`, - // }), - ], -}); + return `${timestamp} ${level}: ${message}${metaStr}`; + }), + ); + } else { + formats.push(winston.format.json()); + } -const logger = - appSettings.network === 'mainnet' ? productionLogger : developmentLogger; + const transports: winston.transport[] = []; + // Configure transport based on destination. + if (config.destination === 'file' && config.filename) { + transports.push( + new winston.transports.File({ + filename: config.filename, + level: config.level, + format: winston.format.combine(...formats), + maxFiles: 7, + maxsize: 10 * 1024 * 1024, // 10MB + tailable: true, + }), + ); + } else { + transports.push( + new winston.transports.Console({ + level: config.level, + format: winston.format.combine(...formats), + }), + ); + } + + return winston.createLogger({ + level: config.level, + transports, + }); +} + +// Singleton logger instance +const logger = createLogger(appSettings.logger); export default logger; diff --git a/src/core/splitRules.ts b/src/core/splitRules.ts new file mode 100644 index 0000000..8ea7320 --- /dev/null +++ b/src/core/splitRules.ts @@ -0,0 +1,149 @@ +import type { + RepoDriverId, + NftDriverId, + ImmutableSplitsDriverId, + AddressDriverId, + RepoDeadlineDriverId, +} from './types'; + +const SPLIT_RULES = Object.freeze([ + // Project Rules + { + senderAccountType: 'project', + receiverAccountType: 'address', + relationshipType: 'project_maintainer', + }, + { + senderAccountType: 'project', + receiverAccountType: 'project', + relationshipType: 'project_dependency', + }, + { + senderAccountType: 'project', + receiverAccountType: 'address', + relationshipType: 'project_dependency', + }, + { + senderAccountType: 'project', + receiverAccountType: 'drip_list', + relationshipType: 'project_dependency', + }, + + // Drip List Rules + { + senderAccountType: 'drip_list', + receiverAccountType: 'address', + relationshipType: 'drip_list_receiver', + }, + { + senderAccountType: 'drip_list', + receiverAccountType: 'drip_list', + relationshipType: 'drip_list_receiver', + }, + { + senderAccountType: 'drip_list', + receiverAccountType: 'project', + relationshipType: 'drip_list_receiver', + }, + + // Ecosystem Main Account Rules + { + senderAccountType: 'ecosystem_main_account', + receiverAccountType: 'project', + relationshipType: 'ecosystem_receiver', + }, + { + senderAccountType: 'ecosystem_main_account', + receiverAccountType: 'sub_list', + relationshipType: 'sub_list_link', + }, + + // Sub List Rules + { + senderAccountType: 'sub_list', + receiverAccountType: 'address', + relationshipType: 'sub_list_link', + }, + { + senderAccountType: 'sub_list', + receiverAccountType: 'drip_list', + relationshipType: 'sub_list_link', + }, + { + senderAccountType: 'sub_list', + receiverAccountType: 'project', + relationshipType: 'sub_list_link', + }, + { + senderAccountType: 'sub_list', + receiverAccountType: 'sub_list', + relationshipType: 'sub_list_link', + }, +] as const); + +type EntityIdMap = { + project: RepoDriverId; + drip_list: NftDriverId; + ecosystem_main_account: NftDriverId; + sub_list: ImmutableSplitsDriverId; + deadline: RepoDeadlineDriverId; + address: AddressDriverId; +}; + +export type RelationshipType = (typeof SPLIT_RULES)[number]['relationshipType']; +export type AccountType = + | (typeof SPLIT_RULES)[number]['senderAccountType'] + | (typeof SPLIT_RULES)[number]['receiverAccountType']; + +type SplitRuleFromRaw = R extends { + senderAccountType: infer S extends keyof EntityIdMap; + receiverAccountType: infer T extends keyof EntityIdMap; + relationshipType: string; +} + ? { + senderAccountType: S; + senderAccountId: EntityIdMap[S]; + receiverAccountType: T; + receiverAccountId: EntityIdMap[T]; + relationshipType: R['relationshipType']; + } + : never; + +export type SplitReceiverShape = SplitRuleFromRaw< + (typeof SPLIT_RULES)[number] +> & { + weight: number; + blockTimestamp: Date; + splitsToRepoDriverSubAccount?: boolean; +}; + +export const ACCOUNT_TYPES = Array.from( + new Set( + SPLIT_RULES.flatMap((rule) => [ + rule.senderAccountType, + rule.receiverAccountType, + ]), + ), +); + +export const RELATIONSHIP_TYPES = Array.from( + new Set(SPLIT_RULES.map((rule) => rule.relationshipType)), +) as (typeof SPLIT_RULES)[number]['relationshipType'][]; + +export const ACCOUNT_TYPE_TO_METADATA_RECEIVER_TYPE: Record< + AccountType, + string +> = { + project: 'repoDriver', + drip_list: 'dripList', + ecosystem_main_account: 'ecosystem', + sub_list: 'subList', + address: 'address', +}; + +export const METADATA_RECEIVER_TYPE_TO_ACCOUNT_TYPE = Object.fromEntries( + Object.entries(ACCOUNT_TYPE_TO_METADATA_RECEIVER_TYPE).map(([key, value]) => [ + value, + key, + ]), +) as Record; diff --git a/src/core/types.ts b/src/core/types.ts index 5c386e7..35b1f2e 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -1,14 +1,5 @@ -import type { AnyVersion } from '@efstajas/versioned-parser'; import type { Model, Sequelize } from 'sequelize'; -import type { - nftDriverAccountMetadataParser, - repoDriverAccountMetadataParser, -} from '../metadata/schemas'; -import type { - DRIPS_CONTRACTS, - FORGES_MAP, - SUPPORTED_NETWORKS, -} from './constants'; +import type { DRIPS_CONTRACTS, SUPPORTED_NETWORKS } from './constants'; export type KnownAny = any; @@ -17,14 +8,24 @@ export type IpfsHash = string & { __brand: 'IpfsHash' }; export type AddressDriverId = string & { __brand: 'AddressDriverId'; }; - export type NftDriverId = string & { __brand: 'NftDriverId' }; -export type DripListId = NftDriverId; - export type RepoDriverId = string & { __brand: 'RepoDriverId' }; -export type ProjectId = RepoDriverId; - -export type AccountId = AddressDriverId | NftDriverId | RepoDriverId; +export type ImmutableSplitsDriverId = string & { + __brand: 'ImmutableSplitsDriverId'; +}; +export type RepoDeadlineDriverId = string & { + __brand: 'RepoDeadlineDriverId'; +}; +export type RepoSubAccountDriverId = string & { + __brand: 'RepoSubAccountDriverId'; +}; +export type AccountId = + | AddressDriverId + | NftDriverId + | RepoDriverId + | ImmutableSplitsDriverId + | RepoDeadlineDriverId + | RepoSubAccountDriverId; export type Address = string & { __brand: 'Address' }; @@ -46,8 +47,6 @@ export type SupportedNetwork = (typeof SUPPORTED_NETWORKS)[number]; export type DbSchema = SupportedNetwork & { __brand: 'DbSchema' }; -export type Forge = ValuesOf; - export type DripsContract = (typeof DRIPS_CONTRACTS)[number]; export type ChainConfig = { @@ -64,31 +63,6 @@ export type ModelStaticMembers = { initialize(sequelize: Sequelize): void; }; -type ArrayElement = - ArrayType extends readonly (infer ElementType)[] ? ElementType : never; - -export type Dependency = ArrayElement< - | AnyVersion['splits']['dependencies'] - | AnyVersion['projects'] ->; - -export type DependencyOfProjectType = { - type: 'repoDriver'; - accountId: ProjectId; - source: { - forge: 'github'; - repoName: string; - ownerName: string; - url: string; - }; - weight: number; -}; - -export enum DependencyType { - ProjectDependency = 'ProjectDependency', - DripListDependency = 'DripListDependency', -} - export type StreamHistoryHashes = string & { __type: 'StreamHistoryHashes'; }; diff --git a/src/db/database.ts b/src/db/database.ts index a9d0ace..3f409a9 100644 --- a/src/db/database.ts +++ b/src/db/database.ts @@ -1,138 +1,41 @@ import { Sequelize } from 'sequelize'; import logger from '../core/logger'; -import { getRegisteredModels, registerModels } from './modelRegistration'; -import { - AddressDriverSplitReceiverModel, - DripListModel, - DripListSplitReceiverModel, - GitProjectModel, - RepoDriverSplitReceiverModel, -} from '../models'; import appSettings from '../config/appSettings'; -import unreachableError from '../utils/unreachableError'; - -const { postgresConnectionString } = appSettings; +import { getRegisteredModels, registerModels } from './modelRegistration'; -export const dbConnection = new Sequelize(`${postgresConnectionString}`, { - dialect: 'postgres', - logging: false, - timezone: 'UTC', -}); +export const dbConnection = new Sequelize( + appSettings.postgresConnectionString, + { + dialect: 'postgres', + logging: false, + timezone: 'UTC', + pool: { + max: 15, + acquire: 30000, + idle: 10000, + }, + }, +); export async function connectToDb(): Promise { - logger.info('Initializing database...'); - - await authenticate(); - registerModels(); - await initializeEntities(); - defineAssociations(); - - await dbConnection.sync(); - - logger.info('Database initialized.'); -} - -async function authenticate(): Promise { try { await dbConnection.authenticate(); - logger.info('Connection has been established successfully.'); - - const schema = `"${( - appSettings.network || - unreachableError('Missing network in app settings.') - ).replace(/"/g, '""')}"`; + registerModels(); + await initializeEntities(); - await dbConnection.query(`CREATE SCHEMA IF NOT EXISTS ${schema};`); + logger.info('Connected to the database.'); + } catch (error) { + logger.error('Failed to connect to the database.', error); - await dbConnection.authenticate(); - } catch (error: any) { - logger.error( - `Unable to connect to the database: ${error} in ${error.stack}`, - ); throw error; } } async function initializeEntities(): Promise { - try { - logger.info('Initializing database schema...'); - - const promises = getRegisteredModels().map(async (Model) => { - Model.initialize(dbConnection); - }); - - await Promise.all(promises); - - logger.info('Database schema initialized.'); - } catch (error: any) { - logger.error(`Unable to initialize the database schema: ${error}.`); - throw error; - } -} - -function defineAssociations() { - // One-to-Many: A project can fund multiple address splits. - GitProjectModel.hasMany(AddressDriverSplitReceiverModel, { - foreignKey: 'funderProjectId', - }); - AddressDriverSplitReceiverModel.belongsTo(GitProjectModel, { - foreignKey: 'funderProjectId', - }); - - // One-to-Many: A project can fund multiple project splits. - GitProjectModel.hasMany(RepoDriverSplitReceiverModel, { - foreignKey: 'funderProjectId', - }); - RepoDriverSplitReceiverModel.belongsTo(GitProjectModel, { - foreignKey: 'funderProjectId', - }); - - // One-to-Many: A project can fund multiple drip list splits. - GitProjectModel.hasMany(DripListSplitReceiverModel, { - foreignKey: 'funderProjectId', - }); - DripListSplitReceiverModel.belongsTo(GitProjectModel, { - foreignKey: 'funderProjectId', - }); - - // One-to-One: A RepoDriverSplitReceiver represents/is a project. - GitProjectModel.hasOne(RepoDriverSplitReceiverModel, { - foreignKey: 'fundeeProjectId', - }); - RepoDriverSplitReceiverModel.belongsTo(GitProjectModel, { - foreignKey: 'fundeeProjectId', - }); - - // One-to-Many: A drip list can fund multiple address splits. - DripListModel.hasMany(AddressDriverSplitReceiverModel, { - foreignKey: 'funderDripListId', - }); - AddressDriverSplitReceiverModel.belongsTo(DripListModel, { - foreignKey: 'funderDripListId', - }); - - // One-to-Many: A drip list can fund multiple project splits. - DripListModel.hasMany(RepoDriverSplitReceiverModel, { - foreignKey: 'funderDripListId', - }); - RepoDriverSplitReceiverModel.belongsTo(DripListModel, { - foreignKey: 'funderDripListId', - }); + logger.info('Initializing database schema...'); - // One-to-Many: A drip list can fund multiple drip list splits. - DripListModel.hasMany(DripListSplitReceiverModel, { - foreignKey: 'funderDripListId', - }); - DripListSplitReceiverModel.belongsTo(DripListModel, { - foreignKey: 'funderDripListId', - }); + getRegisteredModels().map((Model) => Model.initialize(dbConnection)); - // One-to-One: A DripListSplitReceiverModel represents/is a drip list. - DripListModel.hasOne(DripListSplitReceiverModel, { - foreignKey: 'fundeeDripListId', - }); - DripListSplitReceiverModel.belongsTo(DripListModel, { - foreignKey: 'fundeeDripListId', - }); + logger.info('Database schema initialized.'); } diff --git a/src/db/migrations/20250414133746-initial_create.ts b/src/db/migrations/20250414133746-initial_create.ts new file mode 100644 index 0000000..6edc89e --- /dev/null +++ b/src/db/migrations/20250414133746-initial_create.ts @@ -0,0 +1,1030 @@ +import { DataTypes, literal, Op } from 'sequelize'; +import type { DataType, QueryInterface } from 'sequelize'; +import getSchema from '../../utils/getSchema'; +import type { DbSchema } from '../../core/types'; +import { COMMON_EVENT_INIT_ATTRIBUTES } from '../../core/constants'; + +export async function up({ context: sequelize }: any): Promise { + const schema = getSchema(); + const queryInterface: QueryInterface = sequelize.getQueryInterface(); + + await queryInterface.sequelize.query( + `CREATE SCHEMA IF NOT EXISTS ${schema};`, + ); + + await queryInterface.sequelize.query(` + CREATE TYPE ${schema}.account_type AS ENUM ( + 'project', + 'drip_list', + 'ecosystem_main_account', + 'sub_list', + 'deadline', + 'address' + ); + `); + + await queryInterface.sequelize.query(` + CREATE TYPE ${schema}.relationship_type AS ENUM ( + 'project_dependency', + 'project_maintainer', + 'drip_list_receiver', + 'ecosystem_receiver', + 'sub_list_link' + ); + `); + + await queryInterface.sequelize.query(` + CREATE TYPE ${schema}.project_verification_status AS ENUM ( + 'claimed', + 'unclaimed', + 'pending_metadata' + ); + `); + + await queryInterface.sequelize.query(` + CREATE TYPE ${schema}.forges AS ENUM ( + 'github', + 'gitlab' + ); + `); + + await createSplitReceiversTable(queryInterface, schema); + await createAccountMetadataEventsTable(queryInterface, schema); + await createProjectsTable(queryInterface, schema); + await createDripListsTable(queryInterface, schema); + await createEcosystemMainAccountsTable(queryInterface, schema); + await createTransferEventsTable(queryInterface, schema); + await createSubListsEventsTable(queryInterface, schema); + await createLastIndexedBlockTable(queryInterface, schema); + await createGivenEventsTable(queryInterface, schema); + await createSplitEventsTable(queryInterface, schema); + await createSqueezedStreamsEventsTable(queryInterface, schema); + await createStreamReceiverSeenEventsTable(queryInterface, schema); + await createStreamsSetEventsTable(queryInterface, schema); + await createSplitsSetEventsTable(queryInterface, schema); + await createOwnerUpdatedEventsTable(queryInterface, schema); +} + +async function createOwnerUpdatedEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `owner_updated_events`, + }, + transformFieldNamesToSnakeCase({ + owner: { + allowNull: false, + type: DataTypes.STRING, + }, + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); +} + +async function createSplitsSetEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `splits_set_events`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + receiversHash: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); +} + +async function createStreamsSetEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `streams_set_events`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + erc20: { + allowNull: false, + type: DataTypes.STRING, + }, + receiversHash: { + allowNull: false, + type: DataTypes.STRING, + }, + streamsHistoryHash: { + allowNull: false, + type: DataTypes.STRING, + }, + balance: { + allowNull: false, + type: DataTypes.STRING, + }, + maxEnd: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `streams_set_events`, + }, + transformFieldArrayToSnakeCase(['receiversHash']), + { + name: 'idx_streams_set_events_receiversHash', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `streams_set_events`, + }, + transformFieldArrayToSnakeCase(['accountId']), + { + name: 'idx_streams_set_events_accountId', + }, + ); +} + +async function createStreamReceiverSeenEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `stream_receiver_seen_events`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + config: { + allowNull: false, + type: DataTypes.STRING, + }, + receiversHash: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `stream_receiver_seen_events`, + }, + transformFieldArrayToSnakeCase(['accountId']), + { + name: 'idx_stream_receiver_seen_events_accountId', + }, + ); +} + +async function createSqueezedStreamsEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `squeezed_streams_events`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + erc20: { + allowNull: false, + type: DataTypes.STRING, + }, + senderId: { + allowNull: false, + type: DataTypes.STRING, + }, + amount: { + allowNull: false, + type: DataTypes.STRING, + }, + streamsHistoryHashes: { + allowNull: false, + type: DataTypes.TEXT, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); +} + +async function createSplitEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `split_events`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + receiver: { + allowNull: false, + type: DataTypes.STRING, + }, + erc20: { + allowNull: false, + type: DataTypes.STRING, + }, + amt: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `split_events`, + }, + transformFieldArrayToSnakeCase(['receiver']), + { + name: 'idx_split_events_receiver', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `split_events`, + }, + transformFieldArrayToSnakeCase(['accountId', 'receiver']), + { + name: 'idx_split_events_accountId_receiver', + }, + ); +} + +async function createGivenEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `given_events`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + receiver: { + allowNull: false, + type: DataTypes.STRING, + }, + erc20: { + allowNull: false, + type: DataTypes.STRING, + }, + amt: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `given_events`, + }, + transformFieldArrayToSnakeCase(['accountId']), + { + name: 'idx_given_events_accountId', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `given_events`, + }, + transformFieldArrayToSnakeCase(['receiver']), + { + name: 'idx_given_events_receiver', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `given_events`, + }, + transformFieldArrayToSnakeCase(['erc20']), + { + name: 'idx_given_events_erc20', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `given_events`, + }, + transformFieldArrayToSnakeCase(['transactionHash', 'logIndex']), + { + name: 'idx_given_events_transactionHash_logIndex', + }, + ); +} + +async function createLastIndexedBlockTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `last_indexed_block`, + }, + transformFieldNamesToSnakeCase({ + id: { + primaryKey: true, + autoIncrement: true, + type: DataTypes.INTEGER, + }, + blockNumber: { + unique: true, + allowNull: false, + type: DataTypes.BIGINT, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }), + ); +} + +async function createSubListsEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `sub_lists`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + parentAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + parentAccountType: { + allowNull: false, + type: literal(`${schema}.account_type`).val as unknown as DataType, + }, + rootAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + rootAccountType: { + allowNull: false, + type: literal(`${schema}.account_type`).val as unknown as DataType, + }, + lastProcessedIpfsHash: { + allowNull: false, + type: DataTypes.TEXT, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `sub_lists`, + }, + transformFieldArrayToSnakeCase(['accountId']), + { + name: 'idx_sub_lists_account_id', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `sub_lists`, + }, + transformFieldArrayToSnakeCase(['parentAccountId']), + { + name: 'idx_sub_lists_parent_account_id', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `sub_lists`, + }, + transformFieldArrayToSnakeCase(['rootAccountId']), + { + name: 'idx_sub_lists_root_account_id', + }, + ); +} + +async function createDripListsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `drip_lists`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + ownerAddress: { + allowNull: false, + type: DataTypes.STRING, + }, + ownerAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + name: { + allowNull: true, + type: DataTypes.STRING, + }, + latestVotingRoundId: { + allowNull: true, + type: DataTypes.UUID, + }, + description: { + allowNull: true, + type: DataTypes.TEXT, + }, + creator: { + allowNull: true, + type: DataTypes.STRING, + }, + previousOwnerAddress: { + allowNull: true, + type: DataTypes.STRING, + }, + isVisible: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + lastProcessedIpfsHash: { + allowNull: false, + type: DataTypes.TEXT, + }, + lastProcessedVersion: { + allowNull: false, + type: DataTypes.BIGINT, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `drip_lists`, + }, + transformFieldArrayToSnakeCase(['ownerAddress']), + { + name: 'idx_drip_lists_owner_address', + }, + ); +} + +async function createEcosystemMainAccountsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `ecosystem_main_accounts`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + ownerAddress: { + allowNull: false, + type: DataTypes.STRING, + }, + ownerAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + name: { + allowNull: true, + type: DataTypes.STRING, + }, + description: { + allowNull: true, + type: DataTypes.TEXT, + }, + creator: { + allowNull: true, + type: DataTypes.STRING, + }, + previousOwnerAddress: { + allowNull: true, + type: DataTypes.STRING, + }, + isVisible: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + lastProcessedIpfsHash: { + allowNull: false, + type: DataTypes.TEXT, + }, + lastProcessedVersion: { + allowNull: false, + type: DataTypes.BIGINT, + }, + avatar: { + allowNull: false, + type: DataTypes.STRING, + }, + color: { + allowNull: false, + type: DataTypes.STRING, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `ecosystem_main_accounts`, + }, + transformFieldArrayToSnakeCase(['ownerAddress']), + { + name: 'idx_ecosystem_main_accounts_owner_address', + }, + ); +} + +async function createProjectsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `projects`, + }, + transformFieldNamesToSnakeCase({ + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + isVisible: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + name: { + allowNull: true, + type: DataTypes.STRING, + }, + verificationStatus: { + allowNull: false, + type: literal(`${schema}.project_verification_status`) + .val as unknown as DataType, + }, + ownerAddress: { + allowNull: true, + type: DataTypes.STRING, + }, + ownerAccountId: { + allowNull: true, + type: DataTypes.STRING, + }, + forge: { + allowNull: true, + type: literal(`${schema}.forges`).val as unknown as DataType, + }, + url: { + allowNull: true, + type: DataTypes.STRING, + }, + emoji: { + allowNull: true, + type: DataTypes.STRING, + }, + avatarCid: { + allowNull: true, + type: DataTypes.STRING, + }, + color: { + allowNull: true, + type: DataTypes.STRING, + }, + lastProcessedIpfsHash: { + allowNull: true, + type: DataTypes.TEXT, + }, + lastProcessedVersion: { + allowNull: false, + type: DataTypes.STRING, + }, + claimedAt: { + allowNull: true, + type: DataTypes.DATE, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `projects`, + }, + transformFieldArrayToSnakeCase(['ownerAddress']), + { + name: 'idx_projects_owner_address', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `projects`, + }, + transformFieldArrayToSnakeCase(['verificationStatus']), + { + name: 'idx_projects_verification_status', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `projects`, + }, + transformFieldArrayToSnakeCase(['url']), + { + name: 'idx_projects_url', + }, + ); +} + +async function createAccountMetadataEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `account_metadata_emitted_events`, + }, + transformFieldNamesToSnakeCase({ + key: { + allowNull: false, + type: DataTypes.STRING, + }, + value: { + allowNull: false, + type: DataTypes.STRING, + }, + accountId: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `account_metadata_emitted_events`, + }, + transformFieldArrayToSnakeCase(['accountId']), + { + name: 'idx_account_metadata_emitted_events_accountId', + }, + ); +} + +async function createTransferEventsTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `transfer_events`, + }, + transformFieldNamesToSnakeCase({ + tokenId: { + allowNull: false, + type: DataTypes.STRING, + }, + from: { + allowNull: false, + type: DataTypes.STRING, + }, + to: { + allowNull: false, + type: DataTypes.STRING, + }, + ...COMMON_EVENT_INIT_ATTRIBUTES, + }), + ); +} + +async function createSplitReceiversTable( + queryInterface: QueryInterface, + schema: DbSchema, +) { + await queryInterface.createTable( + { + schema, + tableName: `splits_receivers`, + }, + transformFieldNamesToSnakeCase({ + id: { + primaryKey: true, + autoIncrement: true, + type: DataTypes.INTEGER, + }, + receiverAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + receiverAccountType: { + allowNull: false, + type: literal(`${schema}.account_type`).val as unknown as DataType, + }, + senderAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + senderAccountType: { + allowNull: false, + type: literal(`${schema}.account_type`).val as unknown as DataType, + }, + relationshipType: { + allowNull: false, + type: literal(`${schema}.relationship_type`).val as unknown as DataType, + }, + splitsToRepoDriverSubAccount: { + type: DataTypes.BOOLEAN, + allowNull: true, + }, + weight: { + type: DataTypes.INTEGER, + allowNull: false, + }, + blockTimestamp: { + type: DataTypes.DATE, + allowNull: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + }, + }), + ); + + await queryInterface.addIndex( + { + schema, + tableName: `splits_receivers`, + }, + transformFieldArrayToSnakeCase(['receiverAccountId', 'senderAccountId']), + { + name: 'idx_splits_receivers_receiver_sender', + }, + ); + await queryInterface.addIndex( + { + schema, + tableName: `splits_receivers`, + }, + transformFieldArrayToSnakeCase(['senderAccountId', 'receiverAccountId']), + { + name: 'idx_splits_receivers_sender_receiver', + }, + ); + + await queryInterface.addConstraint(`${getSchema()}.splits_receivers`, { + type: 'check', + name: 'chk_splits_receivers_project_splits_to_repo_driver_sub_account', + fields: ['receiver_account_type', 'splits_to_repo_driver_sub_account'], + where: { + [Op.or]: [ + { + receiver_account_type: 'project', + splits_to_repo_driver_sub_account: { + [Op.not]: null, + }, + }, + { + receiver_account_type: { + [Op.ne]: 'project', + }, + splits_to_repo_driver_sub_account: null, + }, + ], + }, + }); +} + +export async function down({ context: sequelize }: any): Promise { + const schema = getSchema(); + const queryInterface: QueryInterface = sequelize.getQueryInterface(); + + await queryInterface.dropTable({ + schema, + tableName: `owner_updated_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `splits_set_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `streams_set_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `stream_receiver_seen_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `squeezed_streams_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `split_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `given_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `sub_lists`, + }); + await queryInterface.dropTable({ + schema, + tableName: `drip_lists`, + }); + await queryInterface.dropTable({ + schema, + tableName: `ecosystem_main_accounts`, + }); + await queryInterface.dropTable({ + schema, + tableName: `projects`, + }); + await queryInterface.dropTable({ + schema, + tableName: `account_metadata_emitted_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `transfer_events`, + }); + await queryInterface.dropTable({ + schema, + tableName: `splits_receivers`, + }); + await queryInterface.dropTable({ + schema, + tableName: `last_indexed_block`, + }); + + await queryInterface.sequelize.query(` + DROP TYPE IF EXISTS ${schema}.account_type; + `); + + await queryInterface.sequelize.query(` + DROP TYPE IF EXISTS ${schema}.relationship_type; + `); + + await queryInterface.sequelize.query(` + DROP TYPE IF EXISTS ${schema}.project_verification_status; + `); + + await queryInterface.sequelize.query(` + DROP TYPE IF EXISTS ${schema}.forges; + `); +} + +export function camelToSnake(str: string): string { + return str + .replace(/([A-Z])/g, '_$1') + .replace(/^_/, '') + .toLowerCase(); +} + +export function transformFieldNamesToSnakeCase>( + fields: T, +): Record { + return Object.fromEntries( + Object.entries(fields).map(([key, value]) => [camelToSnake(key), value]), + ); +} + +export function transformFieldArrayToSnakeCase(fields: string[]): string[] { + return fields.map(camelToSnake); +} diff --git a/src/db/modelRegistration.ts b/src/db/modelRegistration.ts index e6f567e..5dc3768 100644 --- a/src/db/modelRegistration.ts +++ b/src/db/modelRegistration.ts @@ -1,22 +1,21 @@ import type { ModelStaticMembers } from '../core/types'; import { AccountMetadataEmittedEventModel, - AddressDriverSplitReceiverModel, DripListModel, - DripListSplitReceiverModel, - GitProjectModel, - OwnerUpdateRequestedEventModel, - OwnerUpdatedEventModel, - RepoDriverSplitReceiverModel, + ProjectModel, TransferEventModel, GivenEventModel, - SplitsSetEventModel, StreamsSetEventModel, StreamReceiverSeenEventModel, + LastIndexedBlockModel, + SplitEventModel, + SqueezedStreamsEventModel, + SubListModel, + EcosystemMainAccountModel, + SplitsReceiverModel, + OwnerUpdatedEventModel, } from '../models'; -import _LastIndexedBlockModel from '../models/_LastIndexedBlockModel'; -import SplitEventModel from '../models/SplitEventModel'; -import SqueezedStreamsEventModel from '../models/SqueezedStreamsEventModel'; +import SplitsSetEventModel from '../models/SplitsSetEventModel'; const REGISTERED_MODELS: ModelStaticMembers[] = []; @@ -29,21 +28,20 @@ export function getRegisteredModels(): ModelStaticMembers[] { } export function registerModels(): void { - registerModel(_LastIndexedBlockModel); + registerModel(LastIndexedBlockModel); + registerModel(SubListModel); + registerModel(ProjectModel); registerModel(DripListModel); registerModel(GivenEventModel); registerModel(SplitEventModel); - registerModel(GitProjectModel); registerModel(TransferEventModel); - registerModel(StreamsSetEventModel); + registerModel(SplitsReceiverModel); registerModel(SplitsSetEventModel); + registerModel(StreamsSetEventModel); registerModel(OwnerUpdatedEventModel); + registerModel(EcosystemMainAccountModel); registerModel(SqueezedStreamsEventModel); - registerModel(DripListSplitReceiverModel); registerModel(StreamReceiverSeenEventModel); - registerModel(RepoDriverSplitReceiverModel); - registerModel(OwnerUpdateRequestedEventModel); - registerModel(AddressDriverSplitReceiverModel); registerModel(AccountMetadataEmittedEventModel); } diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/AccountMetadataEmittedEventHandler.ts b/src/eventHandlers/AccountMetadataEmittedEvent/AccountMetadataEmittedEventHandler.ts index 32975a6..2abfcc1 100644 --- a/src/eventHandlers/AccountMetadataEmittedEvent/AccountMetadataEmittedEventHandler.ts +++ b/src/eventHandlers/AccountMetadataEmittedEvent/AccountMetadataEmittedEventHandler.ts @@ -1,159 +1,233 @@ -import type { AccountMetadataEmittedEvent } from '../../../contracts/CURRENT_NETWORK/Drips'; +import type { AnyVersion } from '@efstajas/versioned-parser'; +import { toUtf8String } from 'ethers'; import type { AccountId } from '../../core/types'; - import EventHandlerBase from '../../events/EventHandlerBase'; import { DRIPS_APP_USER_METADATA_KEY } from '../../core/constants'; -import handleGitProjectMetadata from './gitProject/handleGitProjectMetadata'; -import LogManager from '../../core/LogManager'; +import handleProjectMetadata from './handlers/handleProjectMetadata'; import { + isImmutableSplitsDriverId, isNftDriverId, isRepoDriverId, - toAccountId, + convertToAccountId, + convertToRepoDriverId, + convertToNftDriverId, + convertToImmutableSplitsDriverId, } from '../../utils/accountIdUtils'; -import { isLatestEvent } from '../../utils/eventUtils'; -import { toIpfsHash } from '../../utils/metadataUtils'; -import handleDripListMetadata from './dripList/handleDripListMetadata'; +import { + getNftDriverMetadata, + convertToIpfsHash, +} from '../../utils/metadataUtils'; +import handleDripListMetadata from './handlers/handleDripListMetadata'; import type EventHandlerRequest from '../../events/EventHandlerRequest'; -import { AccountMetadataEmittedEventModel } from '../../models'; import { dbConnection } from '../../db/database'; -import { getCurrentSplitsByAccountId } from '../../utils/getCurrentSplits'; +import handleEcosystemMainAccountMetadata from './handlers/handleEcosystemMainAccountMetadata'; +import handleSubListMetadata from './handlers/handleSubListMetadata'; +import type { nftDriverAccountMetadataParser } from '../../metadata/schemas'; +import { getCurrentSplitReceiversBySender } from './receiversRepository'; +import type { AccountMetadataEmittedEvent } from '../../../contracts/CURRENT_NETWORK/Drips'; +import { AccountMetadataEmittedEventModel } from '../../models'; +import ScopedLogger from '../../core/ScopedLogger'; +import { isLatestEvent } from '../../utils/isLatestEvent'; export default class AccountMetadataEmittedEventHandler extends EventHandlerBase<'AccountMetadataEmitted(uint256,bytes32,bytes)'> { public readonly eventSignatures = [ 'AccountMetadataEmitted(uint256,bytes32,bytes)' as const, ]; - protected async _handle( - request: EventHandlerRequest<'AccountMetadataEmitted(uint256,bytes32,bytes)'>, - ): Promise { - const { - id: requestId, - event: { args, logIndex, blockNumber, blockTimestamp, transactionHash }, - } = request; - + protected async _handle({ + id: requestId, + event: { + args, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + eventSignature, + }, + }: EventHandlerRequest<'AccountMetadataEmitted(uint256,bytes32,bytes)'>): Promise { const [accountId, key, value] = args as AccountMetadataEmittedEvent.OutputTuple; + const ipfsHash = convertToIpfsHash(value); + + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( + [ + `📥 ${this.name} is processing ${eventSignature}:`, + ` - key: ${toUtf8String(key)} (raw: ${key})`, + ` - value: ${ipfsHash} (raw: ${value})`, + ` - accountId: ${accountId}`, + ` - logIndex: ${logIndex}`, + ` - txHash: ${transactionHash}`, + ].join('\n'), + ); + if (!this._isEmittedByTheDripsApp(key)) { - LogManager.logRequestInfo( - `Skipping ${request.event.eventSignature} event processing because the key '${key}' is not emitted by the Drips App.`, - requestId, + scopedLogger.log( + `Skipping ${eventSignature} event: key '${key}' not emitted by the Drips App.`, ); return; } - const typedAccountId = toAccountId(accountId); - const ipfsHash = toIpfsHash(value); - - LogManager.logRequestInfo( - `📥 ${this.name} is processing the following ${request.event.eventSignature}: - \r\t - key: ${key} - \r\t - value: ${value} (ipfs hash: ${ipfsHash}) - \r\t - accountId: ${typedAccountId} - \r\t - logIndex: ${logIndex} - \r\t - tx hash: ${transactionHash}`, - requestId, - ); + if (!this._canProcessDriverType(accountId)) { + scopedLogger.log( + `Skipping ${eventSignature} event: accountId '${accountId}' is not of a Driver that can be processed.`, + ); - await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); + return; + } - const [accountMetadataEmittedEventModel, isEventCreated] = - await AccountMetadataEmittedEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { + await dbConnection.transaction(async (transaction) => { + const accountMetadataEmittedEvent = + await AccountMetadataEmittedEventModel.create( + { key, value, logIndex, blockNumber, blockTimestamp, transactionHash, - accountId: typedAccountId, + accountId: convertToAccountId(accountId), }, - }); - - logManager.appendFindOrCreateLog( - AccountMetadataEmittedEventModel, - isEventCreated, - `${accountMetadataEmittedEventModel.transactionHash}-${accountMetadataEmittedEventModel.logIndex}`, - ); + { + transaction, + }, + ); - // Only if the event is the latest (in the DB), we process the metadata. + scopedLogger.bufferCreation({ + type: AccountMetadataEmittedEventModel, + input: accountMetadataEmittedEvent, + id: `${accountMetadataEmittedEvent.transactionHash}-${accountMetadataEmittedEvent.logIndex}`, + }); if ( !(await isLatestEvent( - accountMetadataEmittedEventModel, + accountMetadataEmittedEvent, AccountMetadataEmittedEventModel, { + accountId, logIndex, transactionHash, - accountId: typedAccountId, }, transaction, )) ) { - logManager.logAllInfo(); + scopedLogger.flush(); return; } - logManager.appendIsLatestEventLog(); - - // The metadata are related to a Project. - if (isRepoDriverId(typedAccountId)) { - await handleGitProjectMetadata( - logManager, - typedAccountId, - transaction, + if (isRepoDriverId(accountId)) { + await handleProjectMetadata({ + logIndex, ipfsHash, + blockNumber, + scopedLogger, + transaction, blockTimestamp, - ); + emitterAccountId: convertToRepoDriverId(accountId), + }); } - // The metadata are related to a Drip List. - else if (isNftDriverId(typedAccountId)) { - await handleDripListMetadata( - logManager, - typedAccountId, - transaction, + + if (isNftDriverId(accountId)) { + const metadata = await getNftDriverMetadata(ipfsHash); + + if (this._isDripListMetadata(metadata)) { + await handleDripListMetadata({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + transaction, + blockNumber, + blockTimestamp, + emitterAccountId: convertToNftDriverId(accountId), + }); + } else if (this._isEcosystemMainAccountMetadata(metadata)) { + await handleEcosystemMainAccountMetadata({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + transaction, + blockNumber, + blockTimestamp, + emitterAccountId: convertToNftDriverId(accountId), + }); + } + } + + if (isImmutableSplitsDriverId(accountId)) { + await handleSubListMetadata({ ipfsHash, - blockTimestamp, + logIndex, blockNumber, - ); - } else { - logManager.appendLog( - `Skipping metadata processing because the account with ID ${typedAccountId} is not a Project or a Drip List.`, - ); + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId: convertToImmutableSplitsDriverId(accountId), + }); } - logManager.logAllInfo(); + scopedLogger.flush(); }); } - public override async beforeHandle( - request: EventHandlerRequest<'AccountMetadataEmitted(uint256,bytes32,bytes)'>, - ): Promise<{ + public override async beforeHandle({ + event: { args }, + id: requestId, + }: EventHandlerRequest<'AccountMetadataEmitted(uint256,bytes32,bytes)'>): Promise<{ accountIdsToInvalidate: AccountId[]; }> { - const { - event: { args }, - } = request; + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log(`${this.name} is gathering accountIds to invalidate...`); const [accountId] = args as AccountMetadataEmittedEvent.OutputTuple; - const typedAccountId = toAccountId(accountId); + const accountIdsToInvalidate = await getCurrentSplitReceiversBySender( + convertToAccountId(accountId), + ); + + scopedLogger.log( + `${this.name} account IDs to invalidate: ${ + accountIdsToInvalidate.length > 0 + ? accountIdsToInvalidate.join(', ') + : 'none' + }`, + ); return { - accountIdsToInvalidate: await getCurrentSplitsByAccountId(typedAccountId), + accountIdsToInvalidate, }; } private _isEmittedByTheDripsApp(key: string): boolean { return key === DRIPS_APP_USER_METADATA_KEY; } + + private _canProcessDriverType(accountId: bigint): boolean { + return ( + isRepoDriverId(accountId) || + isNftDriverId(accountId) || + isImmutableSplitsDriverId(accountId) + ); + } + + private _isEcosystemMainAccountMetadata( + metadata: AnyVersion, + ): boolean { + return 'type' in metadata && metadata.type === 'ecosystem'; + } + + private _isDripListMetadata( + metadata: AnyVersion, + ): boolean { + return ( + metadata.isDripList || + ('type' in metadata ? metadata.type === 'dripList' : false) + ); + } } diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/createDbEntriesForProjectDependency.ts b/src/eventHandlers/AccountMetadataEmittedEvent/createDbEntriesForProjectDependency.ts deleted file mode 100644 index b2fc6f6..0000000 --- a/src/eventHandlers/AccountMetadataEmittedEvent/createDbEntriesForProjectDependency.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { Transaction } from 'sequelize'; -import { - DependencyType, - type DependencyOfProjectType, - type DripListId, - type ProjectId, -} from '../../core/types'; -import GitProjectModel, { - ProjectVerificationStatus, -} from '../../models/GitProjectModel'; -import { FORGES_MAP } from '../../core/constants'; -import unreachableError from '../../utils/unreachableError'; -import RepoDriverSplitReceiverModel from '../../models/RepoDriverSplitReceiverModel'; -import { isNftDriverId, isRepoDriverId } from '../../utils/accountIdUtils'; - -export default async function createDbEntriesForProjectDependency( - funderAccountId: ProjectId | DripListId, - projectDependency: DependencyOfProjectType, - transaction: Transaction, - blockTimestamp: Date, -) { - const { - weight, - accountId: fundeeProjectId, - source: { forge, ownerName, repoName, url }, - } = projectDependency; - - await GitProjectModel.findOrCreate({ - lock: true, - transaction, - where: { - id: fundeeProjectId, - }, - defaults: { - url, - isVisible: true, // During creation, the project is visible by default. Account metadata will set the final visibility. - isValid: true, // There are no receivers yet, so the project is valid. - id: fundeeProjectId, - name: `${ownerName}/${repoName}`, - verificationStatus: ProjectVerificationStatus.Unclaimed, - forge: - Object.values(FORGES_MAP).find( - (f) => f.toLocaleLowerCase() === forge.toLowerCase(), - ) ?? unreachableError(), - }, - }); - - return RepoDriverSplitReceiverModel.create( - { - weight, - fundeeProjectId, - type: isNftDriverId(funderAccountId) - ? DependencyType.DripListDependency - : DependencyType.ProjectDependency, - funderDripListId: isNftDriverId(funderAccountId) ? funderAccountId : null, - funderProjectId: isRepoDriverId(funderAccountId) ? funderAccountId : null, - blockTimestamp, - }, - { transaction }, - ); -} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/dripList/handleDripListMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/dripList/handleDripListMetadata.ts deleted file mode 100644 index a26143f..0000000 --- a/src/eventHandlers/AccountMetadataEmittedEvent/dripList/handleDripListMetadata.ts +++ /dev/null @@ -1,222 +0,0 @@ -/* eslint-disable no-param-reassign */ -import type { AnyVersion } from '@efstajas/versioned-parser'; -import type { Transaction } from 'sequelize'; -import type { UUID } from 'crypto'; -import { - DependencyType, - type DripListId, - type IpfsHash, -} from '../../../core/types'; -import getNftDriverMetadata from '../../../utils/metadataUtils'; -import validateDripListMetadata from './validateDripListMetadata'; -import type { nftDriverAccountMetadataParser } from '../../../metadata/schemas'; -import LogManager from '../../../core/LogManager'; -import { - isAddressDriverId, - isNftDriverId, - isRepoDriverId, -} from '../../../utils/accountIdUtils'; -import { assertDependencyOfProjectType } from '../../../utils/assert'; -import createDbEntriesForProjectDependency from '../createDbEntriesForProjectDependency'; -import { - AddressDriverSplitReceiverModel, - DripListModel, - RepoDriverSplitReceiverModel, - DripListSplitReceiverModel, -} from '../../../models'; -import unreachableError from '../../../utils/unreachableError'; -import validateSplitsReceivers from '../splitsValidator'; -import getUserAddress from '../../../utils/getAccountAddress'; -import { AddressDriverSplitReceiverType } from '../../../models/AddressDriverSplitReceiverModel'; -import appSettings from '../../../config/appSettings'; - -export default async function handleDripListMetadata( - logManager: LogManager, - dripListId: DripListId, - transaction: Transaction, - ipfsHash: IpfsHash, - blockTimestamp: Date, - blockNumber: number, -) { - const dripList = await DripListModel.findByPk(dripListId, { - transaction, - lock: true, - }); - - if (!dripList) { - throw new Error( - `Failed to update metadata for Drip List with ID ${dripListId}: Drip List not found. - \r Possible reasons: - \r\t - The event that should have created the Drip List was not processed yet. - \r\t - The metadata were manually emitted for a Drip List that does not exist in the app.`, - ); - } - - const metadata = await getNftDriverMetadata(ipfsHash); - - const [areSplitsValid, onChainSplitsHash, calculatedSplitsHash] = - await validateSplitsReceivers( - dripList.id, - metadata.projects.map((s) => ({ - weight: s.weight, - accountId: s.accountId, - })), - ); - - // If we reach this point, it means that the processed `AccountMetadataEmitted` event is the latest in the DB. - // But we still need to check if the splits are the latest on-chain. - // There is no need to process the metadata if the splits are not the latest on-chain. - - if (!areSplitsValid) { - logManager.appendLog( - `Skipping metadata update for Drip List with ID ${dripListId} because the splits receivers hashes from the contract and the metadata do not match: - \r\t - On-chain splits receivers hash: ${onChainSplitsHash} - \r\t - Metadata splits receivers hash: ${calculatedSplitsHash} - \r Possible reasons: - \r\t - The metadata were the latest in the DB but not on-chain. - \r\t - The metadata were manually emitted with different splits than the latest on-chain.`, - ); - - return; - } - - await validateDripListMetadata(dripList, metadata); - - await updateDripListMetadata( - dripList, - logManager, - transaction, - metadata, - blockNumber, - ipfsHash, - ); - - await createDbEntriesForDripListSplits( - dripListId, - metadata.projects, - logManager, - transaction, - blockTimestamp, - ); -} - -async function updateDripListMetadata( - dripList: DripListModel, - logManager: LogManager, - transaction: Transaction, - metadata: AnyVersion, - blockNumber: number, - metaIpfsHash: IpfsHash, -): Promise { - dripList.isValid = true; - dripList.name = metadata.name ?? null; - dripList.description = - 'description' in metadata ? metadata.description || null : null; - dripList.latestVotingRoundId = - 'latestVotingRoundId' in metadata - ? (metadata.latestVotingRoundId as UUID) || null - : null; - dripList.lastProcessedIpfsHash = metaIpfsHash; - - if ( - blockNumber > appSettings.visibilityThresholdBlockNumber && - 'isVisible' in metadata - ) { - dripList.isVisible = metadata.isVisible; - } else { - dripList.isVisible = true; - } - - logManager.appendUpdateLog(dripList, DripListModel, dripList.id); - - await dripList.save({ transaction }); -} - -async function createDbEntriesForDripListSplits( - funderDripListId: DripListId, - splits: AnyVersion['projects'], - logManager: LogManager, - transaction: Transaction, - blockTimestamp: Date, -) { - await clearCurrentProjectSplits(funderDripListId, transaction); - - const splitsPromises = splits.map((split) => { - if (isRepoDriverId(split.accountId)) { - assertDependencyOfProjectType(split); - - return createDbEntriesForProjectDependency( - funderDripListId, - split, - transaction, - blockTimestamp, - ); - } - - if (isNftDriverId(split.accountId)) { - return DripListSplitReceiverModel.create( - { - funderDripListId, - fundeeDripListId: split.accountId, - weight: split.weight, - type: DependencyType.DripListDependency, - blockTimestamp, - }, - { transaction }, - ); - } - - if (isAddressDriverId(split.accountId)) { - return AddressDriverSplitReceiverModel.create( - { - funderDripListId, - weight: split.weight, - fundeeAccountId: split.accountId, - fundeeAccountAddress: getUserAddress(split.accountId), - type: AddressDriverSplitReceiverType.DripListDependency, - blockTimestamp, - }, - { transaction }, - ); - } - - return unreachableError( - `Split with account ID ${split.accountId} is not an Address, Drip List, or a Git Project.`, - ); - }); - - const result = await Promise.all([...splitsPromises]); - - logManager.appendLog( - `Updated ${LogManager.nameOfType( - DripListModel, - )} with ID ${funderDripListId} splits: ${result - .map((p) => JSON.stringify(p)) - .join(`, `)} - `, - ); -} - -async function clearCurrentProjectSplits( - funderDripListId: string, - transaction: Transaction, -) { - await AddressDriverSplitReceiverModel.destroy({ - where: { - funderDripListId, - }, - transaction, - }); - await RepoDriverSplitReceiverModel.destroy({ - where: { - funderDripListId, - }, - transaction, - }); - await DripListSplitReceiverModel.destroy({ - where: { - funderDripListId, - }, - transaction, - }); -} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/dripList/validateDripListMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/dripList/validateDripListMetadata.ts deleted file mode 100644 index cee09c2..0000000 --- a/src/eventHandlers/AccountMetadataEmittedEvent/dripList/validateDripListMetadata.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { AnyVersion } from '@efstajas/versioned-parser'; -import type { nftDriverAccountMetadataParser } from '../../../metadata/schemas'; -import unreachableError from '../../../utils/unreachableError'; -import type { DripListModel } from '../../../models'; - -export default async function validateDripListMetadata( - dripList: DripListModel, - metadata: AnyVersion, -): Promise { - if (!metadata) { - throw new Error( - `Drip List metadata not found for Drip List with (token) ID ${dripList.id} but it was expected to exist.`, - ); - } - - const errors = []; - - const { describes, isDripList } = metadata; - const { id: dripListId } = dripList; - - if (describes.accountId !== dripListId) { - errors.push( - `accountId mismatch with: got ${describes.accountId}, expected ${dripListId}`, - ); - } - - if (!isDripList) { - unreachableError( - `isDripList mismatch with: got ${isDripList}, expected true`, - ); - } - - if (errors.length > 0) { - throw new Error( - `Drip List with ID ${dripListId} has metadata that does not match the metadata emitted by the contract (${errors.join( - '; ', - )}).`, - ); - } -} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/gitProject/handleGitProjectMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/gitProject/handleGitProjectMetadata.ts deleted file mode 100644 index 1a4baef..0000000 --- a/src/eventHandlers/AccountMetadataEmittedEvent/gitProject/handleGitProjectMetadata.ts +++ /dev/null @@ -1,248 +0,0 @@ -/* eslint-disable no-param-reassign */ -import type { Transaction } from 'sequelize'; -import type { AnyVersion } from '@efstajas/versioned-parser'; -import { - AddressDriverSplitReceiverModel, - DripListSplitReceiverModel, - GitProjectModel, - RepoDriverSplitReceiverModel, -} from '../../../models'; -import type { repoDriverAccountMetadataParser } from '../../../metadata/schemas'; -import LogManager from '../../../core/LogManager'; -import { calculateProjectStatus } from '../../../utils/gitProjectUtils'; -import { - DependencyType, - type IpfsHash, - type ProjectId, -} from '../../../core/types'; -import { - assertAddressDiverId, - isAddressDriverId, - isNftDriverId, - isRepoDriverId, -} from '../../../utils/accountIdUtils'; -import { AddressDriverSplitReceiverType } from '../../../models/AddressDriverSplitReceiverModel'; -import { assertDependencyOfProjectType } from '../../../utils/assert'; -import createDbEntriesForProjectDependency from '../createDbEntriesForProjectDependency'; -import unreachableError from '../../../utils/unreachableError'; -import { getProjectMetadata } from '../../../utils/metadataUtils'; -import validateProjectMetadata from './validateProjectMetadata'; -import validateSplitsReceivers from '../splitsValidator'; -import getUserAddress from '../../../utils/getAccountAddress'; - -export default async function handleGitProjectMetadata( - logManager: LogManager, - projectId: ProjectId, - transaction: Transaction, - ipfsHash: IpfsHash, - blockTimestamp: Date, -) { - const project = await GitProjectModel.findByPk(projectId, { - transaction, - lock: true, - }); - - if (!project) { - throw new Error( - `Failed to update metadata for Project with ID ${projectId}: Project not found. - \r Possible reasons: - \r\t - The event that should have created the Project was not processed yet. - \r\t - The metadata were manually emitted for a Project that does not exist in the app.`, - ); - } - - const metadata = await getProjectMetadata(ipfsHash); - - const [areSplitsValid, onChainSplitsHash, calculatedSplitsHash] = - await validateSplitsReceivers( - project.id, - metadata.splits.dependencies - .concat(metadata.splits.maintainers as any) - .map((s) => ({ - weight: s.weight, - accountId: s.accountId, - })), - ); - - // If we reach this point, it means that the processed `AccountMetadataEmitted` event is the latest in the DB. - // But we still need to check if the splits are the latest on-chain. - // There is no need to process the metadata if the splits are not the latest on-chain. - - if (!areSplitsValid) { - logManager.appendLog( - `Skipping metadata update for Project with ID ${projectId} because the splits receivers hashes from the contract and the metadata do not match: - \r\t - On-chain splits receivers hash: ${onChainSplitsHash} - \r\t - Metadata splits receivers hash: ${calculatedSplitsHash} - \r Possible reasons: - \r\t - The metadata were the latest in the DB but not on-chain. - \r\t - The metadata were manually emitted with different splits than the latest on-chain.`, - ); - - return; - } - - await validateProjectMetadata(project, metadata); - - await updateGitProjectMetadata( - project, - logManager, - transaction, - metadata, - ipfsHash, - ); - - await createDbEntriesForProjectSplits( - projectId, - metadata.splits, - logManager, - transaction, - blockTimestamp, - ); -} - -async function updateGitProjectMetadata( - project: GitProjectModel, - logManager: LogManager, - transaction: Transaction, - metadata: AnyVersion, - metadataIpfsHash: IpfsHash, -): Promise { - const { color, source, description } = metadata; - - project.color = color; - project.url = source.url; - project.description = description ?? null; - project.verificationStatus = calculateProjectStatus(project); - project.isVisible = 'isVisible' in metadata ? metadata.isVisible : true; // Projects without `isVisible` field (V4 and below) are considered visible by default. - project.lastProcessedIpfsHash = metadataIpfsHash; - - if ('avatar' in metadata) { - // Metadata V4 - - if (metadata.avatar.type === 'emoji') { - project.emoji = metadata.avatar.emoji; - project.avatarCid = null; - } else if (metadata.avatar.type === 'image') { - project.avatarCid = metadata.avatar.cid; - project.emoji = null; - } - } else { - // Metadata V3 - - project.emoji = metadata.emoji; - } - - logManager.appendUpdateLog(project, GitProjectModel, project.id); - - await project.save({ transaction }); -} - -async function createDbEntriesForProjectSplits( - funderProjectId: ProjectId, - splits: AnyVersion['splits'], - logManager: LogManager, - transaction: Transaction, - blockTimestamp: Date, -) { - await clearCurrentProjectSplits(funderProjectId, transaction); - - const { dependencies, maintainers } = splits; - - const maintainerPromises = maintainers.map((maintainer) => { - assertAddressDiverId(maintainer.accountId); - - return AddressDriverSplitReceiverModel.create( - { - funderProjectId, - weight: maintainer.weight, - fundeeAccountId: maintainer.accountId, - fundeeAccountAddress: getUserAddress(maintainer.accountId), - type: AddressDriverSplitReceiverType.ProjectMaintainer, - blockTimestamp, - }, - { transaction }, - ); - }); - - const dependencyPromises = dependencies.map(async (dependency) => { - if (isRepoDriverId(dependency.accountId)) { - assertDependencyOfProjectType(dependency); - - return createDbEntriesForProjectDependency( - funderProjectId, - dependency, - transaction, - blockTimestamp, - ); - } - - if (isAddressDriverId(dependency.accountId)) { - return AddressDriverSplitReceiverModel.create( - { - funderProjectId, - weight: dependency.weight, - fundeeAccountId: dependency.accountId, - fundeeAccountAddress: getUserAddress(dependency.accountId), - type: AddressDriverSplitReceiverType.ProjectDependency, - blockTimestamp, - }, - { transaction }, - ); - } - - if (isNftDriverId(dependency.accountId)) { - return DripListSplitReceiverModel.create( - { - funderProjectId, - fundeeDripListId: dependency.accountId, - weight: dependency.weight, - type: DependencyType.ProjectDependency, - blockTimestamp, - }, - { transaction }, - ); - } - - return unreachableError( - `Dependency with account ID ${dependency.accountId} is not an Address nor a Git Project.`, - ); - }); - - const result = await Promise.all([ - ...maintainerPromises, - ...dependencyPromises, - ]); - - logManager.appendLog( - `Updated ${LogManager.nameOfType( - GitProjectModel, - )} with ID ${funderProjectId} splits: ${result - .map((p) => JSON.stringify(p)) - .join(`, `)} - `, - ); -} - -async function clearCurrentProjectSplits( - funderProjectId: string, - transaction: Transaction, -) { - await AddressDriverSplitReceiverModel.destroy({ - where: { - funderProjectId, - }, - transaction, - }); - await RepoDriverSplitReceiverModel.destroy({ - where: { - funderProjectId, - }, - transaction, - }); - await DripListSplitReceiverModel.destroy({ - where: { - funderProjectId, - }, - transaction, - }); -} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/gitProject/validateProjectMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/gitProject/validateProjectMetadata.ts deleted file mode 100644 index 307f42c..0000000 --- a/src/eventHandlers/AccountMetadataEmittedEvent/gitProject/validateProjectMetadata.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { AnyVersion } from '@efstajas/versioned-parser'; -import type { repoDriverAccountMetadataParser } from '../../../metadata/schemas'; -import type { GitProjectModel } from '../../../models'; -import unreachableError from '../../../utils/unreachableError'; - -export default async function validateProjectMetadata( - project: GitProjectModel, - metadata: AnyVersion, -): Promise { - if (!metadata) { - unreachableError(`Metadata for Git Project with ID ${project.id} is null.`); - } - - const errors = []; - - const { describes, source } = metadata; - const { - url: metaUrl, - repoName: metaRepoName, - ownerName: metaOwnerName, - } = source; - const { id: onChainProjectId, name: onChainProjectName } = project; - - if (`${metaOwnerName}/${metaRepoName}` !== `${onChainProjectName}`) { - errors.push( - `repoName mismatch: got ${metaOwnerName}/${metaRepoName}, expected ${onChainProjectName}.`, - ); - } - - if (metaUrl !== project.url) { - errors.push(`url mismatch: got ${metaUrl}, expected ${project.url}.`); - } - - if (describes.accountId !== onChainProjectId) { - errors.push( - `accountId mismatch with: got ${describes.accountId}, expected ${onChainProjectId}.`, - ); - } - - if (errors.length > 0) { - throw new Error( - `Git Project with ID ${onChainProjectId} has metadata that does not match the metadata emitted by the contract (${errors.join( - '; ', - )}).`, - ); - } -} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleDripListMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleDripListMetadata.ts new file mode 100644 index 0000000..198ae28 --- /dev/null +++ b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleDripListMetadata.ts @@ -0,0 +1,340 @@ +/* eslint-disable no-param-reassign */ +import type { AnyVersion } from '@efstajas/versioned-parser'; +import type { Transaction } from 'sequelize'; +import type { UUID } from 'crypto'; +import type { + Address, + AddressDriverId, + IpfsHash, + NftDriverId, +} from '../../../core/types'; +import type { nftDriverAccountMetadataParser } from '../../../metadata/schemas'; +import type ScopedLogger from '../../../core/ScopedLogger'; +import unreachableError from '../../../utils/unreachableError'; +import verifySplitsReceivers from '../verifySplitsReceivers'; +import appSettings from '../../../config/appSettings'; +import { + createSplitReceiver, + deleteExistingSplitReceivers, +} from '../receiversRepository'; +import { verifyProjectSources } from '../../../utils/projectUtils'; +import DripListModel from '../../../models/DripListModel'; +import { + assertIsAddressDiverId, + assertIsNftDriverId, + assertIsRepoDriverId, + convertToNftDriverId, +} from '../../../utils/accountIdUtils'; +import { makeVersion } from '../../../utils/lastProcessedVersion'; +import { + addressDriverContract, + nftDriverContract, +} from '../../../core/contractClients'; +import { ProjectModel } from '../../../models'; + +type Params = { + ipfsHash: IpfsHash; + logIndex: number; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: NftDriverId; + metadata: AnyVersion; +}; + +export default async function handleDripListMetadata({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + blockNumber, + transaction, + blockTimestamp, + emitterAccountId, +}: Params) { + validateMetadata(metadata); + + if (metadata.describes.accountId !== emitterAccountId) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped Drip List ${emitterAccountId} metadata processing: metadata describes account ID '${metadata.describes.accountId}' but metadata emitted by '${emitterAccountId}'.`, + ); + + return; + } + + const splitReceivers = metadata.projects ?? metadata.recipients; + + const { isMatch, actualHash, onChainHash } = await verifySplitsReceivers( + emitterAccountId, + splitReceivers.map(({ weight, accountId }) => ({ + weight, + accountId, + })), + ); + + if (!isMatch) { + scopedLogger.bufferMessage( + `Skipped Drip List ${emitterAccountId} metadata processing: on-chain splits hash '${onChainHash}' does not match hash '${actualHash}' calculated from metadata.`, + ); + + return; + } + + const { areProjectsValid, message } = await verifyProjectSources( + splitReceivers.filter((splitReceiver) => 'source' in splitReceiver), + ); + + if (!areProjectsValid) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped Drip List ${emitterAccountId} metadata processing: ${message}`, + ); + + return; + } + + // ✅ All checks passed, we can proceed with the processing. + + await upsertDripList({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + blockNumber, + transaction, + }); + + deleteExistingSplitReceivers(emitterAccountId, transaction); + + await createNewSplitReceivers({ + metadata, + logIndex, + blockNumber, + transaction, + scopedLogger, + blockTimestamp, + emitterAccountId, + }); +} + +async function upsertDripList({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + blockNumber, + transaction, +}: { + logIndex: number; + ipfsHash: IpfsHash; + blockNumber: number; + scopedLogger: ScopedLogger; + transaction: Transaction; + metadata: AnyVersion; +}) { + const accountId = convertToNftDriverId(metadata.describes.accountId); + + const onChainOwner = (await nftDriverContract.ownerOf(accountId)) as Address; + + const values = { + accountId, + name: metadata.name ?? null, + description: + 'description' in metadata ? metadata.description || null : null, + ownerAddress: onChainOwner, + ownerAccountId: ( + await addressDriverContract.calcAccountId(onChainOwner) + ).toString() as AddressDriverId, + latestVotingRoundId: + 'latestVotingRoundId' in metadata + ? (metadata.latestVotingRoundId as UUID) || null + : null, + lastProcessedIpfsHash: ipfsHash, + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), + }; + + const [dripList, isCreation] = await DripListModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { accountId }, + defaults: { + ...values, + isValid: false, // Until the `SplitsSet` event is processed. + isVisible: + blockNumber > appSettings.visibilityThresholdBlockNumber && + 'isVisible' in metadata + ? metadata.isVisible + : true, + }, + }); + + if (isCreation) { + scopedLogger.bufferCreation({ + id: accountId, + type: DripListModel, + input: dripList, + }); + } else { + const newVersion = makeVersion(blockNumber, logIndex); + const storedVersion = BigInt(dripList.lastProcessedVersion); + + // Safely update fields that another event handler could also modify. + if (newVersion > storedVersion) { + dripList.isVisible = + blockNumber > appSettings.visibilityThresholdBlockNumber && + 'isVisible' in metadata + ? metadata.isVisible + : true; + } + + scopedLogger.bufferUpdate({ + id: accountId, + type: DripListModel, + input: dripList, + }); + + await dripList.update( + { ...values, isVisible: dripList.isVisible }, + { transaction }, + ); + } +} + +async function createNewSplitReceivers({ + metadata, + logIndex, + blockNumber, + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId, +}: { + logIndex: number; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: NftDriverId; + metadata: AnyVersion; +}) { + const rawReceivers = + // eslint-disable-next-line no-nested-ternary + 'recipients' in metadata + ? (metadata.recipients ?? []) + : 'projects' in metadata + ? (metadata.projects ?? []) + : []; + + // 2. Upgrade legacy payloads so that *every* receiver object has a `type`. + // – v2+ entries already expose `type`. + // – v1 repo receivers carry a `source` property. + const splitReceivers = rawReceivers.map((receiver: any) => { + if ('type' in receiver) { + return receiver; // v6 or v2–v5. + } + + // v1 without `type`. + if ('source' in receiver) { + // Legacy repo driver receiver. + return { ...receiver, type: 'repoDriver' } as const; + } + + // Legacy address receiver. + return { ...receiver, type: 'address' } as const; + }); + + // Nothing to persist. + if (splitReceivers.length === 0) { + return; + } + + // 3. Persist receivers. + const receiverPromises = splitReceivers.map(async (receiver) => { + switch (receiver.type) { + case 'repoDriver': + assertIsRepoDriverId(receiver.accountId); + + await ProjectModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { + accountId: receiver.accountId, + }, + defaults: { + accountId: receiver.accountId, + verificationStatus: 'unclaimed', + isVisible: true, // Visible by default. Account metadata will set the final visibility. + isValid: true, // There are no receivers yet. Consider the project valid. + url: receiver.source.url, + forge: receiver.source.forge, + name: `${receiver.source.ownerName}/${receiver.source.repoName}`, + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), + }, + }); + + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'drip_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'project', + relationshipType: 'drip_list_receiver', + weight: receiver.weight, + blockTimestamp, + }, + }); + + case 'dripList': + assertIsNftDriverId(receiver.accountId); + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'drip_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'drip_list', + relationshipType: 'drip_list_receiver', + weight: receiver.weight, + blockTimestamp, + }, + }); + + case 'address': + assertIsAddressDiverId(receiver.accountId); + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'drip_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'address', + relationshipType: 'drip_list_receiver', + weight: receiver.weight, + blockTimestamp, + }, + }); + + default: + return unreachableError( + `Unhandled Drip List Split Receiver type: ${(receiver as any).type}`, + ); + } + }); + + await Promise.all(receiverPromises); +} + +function validateMetadata( + metadata: AnyVersion, +) { + const isV6 = 'recipients' in metadata && metadata.type === 'dripList'; + const isV5AndBelow = 'projects' in metadata; + + if (!isV6 && !isV5AndBelow) { + throw new Error('Invalid Drip List metadata schema.'); + } +} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleEcosystemMainAccountMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleEcosystemMainAccountMetadata.ts new file mode 100644 index 0000000..57b0188 --- /dev/null +++ b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleEcosystemMainAccountMetadata.ts @@ -0,0 +1,308 @@ +import type { AnyVersion } from '@efstajas/versioned-parser'; +import type { Transaction } from 'sequelize'; +import type { z } from 'zod'; +import { ZeroAddress } from 'ethers'; +import type ScopedLogger from '../../../core/ScopedLogger'; +import type { + Address, + AddressDriverId, + IpfsHash, + NftDriverId, +} from '../../../core/types'; +import type { nftDriverAccountMetadataParser } from '../../../metadata/schemas'; +import verifySplitsReceivers from '../verifySplitsReceivers'; +import type { subListSplitReceiverSchema } from '../../../metadata/schemas/immutable-splits-driver/v1'; +import { verifyProjectSources } from '../../../utils/projectUtils'; +import { + assertIsImmutableSplitsDriverId, + calcParentRepoDriverId, + convertToNftDriverId, +} from '../../../utils/accountIdUtils'; +import { EcosystemMainAccountModel, ProjectModel } from '../../../models'; +import appSettings from '../../../config/appSettings'; +import { + createSplitReceiver, + deleteExistingSplitReceivers, +} from '../receiversRepository'; +import unreachableError from '../../../utils/unreachableError'; +import { + addressDriverContract, + nftDriverContract, +} from '../../../core/contractClients'; +import { + decodeVersion, + makeVersion, +} from '../../../utils/lastProcessedVersion'; +import type { repoSubAccountDriverSplitReceiverSchema } from '../../../metadata/schemas/common/repoSubAccountDriverSplitReceiverSchema'; + +type Params = { + ipfsHash: IpfsHash; + logIndex: number; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: NftDriverId; + metadata: AnyVersion; +}; + +export default async function handleEcosystemMainAccountMetadata({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + blockNumber, + transaction, + blockTimestamp, + emitterAccountId, +}: Params) { + validateMetadata(metadata); + + if (metadata.describes.accountId !== emitterAccountId) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped Ecosystem Main Account ${emitterAccountId} metadata processing: metadata describes account ID '${metadata.describes.accountId}' but metadata emitted by '${emitterAccountId}'.`, + ); + + return; + } + + const { isMatch, actualHash, onChainHash } = await verifySplitsReceivers( + emitterAccountId, + metadata.recipients, + ); + + if (!isMatch) { + scopedLogger.bufferMessage( + `Skipped Ecosystem Main Account ${emitterAccountId} metadata processing: on-chain splits hash '${onChainHash}' does not match hash '${actualHash}' calculated from metadata.`, + ); + + return; + } + + const { areProjectsValid, message } = await verifyProjectSources( + metadata.recipients.filter((r) => r.type === 'repoSubAccountDriver'), + ); + + if (!areProjectsValid) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped Ecosystem Main Account ${emitterAccountId} metadata processing: ${message}`, + ); + } + + // ✅ All checks passed, we can proceed with the processing. + + await upsertEcosystemMainAccount({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + blockNumber, + transaction, + }); + + deleteExistingSplitReceivers(emitterAccountId, transaction); + + await createNewSplitReceivers({ + logIndex, + blockNumber, + transaction, + scopedLogger, + blockTimestamp, + emitterAccountId, + splitReceivers: metadata.recipients, + }); +} + +async function upsertEcosystemMainAccount({ + ipfsHash, + logIndex, + metadata, + scopedLogger, + blockNumber, + transaction, +}: { + logIndex: number; + ipfsHash: IpfsHash; + blockNumber: number; + scopedLogger: ScopedLogger; + transaction: Transaction; + metadata: AnyVersion; +}) { + const accountId = convertToNftDriverId(metadata.describes.accountId); + + const onChainOwner = (await nftDriverContract.ownerOf(accountId)) as Address; + + const values = { + accountId, + name: metadata.name ?? null, + description: + 'description' in metadata ? metadata.description || null : null, + ownerAddress: onChainOwner, + ownerAccountId: ( + await addressDriverContract.calcAccountId(onChainOwner) + ).toString() as AddressDriverId, + lastProcessedIpfsHash: ipfsHash, + isVisible: + blockNumber > appSettings.visibilityThresholdBlockNumber && + 'isVisible' in metadata + ? metadata.isVisible + : true, + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), + color: + 'color' in metadata + ? metadata.color + : unreachableError('Missing color in Ecosystem Main Account metadata'), + avatar: + 'avatar' in metadata + ? metadata.avatar.emoji + : unreachableError('Missing avatar in Ecosystem Main Account metadata'), + }; + + const [ecosystemMainAccount, isCreation] = + await EcosystemMainAccountModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { accountId }, + defaults: { + ...values, + isValid: false, // Until the `SetSplits` event is processed. + previousOwnerAddress: ZeroAddress as Address, + }, + }); + + if (!isCreation) { + const newVersion = makeVersion(blockNumber, logIndex); + const storedVersion = BigInt(ecosystemMainAccount.lastProcessedVersion); + const { blockNumber: sb, logIndex: sl } = decodeVersion(storedVersion); + + if (newVersion < storedVersion) { + scopedLogger.log( + `Skipped Drip List ${accountId} stale 'AccountMetadata' event (${blockNumber}:${logIndex} ≤ lastProcessed ${sb}:${sl}).`, + ); + + return; + } + + scopedLogger.bufferUpdate({ + input: ecosystemMainAccount, + id: ecosystemMainAccount.accountId, + type: EcosystemMainAccountModel, + }); + + await ecosystemMainAccount.update(values, { transaction }); + } else { + scopedLogger.bufferCreation({ + input: ecosystemMainAccount, + id: ecosystemMainAccount.accountId, + type: EcosystemMainAccountModel, + }); + } +} + +async function createNewSplitReceivers({ + logIndex, + blockNumber, + transaction, + scopedLogger, + splitReceivers, + blockTimestamp, + emitterAccountId, +}: { + logIndex: number; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: NftDriverId; + splitReceivers: ( + | z.infer + | z.infer + )[]; +}) { + const receiverPromises = splitReceivers.map(async (receiver) => { + switch (receiver.type) { + case 'repoSubAccountDriver': + // eslint-disable-next-line no-case-declarations + const repoDriverId = await calcParentRepoDriverId(receiver.accountId); + + await ProjectModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { + accountId: repoDriverId, + }, + defaults: { + accountId: repoDriverId, + verificationStatus: 'unclaimed', + isVisible: true, // Visible by default. Account metadata will set the final visibility. + isValid: true, // There are no receivers yet. Consider the project valid. + url: receiver.source.url, + forge: receiver.source.forge, + name: `${receiver.source.ownerName}/${receiver.source.repoName}`, + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), + }, + }); + + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'ecosystem_main_account', + receiverAccountId: repoDriverId, + receiverAccountType: 'project', + relationshipType: 'ecosystem_receiver', + weight: receiver.weight, + blockTimestamp, + splitsToRepoDriverSubAccount: true, + }, + }); + + case 'subList': + assertIsImmutableSplitsDriverId(receiver.accountId); + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'ecosystem_main_account', + receiverAccountId: receiver.accountId, + receiverAccountType: 'sub_list', + relationshipType: 'sub_list_link', + weight: receiver.weight, + blockTimestamp, + }, + }); + + default: + return unreachableError( + `Unhandled Ecosystem Main Account Split Receiver type: ${(receiver as any).type}`, + ); + } + }); + + await Promise.all(receiverPromises); +} + +function validateMetadata( + metadata: AnyVersion, +): asserts metadata is Extract< + typeof metadata, + { + type: 'ecosystem'; + recipients: ( + | z.infer + | z.infer + )[]; + } +> { + if ( + !( + 'recipients' in metadata && + 'type' in metadata && + metadata.type === 'ecosystem' + ) + ) { + throw new Error('Invalid Ecosystem Main Account ID metadata schema.'); + } +} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata.ts new file mode 100644 index 0000000..229e867 --- /dev/null +++ b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata.ts @@ -0,0 +1,319 @@ +/* eslint-disable no-param-reassign */ // Mutating Sequelize model instance is intentional and safe here. +import { type Transaction } from 'sequelize'; +import type { AnyVersion } from '@efstajas/versioned-parser'; +import { ProjectModel } from '../../../models'; +import type { repoDriverAccountMetadataParser } from '../../../metadata/schemas'; +import type ScopedLogger from '../../../core/ScopedLogger'; +import { + calculateProjectStatus, + verifyProjectSources, +} from '../../../utils/projectUtils'; +import type { IpfsHash, RepoDriverId } from '../../../core/types'; +import { + assertIsAddressDiverId, + isAddressDriverId, + isNftDriverId, + isRepoDriverId, +} from '../../../utils/accountIdUtils'; +import unreachableError from '../../../utils/unreachableError'; +import { getProjectMetadata } from '../../../utils/metadataUtils'; +import verifySplitsReceivers from '../verifySplitsReceivers'; +import { + createSplitReceiver, + deleteExistingSplitReceivers, +} from '../receiversRepository'; +import { makeVersion } from '../../../utils/lastProcessedVersion'; +import RecoverableError from '../../../utils/recoverableError'; + +type Params = { + logIndex: number; + ipfsHash: IpfsHash; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: RepoDriverId; +}; + +export default async function handleProjectMetadata({ + ipfsHash, + logIndex, + blockNumber, + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId, +}: Params) { + const metadata = await getProjectMetadata(ipfsHash); + + if (metadata.describes.accountId !== emitterAccountId) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped ${metadata.source.ownerName}/${metadata.source.repoName} (${emitterAccountId}) metadata processing: metadata describes account ID '${metadata.describes.accountId}' but metadata emitted by '${emitterAccountId}'.`, + ); + + return; + } + + const { isMatch, actualHash, onChainHash } = await verifySplitsReceivers( + emitterAccountId, + [...metadata.splits.dependencies, ...metadata.splits.maintainers], + ); + + if (!isMatch) { + scopedLogger.bufferMessage( + `🚨 Skipped ${metadata.source.ownerName}/${metadata.source.repoName} (${emitterAccountId}) metadata processing: on-chain splits hash '${onChainHash}' does not match '${actualHash}' calculated from metadata.`, + ); + + return; + } + + const project = await ProjectModel.findByPk(emitterAccountId, { + transaction, + lock: transaction.LOCK.UPDATE, + }); + + if (!project) { + scopedLogger.bufferMessage( + `Skipped ${metadata.source.ownerName}/${metadata.source.repoName} (${emitterAccountId}) metadata processing: project not found. Likely waiting on 'OwnerUpdated' event to be processed. Retrying, but if this persists, it is a real error.`, + ); + + scopedLogger.flush(); + + throw new RecoverableError( + `Cannot process metadata for Project ${emitterAccountId}: entity not found. Likely waiting on 'OwnerUpdated' event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + + const projectReceivers = metadata.splits.dependencies.flatMap((s) => + 'source' in s ? [s] : [], + ); + const { areProjectsValid, message } = await verifyProjectSources([ + ...projectReceivers, + { + accountId: emitterAccountId, + source: metadata.source, + }, + ]); + + if (!areProjectsValid) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped ${metadata.source.ownerName}/${metadata.source.repoName} (${emitterAccountId}) metadata processing: ${message}`, + ); + + return; + } + + // We'll store `source` information the metadata, not from the 'OwnerUpdatedRequested' event. + // Therefore, it's necessary to also verify the project's source directly. + const { areProjectsValid: isProjectSourceValid } = await verifyProjectSources( + [ + { + accountId: emitterAccountId, + source: metadata.source, + }, + ], + ); + + if (!isProjectSourceValid) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped ${metadata.source.ownerName}/${metadata.source.repoName} (${emitterAccountId}) metadata processing: ${message}`, + ); + return; + } + + // ✅ All checks passed, we can proceed with the processing. + + await updateProject({ + project, + ipfsHash, + metadata, + logIndex, + blockNumber, + transaction, + scopedLogger, + }); + + deleteExistingSplitReceivers(emitterAccountId, transaction); + + await createNewSplitReceivers({ + logIndex, + blockNumber, + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId, + splitReceivers: metadata.splits, + }); +} + +async function updateProject({ + project, + logIndex, + metadata, + ipfsHash, + transaction, + blockNumber, + scopedLogger, +}: { + logIndex: number; + blockNumber: number; + project: ProjectModel; + ipfsHash: IpfsHash; + transaction: Transaction; + scopedLogger: ScopedLogger; + metadata: AnyVersion; +}): Promise { + const { color, source } = metadata; + + project.url = source.url; + project.forge = source.forge; + project.name = `${source.ownerName}/${source.repoName}`; + project.color = color; + + project.lastProcessedIpfsHash = ipfsHash; + project.lastProcessedVersion = makeVersion(blockNumber, logIndex).toString(); + project.verificationStatus = calculateProjectStatus(project); + project.isVisible = 'isVisible' in metadata ? metadata.isVisible : true; // Projects without `isVisible` field (V4 and below) are considered visible by default. + + if ('avatar' in metadata) { + // Metadata V4 + + if (metadata.avatar.type === 'emoji') { + project.emoji = metadata.avatar.emoji; + project.avatarCid = null; + } else if (metadata.avatar.type === 'image') { + project.avatarCid = metadata.avatar.cid; + project.emoji = null; + } + } else { + // Metadata V3 + + project.emoji = metadata.emoji; + } + + scopedLogger.bufferUpdate({ + type: ProjectModel, + input: project, + id: project.accountId, + }); + + await project.save({ transaction }); +} + +async function createNewSplitReceivers({ + logIndex, + blockNumber, + transaction, + scopedLogger, + blockTimestamp, + splitReceivers, + emitterAccountId, +}: { + logIndex: number; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: RepoDriverId; + splitReceivers: AnyVersion['splits']; +}) { + const { dependencies, maintainers } = splitReceivers; + + const maintainerPromises = maintainers.map(async (maintainer) => { + assertIsAddressDiverId(maintainer.accountId); + + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'project', + receiverAccountId: maintainer.accountId, + receiverAccountType: 'address', + relationshipType: 'project_maintainer', + weight: maintainer.weight, + blockTimestamp, + }, + }); + }); + + const dependencyPromises = dependencies.map(async (dependency) => { + if (isRepoDriverId(dependency.accountId)) { + if (!('source' in dependency)) { + throw new Error( + `Project dependency ${dependency.accountId} is missing source information.`, + ); + } + + await ProjectModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { + accountId: dependency.accountId, + }, + defaults: { + accountId: dependency.accountId, + verificationStatus: 'unclaimed', + isVisible: true, // Visible by default. Account metadata will set the final visibility. + isValid: true, // There are no receivers yet. Consider the project valid. + url: dependency.source.url, + forge: dependency.source.forge, + name: `${dependency.source.ownerName}/${dependency.source.repoName}`, + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), + }, + }); + + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'project', + receiverAccountId: dependency.accountId, + receiverAccountType: 'project', + relationshipType: 'project_dependency', + weight: dependency.weight, + blockTimestamp, + }, + }); + } + + if (isAddressDriverId(dependency.accountId)) { + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'project', + receiverAccountId: dependency.accountId, + receiverAccountType: 'address', + relationshipType: 'project_dependency', + weight: dependency.weight, + blockTimestamp, + }, + }); + } + + if (isNftDriverId(dependency.accountId)) { + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'project', + receiverAccountId: dependency.accountId, + receiverAccountType: 'drip_list', + relationshipType: 'project_dependency', + weight: dependency.weight, + blockTimestamp, + }, + }); + } + + return unreachableError( + `Unhandled Project Split Receiver type: ${(dependency as any).type}`, + ); + }); + + await Promise.all([...maintainerPromises, ...dependencyPromises]); +} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleSubListMetadata.ts b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleSubListMetadata.ts new file mode 100644 index 0000000..69c28bd --- /dev/null +++ b/src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleSubListMetadata.ts @@ -0,0 +1,318 @@ +/* eslint-disable no-param-reassign */ +import type { Transaction } from 'sequelize'; +import type { z } from 'zod'; +import type { AnyVersion } from '@efstajas/versioned-parser'; +import type ScopedLogger from '../../../core/ScopedLogger'; +import type { ImmutableSplitsDriverId, IpfsHash } from '../../../core/types'; +import { + EcosystemMainAccountModel, + ProjectModel, + SubListModel, +} from '../../../models'; +import { getImmutableSpitsDriverMetadata } from '../../../utils/metadataUtils'; +import unreachableError from '../../../utils/unreachableError'; +import verifySplitsReceivers from '../verifySplitsReceivers'; +import type { addressDriverSplitReceiverSchema } from '../../../metadata/schemas/repo-driver/v2'; +import type { subListSplitReceiverSchema } from '../../../metadata/schemas/immutable-splits-driver/v1'; +import type { dripListSplitReceiverSchema } from '../../../metadata/schemas/nft-driver/v2'; +import RecoverableError from '../../../utils/recoverableError'; +import type { immutableSplitsDriverMetadataParser } from '../../../metadata/schemas'; +import { verifyProjectSources } from '../../../utils/projectUtils'; +import { + createSplitReceiver, + deleteExistingSplitReceivers, +} from '../receiversRepository'; +import { METADATA_RECEIVER_TYPE_TO_ACCOUNT_TYPE } from '../../../core/splitRules'; +import { + assertIsAddressDiverId, + assertIsImmutableSplitsDriverId, + assertIsNftDriverId, + assertIsRepoDriverId, + convertToAccountId, + convertToImmutableSplitsDriverId, +} from '../../../utils/accountIdUtils'; +import { makeVersion } from '../../../utils/lastProcessedVersion'; +import type { repoSubAccountDriverSplitReceiverSchema } from '../../../metadata/schemas/common/repoSubAccountDriverSplitReceiverSchema'; + +type Params = { + logIndex: number; + blockNumber: number; + ipfsHash: IpfsHash; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + emitterAccountId: ImmutableSplitsDriverId; + transaction: Transaction; +}; + +export default async function handleSubListMetadata({ + ipfsHash, + logIndex, + blockNumber, + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId, +}: Params) { + const metadata = await getImmutableSpitsDriverMetadata(ipfsHash); + + if ( + metadata.parent.type !== 'ecosystem' || + metadata.root.type !== 'ecosystem' + ) { + scopedLogger.bufferMessage( + `🚨 Skipped Sub-List metadata processing: parent and root must be of type 'ecosystem'.`, + ); + + return; + } + + const { isMatch, actualHash, onChainHash } = await verifySplitsReceivers( + emitterAccountId, + metadata.recipients, + ); + + if (!isMatch) { + scopedLogger.bufferMessage( + `🚨 Skipped Sub-List metadata processing: on-chain splits hash '${onChainHash}' does not match '${actualHash}' calculated from metadata.`, + ); + + return; + } + + const { areProjectsValid, message } = await verifyProjectSources( + metadata.recipients.filter((r) => r.type === 'repoSubAccountDriver'), + ); + + if (!areProjectsValid) { + scopedLogger.bufferMessage( + `🚨🕵️‍♂️ Skipped Sub-List metadata processing: ${message}`, + ); + + return; + } + + await validateRootAndParentExist(metadata, transaction); + + // ✅ All checks passed, we can proceed with the processing. + + await upsertSubList({ + metadata, + ipfsHash, + scopedLogger, + transaction, + emitterAccountId, + }); + + deleteExistingSplitReceivers(emitterAccountId, transaction); + + await createNewSplitReceivers({ + logIndex, + blockNumber, + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId, + receivers: metadata.recipients, + }); +} + +async function upsertSubList({ + ipfsHash, + metadata, + scopedLogger, + transaction, + emitterAccountId, +}: { + ipfsHash: IpfsHash; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: ImmutableSplitsDriverId; + metadata: AnyVersion; +}): Promise { + const values = { + accountId: emitterAccountId, + parentAccountType: + METADATA_RECEIVER_TYPE_TO_ACCOUNT_TYPE[metadata.parent.type], + parentAccountId: convertToAccountId(metadata.parent.accountId), + rootAccountType: METADATA_RECEIVER_TYPE_TO_ACCOUNT_TYPE[metadata.root.type], + rootAccountId: convertToAccountId(metadata.root.accountId), + lastProcessedIpfsHash: ipfsHash, + }; + + const accountId = convertToImmutableSplitsDriverId(emitterAccountId); + + const [subList, isCreation] = await SubListModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { accountId }, + defaults: { + ...values, + isValid: false, // Until the `SetSplits` event is processed. + }, + }); + + if (!isCreation) { + scopedLogger.bufferUpdate({ + input: subList, + type: SubListModel, + id: subList.accountId, + }); + + await subList.update(values, { transaction }); + } else { + scopedLogger.bufferCreation({ + input: subList, + type: SubListModel, + id: subList.accountId, + }); + } +} + +async function createNewSplitReceivers({ + logIndex, + receivers, + blockNumber, + scopedLogger, + transaction, + blockTimestamp, + emitterAccountId, +}: { + logIndex: number; + blockNumber: number; + blockTimestamp: Date; + scopedLogger: ScopedLogger; + transaction: Transaction; + emitterAccountId: ImmutableSplitsDriverId; + receivers: ( + | z.infer + | z.infer + | z.infer + | z.infer + )[]; +}) { + const receiverPromises = receivers.map(async (receiver) => { + switch (receiver.type) { + case 'repoSubAccountDriver': + assertIsRepoDriverId(receiver.accountId); + + await ProjectModel.findOrCreate({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { + accountId: receiver.accountId, + }, + defaults: { + accountId: receiver.accountId, + verificationStatus: 'unclaimed', + isVisible: true, // Visible by default. Account metadata will set the final visibility. + isValid: true, // There are no receivers yet. Consider the project valid. + url: receiver.source.url, + forge: receiver.source.forge, + name: `${receiver.source.ownerName}/${receiver.source.repoName}`, + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), + }, + }); + + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'sub_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'project', + relationshipType: 'sub_list_link', + weight: receiver.weight, + blockTimestamp, + }, + }); + + case 'subList': + assertIsImmutableSplitsDriverId(receiver.accountId); + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'sub_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'sub_list', + relationshipType: 'sub_list_link', + weight: receiver.weight, + blockTimestamp, + }, + }); + + case 'dripList': + assertIsNftDriverId(receiver.accountId); + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'sub_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'drip_list', + relationshipType: 'sub_list_link', + weight: receiver.weight, + blockTimestamp, + }, + }); + + case 'address': + assertIsAddressDiverId(receiver.accountId); + return createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape: { + senderAccountId: emitterAccountId, + senderAccountType: 'sub_list', + receiverAccountId: receiver.accountId, + receiverAccountType: 'address', + relationshipType: 'sub_list_link', + weight: receiver.weight, + blockTimestamp, + }, + }); + + default: + return unreachableError( + `Unhandled Sub-List Receiver type: ${(receiver as any).type}`, + ); + } + }); + + await Promise.all(receiverPromises); +} + +async function validateRootAndParentExist( + metadata: AnyVersion, + transaction: Transaction, +) { + const root = await EcosystemMainAccountModel.findByPk( + metadata.root.accountId, + { + transaction, + lock: transaction.LOCK.UPDATE, + }, + ); + + if (!root) { + throw new RecoverableError( + `Root Ecosystem Main Account '${metadata.root.accountId}' not found. Likely waiting on 'AccountMetadata' event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + + const parent = await EcosystemMainAccountModel.findByPk( + metadata.parent.accountId, + { + transaction, + lock: transaction.LOCK.UPDATE, + }, + ); + if (!parent) { + throw new RecoverableError( + `Parent Ecosystem Main Account '${metadata.parent.accountId}' not found. Likely waiting on 'AccountMetadata' event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } +} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/receiversRepository.ts b/src/eventHandlers/AccountMetadataEmittedEvent/receiversRepository.ts new file mode 100644 index 0000000..8a08dd7 --- /dev/null +++ b/src/eventHandlers/AccountMetadataEmittedEvent/receiversRepository.ts @@ -0,0 +1,73 @@ +import { type Transaction } from 'sequelize'; +import type { AccountId } from '../../core/types'; +import type ScopedLogger from '../../core/ScopedLogger'; +import type { SplitReceiverShape } from '../../core/splitRules'; +import { + SplitsReceiverModel, + StreamReceiverSeenEventModel, +} from '../../models'; + +export async function deleteExistingSplitReceivers( + senderAccountId: AccountId, + transaction: Transaction, +) { + await SplitsReceiverModel.destroy({ + where: { + senderAccountId, + }, + transaction, + }); +} + +export async function createSplitReceiver({ + scopedLogger, + transaction, + splitReceiverShape, +}: { + scopedLogger: ScopedLogger; + transaction: Transaction; + splitReceiverShape: SplitReceiverShape; +}) { + const splitReceiver = await SplitsReceiverModel.create( + { ...splitReceiverShape }, + { transaction }, + ); + + scopedLogger.bufferCreation({ + input: splitReceiver, + type: SplitsReceiverModel, + id: splitReceiver.id.toString(), + }); +} + +export async function getCurrentSplitReceiversBySender( + senderAccountId: AccountId, +): Promise { + const splitReceivers = await SplitsReceiverModel.findAll({ + where: { + senderAccountId, + }, + lock: true, + }); + + const accountIds = [ + ...splitReceivers.map((receiver) => receiver.senderAccountId), + ]; + + return Array.from(new Set(accountIds)); +} + +export async function getCurrentSplitReceiversByReceiversHash( + receiversHash: string, +): Promise { + const streamReceiverSeenEvents = await StreamReceiverSeenEventModel.findAll({ + where: { + receiversHash, + }, + lock: true, + }); + + const accountIds = streamReceiverSeenEvents.map((event) => event.accountId); + + return Array.from(new Set(accountIds)); +} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/splitsValidator.ts b/src/eventHandlers/AccountMetadataEmittedEvent/splitsValidator.ts deleted file mode 100644 index 3a4080d..0000000 --- a/src/eventHandlers/AccountMetadataEmittedEvent/splitsValidator.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { SplitsReceiverStruct } from '../../../contracts/CURRENT_NETWORK/Drips'; -import type { DripListId, ProjectId } from '../../core/types'; -import { dripsContract } from '../../core/contractClients'; - -export default async function validateSplitsReceivers( - accountId: ProjectId | DripListId, - splits: SplitsReceiverStruct[], -): Promise< - [ - areSplitsValid: boolean, - onChainSplitsHash: string, - calculatedSplitsHash: string, - ] -> { - const formattedSplits = formatSplitReceivers(splits); - const calculatedSplitsHash = await dripsContract.hashSplits(formattedSplits); - const onChainSplitsHash = await dripsContract.splitsHash(accountId); - - if (calculatedSplitsHash !== onChainSplitsHash) { - return [false, onChainSplitsHash, calculatedSplitsHash]; - } - - return [true, onChainSplitsHash, calculatedSplitsHash]; -} - -export function formatSplitReceivers( - receivers: SplitsReceiverStruct[], -): SplitsReceiverStruct[] { - // Splits receivers must be sorted by user ID, deduplicated, and without weights <= 0. - - const uniqueReceivers = receivers.reduce( - (unique: SplitsReceiverStruct[], o) => { - if ( - !unique.some( - (obj: SplitsReceiverStruct) => - obj.accountId === o.accountId && obj.weight === o.weight, - ) - ) { - unique.push(o); - } - return unique; - }, - [], - ); - - const sortedReceivers = uniqueReceivers.sort((a, b) => - // Sort by user ID. - // eslint-disable-next-line no-nested-ternary - BigInt(a.accountId) > BigInt(b.accountId) - ? 1 - : BigInt(a.accountId) < BigInt(b.accountId) - ? -1 - : 0, - ); - - return sortedReceivers; -} diff --git a/src/eventHandlers/AccountMetadataEmittedEvent/verifySplitsReceivers.ts b/src/eventHandlers/AccountMetadataEmittedEvent/verifySplitsReceivers.ts new file mode 100644 index 0000000..a4f97f0 --- /dev/null +++ b/src/eventHandlers/AccountMetadataEmittedEvent/verifySplitsReceivers.ts @@ -0,0 +1,27 @@ +import { dripsContract } from '../../core/contractClients'; +import { formatSplitReceivers } from '../../utils/formatSplitReceivers'; +import type { SplitsReceiverStruct } from '../../../contracts/CURRENT_NETWORK/Drips'; +import type { AccountId } from '../../core/types'; + +type SplitsHashVerificationResult = { + isMatch: boolean; + onChainHash: string; + actualHash: string; +}; + +export default async function verifySplitsReceivers( + accountId: AccountId, + splitReceivers: SplitsReceiverStruct[], +): Promise { + const actualHash = await dripsContract.hashSplits( + formatSplitReceivers(splitReceivers), + ); + + const onChainHash = await dripsContract.splitsHash(accountId); + + return { + isMatch: actualHash === onChainHash, + onChainHash, + actualHash, + }; +} diff --git a/src/eventHandlers/GivenEventHandler.ts b/src/eventHandlers/GivenEventHandler.ts index 90eb394..f623d33 100644 --- a/src/eventHandlers/GivenEventHandler.ts +++ b/src/eventHandlers/GivenEventHandler.ts @@ -1,6 +1,6 @@ import EventHandlerBase from '../events/EventHandlerBase'; -import LogManager from '../core/LogManager'; -import { toAccountId } from '../utils/accountIdUtils'; +import ScopedLogger from '../core/ScopedLogger'; +import { convertToAccountId } from '../utils/accountIdUtils'; import type EventHandlerRequest from '../events/EventHandlerRequest'; import { GivenEventModel } from '../models'; import { dbConnection } from '../db/database'; @@ -22,12 +22,14 @@ export default class GivenEventHandler extends EventHandlerBase<'Given(uint256,u const [rawAccountId, rawReceiver, rawErc20, rawAmt] = args as GivenEvent.OutputTuple; - const accountId = toAccountId(rawAccountId); - const receiver = toAccountId(rawReceiver); + const accountId = convertToAccountId(rawAccountId); + const receiver = convertToAccountId(rawReceiver); const erc20 = toAddress(rawErc20); const amt = toBigIntString(rawAmt.toString()); - LogManager.logRequestInfo( + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( `📥 ${this.name} is processing the following ${request.event.eventSignature}: \r\t - accountId: ${accountId} \r\t - receiver: ${rawReceiver} @@ -35,20 +37,11 @@ export default class GivenEventHandler extends EventHandlerBase<'Given(uint256,u \r\t - amt: ${rawAmt} \r\t - logIndex: ${logIndex} \r\t - tx hash: ${transactionHash}`, - requestId, ); await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [givenEvent, isEventCreated] = await GivenEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { + const givenEvent = await GivenEventModel.create( + { accountId, receiver, erc20, @@ -58,15 +51,16 @@ export default class GivenEventHandler extends EventHandlerBase<'Given(uint256,u blockTimestamp, transactionHash, }, - }); - - logManager.appendFindOrCreateLog( - GivenEventModel, - isEventCreated, - `${givenEvent.transactionHash}-${givenEvent.logIndex}`, + { transaction }, ); - logManager.logAllInfo(); + scopedLogger.bufferCreation({ + input: givenEvent, + type: GivenEventModel, + id: `${givenEvent.transactionHash}-${givenEvent.logIndex}`, + }); + + scopedLogger.flush(); }); } } diff --git a/src/eventHandlers/OwnerUpdateRequestedEventHandler.ts b/src/eventHandlers/OwnerUpdateRequestedEventHandler.ts deleted file mode 100644 index 424f34e..0000000 --- a/src/eventHandlers/OwnerUpdateRequestedEventHandler.ts +++ /dev/null @@ -1,171 +0,0 @@ -import type { OwnerUpdateRequestedEvent as CurrentNetworkOwnerUpdateRequestedEvent } from '../../contracts/CURRENT_NETWORK/RepoDriver'; -import type { OwnerUpdateRequestedEvent as FilecoinOwnerUpdateRequestedEvent } from '../../contracts/filecoin/RepoDriver'; -import OwnerUpdateRequestedEventModel from '../models/OwnerUpdateRequestedEventModel'; -import EventHandlerBase from '../events/EventHandlerBase'; -import { GitProjectModel } from '../models'; -import { ProjectVerificationStatus } from '../models/GitProjectModel'; -import { - calculateProjectStatus, - toForge, - toReadable, - toUrl, -} from '../utils/gitProjectUtils'; -import LogManager from '../core/LogManager'; -import { toRepoDriverId } from '../utils/accountIdUtils'; -import { isLatestEvent } from '../utils/eventUtils'; -import type EventHandlerRequest from '../events/EventHandlerRequest'; -import { dbConnection } from '../db/database'; -import { singleOrDefault } from '../utils/linq'; - -export default class OwnerUpdateRequestedEventHandler extends EventHandlerBase< - | 'OwnerUpdateRequested(uint256,uint8,bytes,address)' - | 'OwnerUpdateRequested(uint256,uint8,bytes)' -> { - public readonly eventSignatures = [ - 'OwnerUpdateRequested(uint256,uint8,bytes,address)' as const, - 'OwnerUpdateRequested(uint256,uint8,bytes)' as const, - ]; - - protected async _handle( - request: EventHandlerRequest< - | 'OwnerUpdateRequested(uint256,uint8,bytes,address)' - | 'OwnerUpdateRequested(uint256,uint8,bytes)' - >, - ): Promise { - const { - id: requestId, - event: { args, logIndex, blockNumber, blockTimestamp, transactionHash }, - } = request; - - const [accountId, forge, name] = args as - | CurrentNetworkOwnerUpdateRequestedEvent.OutputTuple - | FilecoinOwnerUpdateRequestedEvent.OutputTuple; - - const repoDriverId = toRepoDriverId(accountId); - const forgeAsString = toForge(forge); - const decodedName = toReadable(name); - - LogManager.logRequestInfo( - `📥 ${this.name} is processing the following ${request.event.eventSignature}: - \r\t - forge: ${forgeAsString} - \r\t - name: ${decodedName} - \r\t - accountId: ${repoDriverId} - \r\t - logIndex: ${logIndex} - \r\t - blockNumber: ${blockNumber} - \r\t - tx hash: ${transactionHash}`, - requestId, - ); - - await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [ownerUpdateRequestedEvent, isEventCreated] = - await OwnerUpdateRequestedEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - name: decodedName, - forge: forgeAsString, - accountId: repoDriverId, - }, - }); - - logManager.appendFindOrCreateLog( - OwnerUpdateRequestedEventModel, - isEventCreated, - `${ownerUpdateRequestedEvent.transactionHash}-${ownerUpdateRequestedEvent.logIndex}`, - ); - - // Depending on the order of processing, a project can be created: - // - By a `OwnerUpdateRequested` event. - // - By a `OwnerUpdated` event. - // - By an `AccountMetadataEmitted` event, as a (non existing in the DB) Project dependency of the account that emitted the metadata. - const [project, isProjectCreated] = await GitProjectModel.findOrCreate({ - transaction, - lock: true, - where: { - id: repoDriverId, - }, - defaults: { - isVisible: true, // During creation, the project is visible by default. Account metadata will set the final visibility. - id: repoDriverId, - isValid: true, // There are no receivers yet, so the project is valid. - name: decodedName, - forge: forgeAsString, - url: toUrl(forgeAsString, decodedName), - verificationStatus: ProjectVerificationStatus.OwnerUpdateRequested, - }, - }); - - if (isProjectCreated) { - logManager - .appendFindOrCreateLog(GitProjectModel, isProjectCreated, project.id) - .logAllInfo(); - - return; - } - - // Here, the Project already exists. - // Only if the event is the latest (in the DB), we process the metadata. - // After all events are processed, the Project will be updated with the latest values. - if ( - !(await isLatestEvent( - ownerUpdateRequestedEvent, - OwnerUpdateRequestedEventModel, - { - logIndex, - transactionHash, - accountId, - }, - transaction, - )) - ) { - logManager.logAllInfo(); - - return; - } - - project.name = decodedName; - project.forge = forgeAsString; - project.url = toUrl(forgeAsString, decodedName); - project.verificationStatus = calculateProjectStatus(project); - - logManager - .appendIsLatestEventLog() - .appendUpdateLog(project, GitProjectModel, project.id); - - await project.save({ transaction }); - - logManager.logAllInfo(); - }); - } - - override async afterHandle(context: { - args: [accountId: bigint]; - blockTimestamp: Date; - }): Promise { - const { args, blockTimestamp } = context; - const [accountId] = args; - - const ownerAccountId = singleOrDefault( - await GitProjectModel.findAll({ - where: { - id: toRepoDriverId(accountId), - }, - }), - )?.ownerAccountId; - - super.afterHandle({ - args: [accountId, ownerAccountId], - blockTimestamp, - }); - } -} diff --git a/src/eventHandlers/OwnerUpdatedEventHandler.ts b/src/eventHandlers/OwnerUpdatedEventHandler.ts index cf87492..32a1002 100644 --- a/src/eventHandlers/OwnerUpdatedEventHandler.ts +++ b/src/eventHandlers/OwnerUpdatedEventHandler.ts @@ -1,142 +1,148 @@ import type { OwnerUpdatedEvent } from '../../contracts/CURRENT_NETWORK/RepoDriver'; +import { + addressDriverContract, + repoDriverContract, +} from '../core/contractClients'; +import ScopedLogger from '../core/ScopedLogger'; +import type { Address, AddressDriverId } from '../core/types'; +import { dbConnection } from '../db/database'; import EventHandlerBase from '../events/EventHandlerBase'; -import { GitProjectModel, OwnerUpdatedEventModel } from '../models'; -import LogManager from '../core/LogManager'; -import { calcAccountId, toRepoDriverId } from '../utils/accountIdUtils'; -import { calculateProjectStatus } from '../utils/gitProjectUtils'; -import { isLatestEvent } from '../utils/eventUtils'; import type EventHandlerRequest from '../events/EventHandlerRequest'; -import { ProjectVerificationStatus } from '../models/GitProjectModel'; -import { dbConnection } from '../db/database'; +import { ProjectModel } from '../models'; +import OwnerUpdatedEventModel from '../models/OwnerUpdatedEventModel'; +import { convertToRepoDriverId } from '../utils/accountIdUtils'; +import { makeVersion } from '../utils/lastProcessedVersion'; +import { calculateProjectStatus } from '../utils/projectUtils'; export default class OwnerUpdatedEventHandler extends EventHandlerBase<'OwnerUpdated(uint256,address)'> { public readonly eventSignatures = ['OwnerUpdated(uint256,address)' as const]; - protected async _handle( - request: EventHandlerRequest<'OwnerUpdated(uint256,address)'>, - ): Promise { - const { - id: requestId, - event: { args, logIndex, blockNumber, blockTimestamp, transactionHash }, - } = request; - - const [accountId, owner] = args as OwnerUpdatedEvent.OutputTuple; - - const repoDriverId = toRepoDriverId(accountId); - - LogManager.logRequestInfo( - `📥 ${this.name} is processing the following ${request.event.eventSignature}: - \r\t - owner: ${owner} - \r\t - accountId: ${repoDriverId} - \r\t - logIndex: ${logIndex} - \r\t - blockNumber: ${blockNumber} - \r\t - tx hash: ${transactionHash}`, - requestId, + protected async _handle({ + id: requestId, + event: { + args, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + eventSignature, + }, + }: EventHandlerRequest<'OwnerUpdated(uint256,address)'>): Promise { + const [rawAccountId, owner] = args as OwnerUpdatedEvent.OutputTuple; + const accountId = convertToRepoDriverId(rawAccountId); + + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( + [ + `📥 ${this.name} is processing ${eventSignature}:`, + ` - owner: ${owner}`, + ` - accountId: ${accountId}`, + ` - logIndex: ${logIndex}`, + ` - txHash: ${transactionHash}`, + ].join('\n'), ); - await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [ownerUpdatedEvent, isEventCreated] = - await OwnerUpdatedEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - owner, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - accountId: repoDriverId, - }, - }); + const onChainOwner = (await repoDriverContract.ownerOf( + accountId, + )) as Address; + if (owner !== onChainOwner) { + scopedLogger.log( + `Skipped Project ${accountId} 'OwnerUpdated' event processing: on-chain owner '${onChainOwner}' does not match event 'owner' '${owner}'.`, + ); + + return; + } - logManager.appendFindOrCreateLog( - OwnerUpdatedEventModel, - isEventCreated, - `${ownerUpdatedEvent.transactionHash}-${ownerUpdatedEvent.logIndex}`, + await dbConnection.transaction(async (transaction) => { + const ownerUpdatedEvent = await OwnerUpdatedEventModel.create( + { + owner, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + accountId, + }, + { transaction }, ); - // Depending on the order of processing, a project can be created: - // - By a `OwnerUpdateRequested` event. - // - By a `OwnerUpdated` event. - // - By an `AccountMetadataEmitted` event, as a (non existing in the DB) Project dependency of the account that emitted the metadata. - const [project, isProjectCreated] = await GitProjectModel.findOrCreate({ + scopedLogger.bufferCreation({ + input: ownerUpdatedEvent, + type: OwnerUpdatedEventModel, + id: `${transactionHash}-${logIndex}`, + }); + + const [project, isCreation] = await ProjectModel.findOrCreate({ transaction, - lock: true, + lock: transaction.LOCK.UPDATE, where: { - id: repoDriverId, + accountId, }, defaults: { - isVisible: true, // During creation, the project is visible by default. Account metadata will set the final visibility. - id: repoDriverId, - isValid: true, // There are no receivers yet, so the project is valid. - ownerAddress: owner, + accountId, + ownerAddress: onChainOwner, + ownerAccountId: ( + await addressDriverContract.calcAccountId(onChainOwner) + ).toString() as AddressDriverId, claimedAt: blockTimestamp, - ownerAccountId: await calcAccountId(owner), - verificationStatus: ProjectVerificationStatus.OwnerUpdated, + verificationStatus: 'pending_metadata', + isVisible: true, // Visible by default. Account metadata will set the final visibility. + isValid: true, // There are no receivers yet. Consider the project valid. + lastProcessedVersion: makeVersion(blockNumber, logIndex).toString(), }, }); - if (isProjectCreated) { - logManager - .appendFindOrCreateLog(GitProjectModel, isProjectCreated, project.id) - .logAllInfo(); - - return; - } + if (isCreation) { + scopedLogger.bufferCreation({ + type: ProjectModel, + input: project, + id: project.accountId, + }); + } else { + const newVersion = makeVersion(blockNumber, logIndex); + const storedVersion = BigInt(project.lastProcessedVersion); + + // Safely update fields that another event handler could also modify. + if (newVersion > storedVersion) { + project.verificationStatus = calculateProjectStatus(project); + } + + project.ownerAccountId = ( + await addressDriverContract.calcAccountId(onChainOwner) + ).toString() as AddressDriverId; + project.ownerAddress = onChainOwner; + project.claimedAt = blockTimestamp; + + project.lastProcessedVersion = newVersion.toString(); + + scopedLogger.bufferUpdate({ + type: ProjectModel, + id: project.accountId, + input: project, + }); - // Here, the Project already exists. - // Only if the event is the latest (in the DB), we process the metadata. - // After all events are processed, the Project will be updated with the latest values. - if ( - !isLatestEvent( - ownerUpdatedEvent, - OwnerUpdatedEventModel, - { - logIndex, - transactionHash, - accountId: repoDriverId, - }, - transaction, - ) - ) { - logManager.logAllInfo(); - - return; + await project.save({ transaction }); } - project.ownerAddress = owner; - project.claimedAt = blockTimestamp; - project.ownerAccountId = (await calcAccountId(owner)) ?? null; - project.verificationStatus = calculateProjectStatus(project); - - logManager - .appendIsLatestEventLog() - .appendUpdateLog(project, GitProjectModel, project.id); - - await project.save({ transaction }); - - logManager.logAllInfo(); + scopedLogger.flush(); }); } override async afterHandle(context: { args: [accountId: bigint, owner: string]; blockTimestamp: Date; + requestId: string; }): Promise { const { args, blockTimestamp } = context; const [accountId, owner] = args; - const ownerAccountId = await calcAccountId(owner); + const ownerAccountId = await addressDriverContract.calcAccountId(owner); super.afterHandle({ args: [accountId, ownerAccountId], blockTimestamp, + requestId: context.requestId, }); } } diff --git a/src/eventHandlers/SplitEventHandler.ts b/src/eventHandlers/SplitEventHandler.ts index becf000..d505c91 100644 --- a/src/eventHandlers/SplitEventHandler.ts +++ b/src/eventHandlers/SplitEventHandler.ts @@ -1,6 +1,6 @@ import EventHandlerBase from '../events/EventHandlerBase'; -import LogManager from '../core/LogManager'; -import { toAccountId } from '../utils/accountIdUtils'; +import ScopedLogger from '../core/ScopedLogger'; +import { convertToAccountId } from '../utils/accountIdUtils'; import type EventHandlerRequest from '../events/EventHandlerRequest'; import { SplitEventModel } from '../models'; import { dbConnection } from '../db/database'; @@ -22,12 +22,14 @@ export default class SplitEventHandler extends EventHandlerBase<'Split(uint256,u const [rawAccountId, rawReceiver, rawErc20, rawAmt] = args as SplitEvent.OutputTuple; - const accountId = toAccountId(rawAccountId); - const receiver = toAccountId(rawReceiver); + const accountId = convertToAccountId(rawAccountId); + const receiver = convertToAccountId(rawReceiver); const erc20 = toAddress(rawErc20); const amt = toBigIntString(rawAmt.toString()); - LogManager.logRequestInfo( + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( `📥 ${this.name} is processing the following ${request.event.eventSignature}: \r\t - accountId: ${accountId} \r\t - receiver: ${rawReceiver} @@ -35,20 +37,11 @@ export default class SplitEventHandler extends EventHandlerBase<'Split(uint256,u \r\t - amt: ${rawAmt} \r\t - logIndex: ${logIndex} \r\t - tx hash: ${transactionHash}`, - requestId, ); await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [givenEvent, isEventCreated] = await SplitEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { + const splitEvent = await SplitEventModel.create( + { accountId, receiver, erc20, @@ -58,15 +51,16 @@ export default class SplitEventHandler extends EventHandlerBase<'Split(uint256,u blockTimestamp, transactionHash, }, - }); - - logManager.appendFindOrCreateLog( - SplitEventModel, - isEventCreated, - `${givenEvent.transactionHash}-${givenEvent.logIndex}`, + { transaction }, ); - logManager.logAllInfo(); + scopedLogger.bufferCreation({ + input: splitEvent, + type: SplitEventModel, + id: `${splitEvent.transactionHash}-${splitEvent.logIndex}`, + }); + + scopedLogger.flush(); }); } } diff --git a/src/eventHandlers/SplitsSetEvent/SplitsSetEventHandler.ts b/src/eventHandlers/SplitsSetEvent/SplitsSetEventHandler.ts new file mode 100644 index 0000000..282601c --- /dev/null +++ b/src/eventHandlers/SplitsSetEvent/SplitsSetEventHandler.ts @@ -0,0 +1,66 @@ +import type { SplitsSetEvent } from '../../../contracts/CURRENT_NETWORK/Drips'; +import ScopedLogger from '../../core/ScopedLogger'; +import { dbConnection } from '../../db/database'; +import EventHandlerBase from '../../events/EventHandlerBase'; +import type EventHandlerRequest from '../../events/EventHandlerRequest'; +import SplitsSetEventModel from '../../models/SplitsSetEventModel'; +import { convertToAccountId } from '../../utils/accountIdUtils'; +import setIsValidFlag from './setIsValidFlag'; + +export default class SplitsSetEventHandler extends EventHandlerBase<'SplitsSet(uint256,bytes32)'> { + public eventSignatures = ['SplitsSet(uint256,bytes32)' as const]; + + protected async _handle({ + id: requestId, + event: { + args, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + eventSignature, + }, + }: EventHandlerRequest<'SplitsSet(uint256,bytes32)'>): Promise { + const [rawAccountId, rawReceiversHash] = args as SplitsSetEvent.OutputTuple; + const accountId = convertToAccountId(rawAccountId); + + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( + [ + `📥 ${this.name} is processing ${eventSignature}:`, + ` - accountId: ${accountId}`, + ` - receiversHash: ${rawReceiversHash}`, + ` - logIndex: ${logIndex}`, + ` - txHash: ${transactionHash}`, + ].join('\n'), + ); + + await dbConnection.transaction(async (transaction) => { + const splitsSetEvent = await SplitsSetEventModel.create( + { + accountId, + receiversHash: rawReceiversHash, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + }, + { transaction }, + ); + + scopedLogger.bufferCreation({ + type: SplitsSetEventModel, + input: splitsSetEvent, + id: `${splitsSetEvent.transactionHash}-${splitsSetEvent.logIndex}`, + }); + + // Account’s splits are set by `AccountMetadataEmitted` events. + // The `SplitsSet` event only confirms that the split receivers are valid. + + await setIsValidFlag(splitsSetEvent, scopedLogger, transaction); + + scopedLogger.flush(); + }); + } +} diff --git a/src/eventHandlers/SplitsSetEvent/setIsValidFlag.ts b/src/eventHandlers/SplitsSetEvent/setIsValidFlag.ts new file mode 100644 index 0000000..a216b0f --- /dev/null +++ b/src/eventHandlers/SplitsSetEvent/setIsValidFlag.ts @@ -0,0 +1,194 @@ +import type { Transaction } from 'sequelize'; +import type { AccountId } from '../../core/types'; +import { + calcSubRepoDriverId, + isImmutableSplitsDriverId, + isNftDriverId, + isRepoDriverId, +} from '../../utils/accountIdUtils'; +import { + dripsContract, + nftDriverContract, + repoDriverContract, +} from '../../core/contractClients'; +import { formatSplitReceivers } from '../../utils/formatSplitReceivers'; +import RecoverableError from '../../utils/recoverableError'; +import { + ProjectModel, + DripListModel, + EcosystemMainAccountModel, + SubListModel, + SplitsReceiverModel, +} from '../../models'; +import type SplitsSetEventModel from '../../models/SplitsSetEventModel'; +import type ScopedLogger from '../../core/ScopedLogger'; +import unreachableError from '../../utils/unreachableError'; + +export default async function setIsValidFlag( + { accountId, receiversHash: eventReceiversHash }: SplitsSetEventModel, + scopedLogger: ScopedLogger, + transaction: Transaction, +): Promise { + const onChainReceiversHash = await dripsContract.splitsHash(accountId); + + // Only proceed if this event matches the latest on-chain hash. + if (eventReceiversHash !== onChainReceiversHash) { + scopedLogger.bufferMessage( + `Skipped setting 'isValid' flag for ${accountId}: on-chain splits hash '${onChainReceiversHash}' does not match event hash '${eventReceiversHash}'.`, + ); + + return; + } + + if (isRepoDriverId(accountId)) { + const project = await ProjectModel.findByPk(accountId, { + transaction, + lock: transaction.LOCK.UPDATE, + }); + + if (!project) { + throw new RecoverableError( + `Failed to set 'isValid' flag for Project: Project '${accountId}' not found. Likely waiting on 'AccountMetadataEmitted' event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + + const onChainOwner = await repoDriverContract.ownerOf(accountId); + const dbOwner = project.ownerAddress; // populated from metadata. + if (onChainOwner !== dbOwner) { + throw new RecoverableError( + `On-chain owner ${onChainOwner} does not match DB owner ${dbOwner} for Project '${accountId}'. Likely waiting on another event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + + const dbReceiversHash = await hashDbSplits(accountId, transaction); + const isValid = dbReceiversHash === onChainReceiversHash; + + project.isValid = isValid; + + scopedLogger.bufferUpdate({ + id: project.accountId, + type: ProjectModel, + input: project, + }); + + await project.save({ transaction }); + + if (!isValid) { + // Rethrow the error to trigger a retry. Eventually, the on-chain hash should match the DB hash. + throw new RecoverableError( + `On-chain splits hash '${onChainReceiversHash}' does not match DB splits hash '${dbReceiversHash}' for Project '${accountId}'. Likely waiting on another event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + } else if (isNftDriverId(accountId)) { + const dripList = await DripListModel.findByPk(accountId, { + transaction, + lock: transaction.LOCK.UPDATE, + }); + + const ecosystemMain = await EcosystemMainAccountModel.findByPk(accountId, { + transaction, + lock: transaction.LOCK.UPDATE, + }); + + const entity = dripList ?? ecosystemMain!; + const Model = dripList ? DripListModel : EcosystemMainAccountModel; + + if (!entity) { + throw new RecoverableError( + `Failed to set 'isValid' flag for ${Model.name}: ${Model.name} '${accountId}' not found.`, + ); + } + + if (dripList && ecosystemMain) { + unreachableError( + `Invariant violation: both Drip List and Ecosystem Main Account found for token '${accountId}'.`, + ); + } + + const onChainOwner = await nftDriverContract.ownerOf(accountId); + const dbOwner = entity.ownerAddress; + if (onChainOwner !== dbOwner) { + throw new RecoverableError( + `On-chain owner ${onChainOwner} does not match DB owner ${dbOwner} for ${Model.name} '${accountId}'. Likely waiting on another event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + + const dbReceiversHash = await hashDbSplits(accountId, transaction); + const isValid = dbReceiversHash === onChainReceiversHash; + + entity.isValid = isValid; + + scopedLogger.bufferUpdate({ + id: entity.accountId, + type: Model, + input: entity, + }); + + await entity.save({ transaction }); + + if (!isValid) { + // Rethrow the error to trigger a retry. Eventually, the on-chain hash should match the DB hash. + throw new RecoverableError( + `On-chain splits hash '${onChainReceiversHash}' does not match DB splits hash '${dbReceiversHash}' for ${Model.name} '${accountId}'. Likely waiting on another event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + } else if (isImmutableSplitsDriverId(accountId)) { + const subList = await SubListModel.findByPk(accountId, { + transaction, + lock: transaction.LOCK.UPDATE, + }); + + if (!subList) { + throw new RecoverableError( + `Failed to set 'isValid' flag for SubList: SubList '${accountId}' not found.`, + ); + } + + const dbReceiversHash = await hashDbSplits(accountId, transaction); + const isValid = dbReceiversHash === onChainReceiversHash; + + subList.isValid = isValid; + + scopedLogger.bufferUpdate({ + id: subList.accountId, + type: SubListModel, + input: subList, + }); + + await subList.save({ transaction }); + + if (!isValid) { + // Rethrow the error to trigger a retry. Eventually, the on-chain hash should match the DB hash. + throw new RecoverableError( + `On-chain splits hash '${onChainReceiversHash}' does not match DB splits hash '${dbReceiversHash}' for SubList '${accountId}'. Likely waiting on another event to be processed. Retrying, but if this persists, it is a real error.`, + ); + } + } +} + +async function hashDbSplits( + accountId: AccountId, + transaction: Transaction, +): Promise { + const rows = await SplitsReceiverModel.findAll({ + transaction, + lock: transaction.LOCK.UPDATE, + where: { senderAccountId: accountId }, + }); + + const receiverPromises = rows.map(async (s) => { + let receiverId = s.receiverAccountId; + if (s.splitsToRepoDriverSubAccount) { + receiverId = await calcSubRepoDriverId(s.receiverAccountId); + } + + return { + accountId: receiverId, + weight: s.weight, + }; + }); + + const receivers = await Promise.all(receiverPromises); + + return dripsContract.hashSplits(formatSplitReceivers(receivers)); +} diff --git a/src/eventHandlers/SplitsSetEventHandler/SplitsSetEventHandler.ts b/src/eventHandlers/SplitsSetEventHandler/SplitsSetEventHandler.ts deleted file mode 100644 index c716103..0000000 --- a/src/eventHandlers/SplitsSetEventHandler/SplitsSetEventHandler.ts +++ /dev/null @@ -1,76 +0,0 @@ -import EventHandlerBase from '../../events/EventHandlerBase'; -import LogManager from '../../core/LogManager'; -import { toAccountId } from '../../utils/accountIdUtils'; -import type EventHandlerRequest from '../../events/EventHandlerRequest'; -import { SplitsSetEventModel } from '../../models'; -import { dbConnection } from '../../db/database'; -import type { SplitsSetEvent } from '../../../contracts/CURRENT_NETWORK/Drips'; -import setIsValidFlag from './setIsValidFlag'; - -export default class SplitsSetEventHandler extends EventHandlerBase<'SplitsSet(uint256,bytes32)'> { - public eventSignatures = ['SplitsSet(uint256,bytes32)' as const]; - - protected async _handle( - request: EventHandlerRequest<'SplitsSet(uint256,bytes32)'>, - ): Promise { - const { - id: requestId, - event: { args, logIndex, blockNumber, blockTimestamp, transactionHash }, - } = request; - - const [rawAccountId, rawReceiversHash] = args as SplitsSetEvent.OutputTuple; - const accountId = toAccountId(rawAccountId); - - LogManager.logRequestInfo( - `📥 ${this.name} is processing the following ${request.event.eventSignature}: - \r\t - accountId: ${accountId} - \r\t - receiversHash: ${rawReceiversHash} - \r\t - logIndex: ${logIndex} - \r\t - tx hash: ${transactionHash}`, - requestId, - ); - - const logManager = new LogManager(requestId); - - const splitsSetEvent = await dbConnection.transaction( - async (transaction) => { - const [splitsSetEventModel, isEventCreated] = - await SplitsSetEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId, - receiversHash: rawReceiversHash, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - }); - - logManager.appendFindOrCreateLog( - SplitsSetEventModel, - isEventCreated, - `${splitsSetEventModel.transactionHash}-${splitsSetEventModel.logIndex}`, - ); - - return splitsSetEventModel; - }, - ); - - // Account's splits are set from `AccountMetadataEmitted` events. - // `SplitsSet` event only validates the splits receivers. - - try { - await setIsValidFlag(splitsSetEvent, logManager); - } catch (error: any) { - logManager.logAllInfo(); - - throw error; - } - } -} diff --git a/src/eventHandlers/SplitsSetEventHandler/setIsValidFlag.ts b/src/eventHandlers/SplitsSetEventHandler/setIsValidFlag.ts deleted file mode 100644 index 9538629..0000000 --- a/src/eventHandlers/SplitsSetEventHandler/setIsValidFlag.ts +++ /dev/null @@ -1,216 +0,0 @@ -import type { DripListId, RepoDriverId } from '../../core/types'; -import type { SplitsSetEventModel } from '../../models'; -import { - AddressDriverSplitReceiverModel, - DripListModel, - DripListSplitReceiverModel, - GitProjectModel, - RepoDriverSplitReceiverModel, -} from '../../models'; -import { isNftDriverId, isRepoDriverId } from '../../utils/accountIdUtils'; -import type { SplitsReceiverStruct } from '../../../contracts/CURRENT_NETWORK/Drips'; -import unreachableError from '../../utils/unreachableError'; -import { dripsContract } from '../../core/contractClients'; -import type LogManager from '../../core/LogManager'; -import { formatSplitReceivers } from '../AccountMetadataEmittedEvent/splitsValidator'; - -export default async function setIsValidFlag( - splitsSetEvent: SplitsSetEventModel, - logManager: LogManager, -): Promise { - const { accountId, receiversHash } = splitsSetEvent; - const onChainSplitsHash = await dripsContract.splitsHash(accountId); - - // Only if the `SplitsSet` event is the latest event (on-chain), we validate the splits. - if (receiversHash !== onChainSplitsHash) { - return; - } - - // Here, we know that the `SplitsSet` event is the latest event (on-chain). - - if (isRepoDriverId(accountId)) { - const project = await GitProjectModel.findByPk(accountId, { - lock: true, - }); - - if (!project) { - throw new Error( - `Failed to set 'isValid' flag for Project with ID '${accountId}': Project not found. - \r Possible reasons: - \r\t - The event that should have created the Project was not processed yet. - \r\t - The event was emitted as a result of a manual 'SetSplits' transaction that for a Project that does not exist in the app.`, - ); - } - - const storedInDbFromMetaReceiversHash = await dripsContract.hashSplits( - formatSplitReceivers(await getProjectDbReceivers(accountId)), - ); - - // If we reach this point, it means that `receiversHash` is the latest on-chain hash. - - if (receiversHash !== storedInDbFromMetaReceiversHash) { - project.isValid = false; - - logManager.appendUpdateLog(project, GitProjectModel, project.id); - - await project.save(); - - // We need to throw so that the job is retried... - throw new Error( - `Splits receivers hashes do not match for Project with ID '${accountId}': - \r\t - On-chain splits hash: ${onChainSplitsHash} - \r\t - 'SetSplits' event splits hash: ${receiversHash} - \r\t - DB (populated from metadata) splits hash: ${storedInDbFromMetaReceiversHash} - \r Possible reasons: - \r\t - The 'AccountMetadataEmitted' event that should have created the Project splits was not processed yet. - \r\t - The 'SetSplits' event (was manually emitted?) had splits that do not match what's already stored in the DB (from metadata).`, - ); - } else if (project.isValid === false) { - project.isValid = true; - - logManager.appendUpdateLog(project, GitProjectModel, project.id); - - await project.save(); - } - } else if (isNftDriverId(accountId)) { - const dripList = await DripListModel.findByPk(accountId, { - lock: true, - }); - - if (!dripList) { - throw new Error( - `Failed to set 'isValid' flag for Drip List with ID '${accountId}': Drip List not found. - \r Possible reasons: - \r\t - The event that should have created the Drip List was not processed yet. - \r\t - The event was emitted as a result of a manual 'SetSplits' transaction that for a Drip List that does not exist in the app.`, - ); - } - - const storedInDbFromMetaReceiversHash = await dripsContract.hashSplits( - formatSplitReceivers(await getDripListDbReceivers(accountId)), - ); - - // If we reach this point, it means that `receiversHash` is the latest on-chain hash. - - if (receiversHash !== storedInDbFromMetaReceiversHash) { - dripList.isValid = false; - - logManager.appendUpdateLog(dripList, DripListModel, dripList.id); - - await dripList.save(); - - // We need to throw so that the job is retried... - throw new Error( - `Splits receivers hashes do not match for Drip List with ID '${accountId}': - \r\t - On-chain splits hash: ${onChainSplitsHash} - \r\t - 'SetSplits' event splits hash: ${receiversHash} - \r\t - DB (populated from metadata) splits hash: ${storedInDbFromMetaReceiversHash} - \r Possible reasons: - \r\t - The 'AccountMetadataEmitted' event that should have created the Drip List splits was not processed yet. - \r\t - The 'SetSplits' event (was manually emitted?) had splits that do not match what's already stored in the DB (from metadata).`, - ); - } else if (dripList.isValid === false) { - dripList.isValid = true; - - logManager.appendUpdateLog(dripList, DripListModel, dripList.id); - - await dripList.save(); - } - } else { - logManager.appendLog( - `Skipping 'isValid' flag update for account with ID '${accountId}' because it's not a Project or a Drip List.`, - ); - } -} - -async function getProjectDbReceivers(accountId: RepoDriverId) { - const addressReceivers: SplitsReceiverStruct[] = - await AddressDriverSplitReceiverModel.findAll({ - lock: true, - - where: { - funderProjectId: accountId, - }, - }).then((receivers) => - receivers.map((receiver) => ({ - accountId: receiver.fundeeAccountId ?? unreachableError(), - weight: receiver.weight, - })), - ); - - const projectReceivers: SplitsReceiverStruct[] = - await RepoDriverSplitReceiverModel.findAll({ - lock: true, - - where: { - funderProjectId: accountId, - }, - }).then((receivers) => - receivers.map((receiver) => ({ - accountId: receiver.fundeeProjectId ?? unreachableError(), - weight: receiver.weight, - })), - ); - - const dripListReceivers: SplitsReceiverStruct[] = - await DripListSplitReceiverModel.findAll({ - lock: true, - - where: { - funderProjectId: accountId, - }, - }).then((receivers) => - receivers.map((receiver) => ({ - accountId: receiver.fundeeDripListId ?? unreachableError(), - weight: receiver.weight, - })), - ); - - return [...addressReceivers, ...projectReceivers, ...dripListReceivers]; -} - -async function getDripListDbReceivers(accountId: DripListId) { - const addressReceivers: SplitsReceiverStruct[] = - await AddressDriverSplitReceiverModel.findAll({ - lock: true, - - where: { - funderDripListId: accountId, - }, - }).then((receivers) => - receivers.map((receiver) => ({ - accountId: receiver.fundeeAccountId ?? unreachableError(), - weight: receiver.weight, - })), - ); - - const projectReceivers: SplitsReceiverStruct[] = - await RepoDriverSplitReceiverModel.findAll({ - lock: true, - - where: { - funderDripListId: accountId, - }, - }).then((receivers) => - receivers.map((receiver) => ({ - accountId: receiver.fundeeProjectId ?? unreachableError(), - weight: receiver.weight, - })), - ); - - const dripListReceivers: SplitsReceiverStruct[] = - await DripListSplitReceiverModel.findAll({ - lock: true, - - where: { - funderDripListId: accountId, - }, - }).then((receivers) => - receivers.map((receiver) => ({ - accountId: receiver.fundeeDripListId ?? unreachableError(), - weight: receiver.weight, - })), - ); - - return [...addressReceivers, ...projectReceivers, ...dripListReceivers]; -} diff --git a/src/eventHandlers/SqueezedStreamsEventHandler.ts b/src/eventHandlers/SqueezedStreamsEventHandler.ts index 8ac633a..791e904 100644 --- a/src/eventHandlers/SqueezedStreamsEventHandler.ts +++ b/src/eventHandlers/SqueezedStreamsEventHandler.ts @@ -1,6 +1,6 @@ import EventHandlerBase from '../events/EventHandlerBase'; -import LogManager from '../core/LogManager'; -import { toAccountId } from '../utils/accountIdUtils'; +import ScopedLogger from '../core/ScopedLogger'; +import { convertToAccountId } from '../utils/accountIdUtils'; import type EventHandlerRequest from '../events/EventHandlerRequest'; import { dbConnection } from '../db/database'; import type { SqueezedStreamsEvent } from '../../contracts/CURRENT_NETWORK/Drips'; @@ -29,14 +29,16 @@ export default class SqueezedStreamsEventHandler extends EventHandlerBase<'Squee rawStreamsHistoryHashes, ] = args as SqueezedStreamsEvent.OutputTuple; - const accountId = toAccountId(rawAccountId); + const accountId = convertToAccountId(rawAccountId); const erc20 = toAddress(rawErc20); - const senderId = toAccountId(rawSenderId); + const senderId = convertToAccountId(rawSenderId); const amt = toBigIntString(rawAmt.toString()); const streamsHistoryHashes = SqueezedStreamsEventModel.toStreamHistoryHashes(rawStreamsHistoryHashes); - LogManager.logRequestInfo( + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( `📥 ${this.name} is processing the following ${request.event.eventSignature}: \r\t - accountId: ${accountId} \r\t - erc20: ${erc20} @@ -45,40 +47,31 @@ export default class SqueezedStreamsEventHandler extends EventHandlerBase<'Squee \r\t - streamsHistoryHashes: ${streamsHistoryHashes} \r\t - logIndex: ${logIndex} \r\t - tx hash: ${transactionHash}`, - requestId, ); await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [transferEvent, isEventCreated] = - await SqueezedStreamsEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId, - erc20, - senderId, - amount: amt, - streamsHistoryHashes, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - }); - - logManager.appendFindOrCreateLog( - SqueezedStreamsEventModel, - isEventCreated, - `${transferEvent.transactionHash}-${transferEvent.logIndex}`, + const transferEvent = await SqueezedStreamsEventModel.create( + { + accountId, + erc20, + senderId, + amount: amt, + streamsHistoryHashes, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + }, + { transaction }, ); - logManager.logAllInfo(); + scopedLogger.bufferCreation({ + input: transferEvent, + type: SqueezedStreamsEventModel, + id: `${transferEvent.transactionHash}-${transferEvent.logIndex}`, + }); + + scopedLogger.flush(); }); } } diff --git a/src/eventHandlers/StreamReceiverSeenEventHandler.ts b/src/eventHandlers/StreamReceiverSeenEventHandler.ts index 10209f6..4f82cf1 100644 --- a/src/eventHandlers/StreamReceiverSeenEventHandler.ts +++ b/src/eventHandlers/StreamReceiverSeenEventHandler.ts @@ -1,13 +1,13 @@ import type { StreamReceiverSeenEvent } from '../../contracts/CURRENT_NETWORK/Drips'; -import LogManager from '../core/LogManager'; +import ScopedLogger from '../core/ScopedLogger'; import type { AccountId } from '../core/types'; import { dbConnection } from '../db/database'; import EventHandlerBase from '../events/EventHandlerBase'; import type EventHandlerRequest from '../events/EventHandlerRequest'; import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; -import { toAccountId } from '../utils/accountIdUtils'; +import { convertToAccountId } from '../utils/accountIdUtils'; import { toBigIntString } from '../utils/bigintUtils'; -import { getCurrentSplitsByReceiversHash } from '../utils/getCurrentSplits'; +import { getCurrentSplitReceiversByReceiversHash } from './AccountMetadataEmittedEvent/receiversRepository'; export default class StreamReceiverSeenEventHandler extends EventHandlerBase<'StreamReceiverSeen(bytes32,uint256,uint256)'> { public eventSignatures = [ @@ -25,63 +25,69 @@ export default class StreamReceiverSeenEventHandler extends EventHandlerBase<'St const [rawReceiversHash, rawAccountId, rawConfig] = args as StreamReceiverSeenEvent.OutputTuple; - const accountId = toAccountId(rawAccountId); + const accountId = convertToAccountId(rawAccountId); const config = toBigIntString(rawConfig.toString()); - LogManager.logRequestInfo( + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( `📥 ${this.name} is processing the following ${request.event.eventSignature}: \r\t - receiversHash: ${rawReceiversHash} \r\t - accountId: ${accountId} \r\t - config: ${config} \r\t - logIndex: ${logIndex} \r\t - tx hash: ${transactionHash}`, - requestId, ); await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [streamReceiverSeenEvent, isEventCreated] = - await StreamReceiverSeenEventModel.findOrCreate({ - lock: true, + const streamReceiverSeenEvent = await StreamReceiverSeenEventModel.create( + { + receiversHash: rawReceiversHash, + accountId, + config, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + }, + { transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - receiversHash: rawReceiversHash, - accountId, - config, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - }); - - logManager.appendFindOrCreateLog( - StreamReceiverSeenEventModel, - isEventCreated, - `${streamReceiverSeenEvent.transactionHash}-${streamReceiverSeenEvent.logIndex}`, + }, ); + + scopedLogger.bufferCreation({ + type: StreamReceiverSeenEventModel, + input: streamReceiverSeenEvent, + id: `${streamReceiverSeenEvent.transactionHash}-${streamReceiverSeenEvent.logIndex}`, + }); }); } - public override async beforeHandle( - request: EventHandlerRequest<'StreamReceiverSeen(bytes32,uint256,uint256)'>, - ): Promise<{ + public override async beforeHandle({ + event: { args }, + id: requestId, + }: EventHandlerRequest<'StreamReceiverSeen(bytes32,uint256,uint256)'>): Promise<{ accountIdsToInvalidate: AccountId[]; }> { - const { - event: { args }, - } = request; + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log(`${this.name} is gathering accountIds to invalidate...`); const [rawReceiversHash] = args as StreamReceiverSeenEvent.OutputTuple; + const accountIdsToInvalidate = + await getCurrentSplitReceiversByReceiversHash(rawReceiversHash); + + scopedLogger.log( + `${this.name} account IDs to invalidate: ${ + accountIdsToInvalidate.length + ? accountIdsToInvalidate.join(', ') + : 'none' + }`, + ); + return { - accountIdsToInvalidate: - await getCurrentSplitsByReceiversHash(rawReceiversHash), + accountIdsToInvalidate, }; } } diff --git a/src/eventHandlers/StreamsSetEventHandler.ts b/src/eventHandlers/StreamsSetEventHandler.ts index 98445b3..a947c20 100644 --- a/src/eventHandlers/StreamsSetEventHandler.ts +++ b/src/eventHandlers/StreamsSetEventHandler.ts @@ -1,10 +1,10 @@ import type { StreamsSetEvent } from '../../contracts/CURRENT_NETWORK/Drips'; -import LogManager from '../core/LogManager'; +import ScopedLogger from '../core/ScopedLogger'; import { dbConnection } from '../db/database'; import EventHandlerBase from '../events/EventHandlerBase'; import type EventHandlerRequest from '../events/EventHandlerRequest'; import StreamsSetEventModel from '../models/StreamsSetEventModel'; -import { toAccountId } from '../utils/accountIdUtils'; +import { convertToAccountId } from '../utils/accountIdUtils'; import { toBigIntString } from '../utils/bigintUtils'; export default class StreamsSetEventHandler extends EventHandlerBase<'StreamsSet(uint256,address,bytes32,bytes32,uint128,uint32)'> { @@ -29,11 +29,13 @@ export default class StreamsSetEventHandler extends EventHandlerBase<'StreamsSet rawMaxEnd, ] = args as StreamsSetEvent.OutputTuple; - const accountId = toAccountId(rawAccountId); + const accountId = convertToAccountId(rawAccountId); const balance = toBigIntString(rawBalance.toString()); const maxEnd = toBigIntString(rawMaxEnd.toString()); - LogManager.logRequestInfo( + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( `📥 ${this.name} is processing the following ${request.event.eventSignature}: \r\t - accountId: ${accountId} \r\t - erc20: ${rawErc20} @@ -43,39 +45,34 @@ export default class StreamsSetEventHandler extends EventHandlerBase<'StreamsSet \r\t - maxEnd: ${maxEnd} \r\t - logIndex: ${logIndex} \r\t - tx hash: ${transactionHash}`, - requestId, ); await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [streamsSetEvent, isEventCreated] = - await StreamsSetEventModel.findOrCreate({ - lock: true, + const streamsSetEvent = await StreamsSetEventModel.create( + { + accountId, + erc20: rawErc20, + receiversHash: rawReceiversHash, + streamsHistoryHash: rawStreamsHistoryHash, + balance, + maxEnd, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + }, + { transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId, - erc20: rawErc20, - receiversHash: rawReceiversHash, - streamsHistoryHash: rawStreamsHistoryHash, - balance, - maxEnd, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - }); - - logManager.appendFindOrCreateLog( - StreamsSetEventModel, - isEventCreated, - `${streamsSetEvent.transactionHash}-${streamsSetEvent.logIndex}`, + }, ); + + scopedLogger.bufferCreation({ + type: StreamsSetEventModel, + input: streamsSetEvent, + id: `${streamsSetEvent.transactionHash}-${streamsSetEvent.logIndex}`, + }); + + scopedLogger.flush(); }); } } diff --git a/src/eventHandlers/TransferEventHandler.ts b/src/eventHandlers/TransferEventHandler.ts index 048ed67..00afc90 100644 --- a/src/eventHandlers/TransferEventHandler.ts +++ b/src/eventHandlers/TransferEventHandler.ts @@ -1,146 +1,183 @@ import { ZeroAddress } from 'ethers'; import type { TransferEvent } from '../../contracts/CURRENT_NETWORK/NftDriver'; import EventHandlerBase from '../events/EventHandlerBase'; -import LogManager from '../core/LogManager'; -import { calcAccountId, toNftDriverId } from '../utils/accountIdUtils'; +import ScopedLogger from '../core/ScopedLogger'; +import { convertToNftDriverId } from '../utils/accountIdUtils'; import type EventHandlerRequest from '../events/EventHandlerRequest'; -import { DripListModel, TransferEventModel } from '../models'; +import { + DripListModel, + EcosystemMainAccountModel, + TransferEventModel, +} from '../models'; import { dbConnection } from '../db/database'; -import { isLatestEvent } from '../utils/eventUtils'; +import RecoverableError from '../utils/recoverableError'; +import type { Address, AddressDriverId } from '../core/types'; +import { + addressDriverContract, + nftDriverContract, +} from '../core/contractClients'; +import unreachableError from '../utils/unreachableError'; import appSettings from '../config/appSettings'; +import { makeVersion } from '../utils/lastProcessedVersion'; export default class TransferEventHandler extends EventHandlerBase<'Transfer(address,address,uint256)'> { public eventSignatures = ['Transfer(address,address,uint256)' as const]; - protected async _handle( - request: EventHandlerRequest<'Transfer(address,address,uint256)'>, - ): Promise { - const { - id: requestId, - event: { args, logIndex, blockNumber, blockTimestamp, transactionHash }, - } = request; - - const [from, to, tokenId] = args as TransferEvent.OutputTuple; - - const id = toNftDriverId(tokenId); - - LogManager.logRequestInfo( - `📥 ${this.name} is processing the following ${request.event.eventSignature}: - \r\t - from: ${from} - \r\t - to: ${to} - \r\t - tokenId: ${tokenId} - \r\t - logIndex: ${logIndex} - \r\t - tx hash: ${transactionHash}`, - requestId, + protected async _handle({ + id: requestId, + event: { + args, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + eventSignature, + }, + }: EventHandlerRequest<'Transfer(address,address,uint256)'>): Promise { + const [from, to, rawTokenId] = args as TransferEvent.OutputTuple; + const tokenId = convertToNftDriverId(rawTokenId); + + const isMint = from === ZeroAddress; + + const scopedLogger = new ScopedLogger(this.name, requestId); + + scopedLogger.log( + [ + `📥 ${this.name} is processing ${eventSignature}:`, + ` - from: ${from}`, + ` - to: ${to}`, + ` - tokenId: ${rawTokenId}`, + ` - logIndex: ${logIndex}`, + ` - txHash: ${transactionHash}`, + ].join('\n'), ); await dbConnection.transaction(async (transaction) => { - const logManager = new LogManager(requestId); - - const [transferEvent, isEventCreated] = - await TransferEventModel.findOrCreate({ - lock: true, - transaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - tokenId: id, - to, - from, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - }); - - logManager.appendFindOrCreateLog( - TransferEventModel, - isEventCreated, - `${transferEvent.transactionHash}-${transferEvent.logIndex}`, + const transferEvent = await TransferEventModel.create( + { + tokenId, + to: to as Address, + from: from as Address, + logIndex, + blockNumber, + blockTimestamp, + transactionHash, + }, + { transaction }, ); - const { visibilityThresholdBlockNumber } = appSettings; + scopedLogger.bufferCreation({ + type: TransferEventModel, + id: `${transactionHash}-${logIndex}`, + input: transferEvent, + }); - // This must be the only place a Drip List is created. - const [dripList, isDripListCreated] = await DripListModel.findOrCreate({ + const dripList = await DripListModel.findByPk(tokenId, { transaction, - lock: true, - where: { - id, - }, - defaults: { - id, - creator: to, // TODO: https://github.com/drips-network/events-processor/issues/14 - isValid: true, // There are no receivers yet, so the drip list is valid. - ownerAddress: to, - ownerAccountId: await calcAccountId(to), - previousOwnerAddress: from, - - isVisible: - blockNumber > visibilityThresholdBlockNumber - ? from === ZeroAddress // If it's a mint, then the Drip List will be visible. If it's a real transfer, then it's not. - : true, // If the block number is less than the visibility threshold, then the Drip List is visible by default. - }, + lock: transaction.LOCK.UPDATE, }); - if (isDripListCreated) { - logManager - .appendFindOrCreateLog(DripListModel, isDripListCreated, dripList.id) - .logAllInfo(); + const ecosystemMainAccount = await EcosystemMainAccountModel.findByPk( + tokenId, + { + transaction, + lock: transaction.LOCK.UPDATE, + }, + ); - return; + const entity = dripList ?? ecosystemMainAccount; + const Model = dripList ? DripListModel : EcosystemMainAccountModel; + + if (!entity) { + scopedLogger.flush(); + + throw new RecoverableError( + `Cannot process '${eventSignature}' event for Drip List or Ecosystem Main Account ${tokenId}: entity not found. Likely waiting on 'AccountMetadata' event to be processed. Retrying, but if this persists, it is a real error.`, + ); } - // Here, the Drip List already exists. - // Only if the event is the latest (in the DB), we process its data. - // After all events are processed, the Drip List will be updated with the latest values. - if ( - !(await isLatestEvent( - transferEvent, - TransferEventModel, - { - transactionHash, - logIndex, - tokenId, - }, - transaction, - )) - ) { - logManager.logAllInfo(); + if (dripList && ecosystemMainAccount) { + unreachableError( + `Invariant violation: both Drip List and Ecosystem Main Account found for token '${tokenId}'.`, + ); + } + + const newVersion = makeVersion(blockNumber, logIndex); + const storedVersion = BigInt(entity.lastProcessedVersion); + + if (isMint) { + entity.creator = to as Address; + + scopedLogger.bufferUpdate({ + type: Model, + id: entity.accountId, + input: entity, + }); + + await entity.save({ transaction }); + } + + const onChainOwner = (await nftDriverContract.ownerOf( + tokenId, + )) as Address; + + if (to !== onChainOwner) { + scopedLogger.bufferMessage( + `Skipped Drip List or Ecosystem Main Account ${tokenId} '${eventSignature}' event processing: event is not the latest (on-chain owner '${onChainOwner}' does not match 'to' '${to}').`, + ); + + scopedLogger.flush(); return; } - dripList.ownerAddress = to; - dripList.previousOwnerAddress = from; - dripList.ownerAccountId = await calcAccountId(to); + // Update to the latest on-chain state. + entity.ownerAddress = onChainOwner; // Equal to `to`. + entity.ownerAccountId = ( + await addressDriverContract.calcAccountId(onChainOwner) + ).toString() as AddressDriverId; // Equal to `to`. + entity.previousOwnerAddress = from as Address; + + // Safely update fields that another event handler could also modify. + if (newVersion > storedVersion) { + entity.isVisible = + blockNumber > appSettings.visibilityThresholdBlockNumber + ? from === ZeroAddress // If it's a mint, then the Drip List will be visible. If it's a real transfer, then it's not. + : true; // If the block number is less than the visibility threshold, then the Drip List is visible by default. + } - // This is real transfer. The Drip List should not be visible unless the block number is less than the visibility threshold. - dripList.isVisible = blockNumber < visibilityThresholdBlockNumber; + entity.lastProcessedVersion = newVersion.toString(); - logManager - .appendIsLatestEventLog() - .appendUpdateLog(dripList, DripListModel, dripList.id); + scopedLogger.bufferUpdate({ + type: Model, + id: entity.accountId, + input: entity, + }); - await dripList.save({ transaction }); + await entity.save({ transaction }); - logManager.logAllInfo(); + scopedLogger.flush(); }); } override async afterHandle(context: { args: [from: string, to: string, tokenId: bigint]; blockTimestamp: Date; + requestId: string; }): Promise { - const { args, blockTimestamp } = context; - const [from, to, tokenId] = args; - + const [from, to, tokenId] = context.args; await super.afterHandle({ - args: [tokenId, await calcAccountId(from), await calcAccountId(to)], - blockTimestamp, + args: [ + tokenId, + ( + await addressDriverContract.calcAccountId(from) + ).toString() as AddressDriverId, + ( + await addressDriverContract.calcAccountId(to) + ).toString() as AddressDriverId, + ], + blockTimestamp: context.blockTimestamp, + requestId: context.requestId, }); } } diff --git a/src/eventHandlers/index.ts b/src/eventHandlers/index.ts index 34e188a..e2f5eff 100644 --- a/src/eventHandlers/index.ts +++ b/src/eventHandlers/index.ts @@ -1,10 +1,7 @@ export { default as GivenEventHandler } from './GivenEventHandler'; export { default as SplitEventHandler } from './SplitEventHandler'; -export { default as StreamsSetEventHandler } from './StreamsSetEventHandler'; export { default as TransferEventHandler } from './TransferEventHandler'; -export { default as OwnerUpdatedEventHandler } from './OwnerUpdatedEventHandler'; +export { default as StreamsSetEventHandler } from './StreamsSetEventHandler'; export { default as SqueezedStreamsEventHandler } from './SqueezedStreamsEventHandler'; export { default as StreamReceiverSeenEventHandler } from './StreamReceiverSeenEventHandler'; -export { default as SplitsSetEventHandler } from './SplitsSetEventHandler/SplitsSetEventHandler'; -export { default as OwnerUpdateRequestedEventHandler } from './OwnerUpdateRequestedEventHandler'; export { default as AccountMetadataEmittedEventHandler } from './AccountMetadataEmittedEvent/AccountMetadataEmittedEventHandler'; diff --git a/src/events/EventHandlerBase.ts b/src/events/EventHandlerBase.ts index c4ff740..03b3df4 100644 --- a/src/events/EventHandlerBase.ts +++ b/src/events/EventHandlerBase.ts @@ -1,9 +1,10 @@ import { isAddress } from 'ethers'; +import { BaseError } from 'sequelize'; import appSettings from '../config/appSettings'; import logger from '../core/logger'; import type { AccountId, Result } from '../core/types'; import saveEventProcessingJob from '../queue/saveEventProcessingJob'; -import { toAccountId } from '../utils/accountIdUtils'; +import { convertToAccountId } from '../utils/accountIdUtils'; import getResult from '../utils/getResult'; import type EventHandlerRequest from './EventHandlerRequest'; import type { EventSignature } from './types'; @@ -19,7 +20,7 @@ export default abstract class EventHandlerBase { protected abstract _handle(request: EventHandlerRequest): Promise; public async createJob(request: EventHandlerRequest): Promise { - await saveEventProcessingJob(request, request.event.eventSignature); + await saveEventProcessingJob(request); } /** @@ -31,6 +32,12 @@ export default abstract class EventHandlerBase { const result = await getResult(this._handle.bind(this))(request); if (!result.ok) { + if (result.error instanceof BaseError) { + logger.error( + `[${request.id}] ${this.name} failed to process event: ${JSON.stringify(result.error, null, 2)}`, + ); + } + throw result.error; } @@ -47,8 +54,9 @@ export default abstract class EventHandlerBase { public async afterHandle(context: { args: any[]; blockTimestamp: Date; + requestId: string; }): Promise { - const { args, blockTimestamp } = context; + const { args, blockTimestamp, requestId } = context; // If the block is older than 15 minutes, we don't invalidate the cache to avoid unnecessary requests while indexing. if (new Date(blockTimestamp).getTime() < Date.now() - 15 * 60000) { @@ -64,7 +72,7 @@ export default abstract class EventHandlerBase { for (const arg of args) { if (!isAddress(arg)) { try { - const accountId = toAccountId(arg); + const accountId = convertToAccountId(arg); if (!accountIds.includes(accountId)) { accountIds.push(accountId); } @@ -85,14 +93,16 @@ export default abstract class EventHandlerBase { }); logger.info( - `'${ + `[${requestId}]'${ this.name }' invalidated cache entries for accountIds: ${accountIds.join( ', ', )}`, ); } catch (error: any) { - logger.error(`Failed to invalidate cache: ${error.message}`); + logger.error( + `[${requestId}] Failed to invalidate cache: ${error.message}`, + ); } } } diff --git a/src/events/EventHandlerRequest.ts b/src/events/EventHandlerRequest.ts index 7ef6ea2..b10a00c 100644 --- a/src/events/EventHandlerRequest.ts +++ b/src/events/EventHandlerRequest.ts @@ -1,12 +1,10 @@ -import type { UUID } from 'crypto'; -import { randomUUID } from 'crypto'; import type { EventData, EventSignature } from './types'; export default class EventHandlerRequest { - public readonly id: UUID; + public readonly id: string; public readonly event: EventData; - constructor(event: EventData, id: UUID = randomUUID()) { + constructor(event: EventData, id: string) { this.id = id; this.event = event; } diff --git a/src/events/poll.ts b/src/events/poll.ts index fc8481f..ca080bc 100644 --- a/src/events/poll.ts +++ b/src/events/poll.ts @@ -6,20 +6,20 @@ import type { Address, KnownAny } from '../core/types'; import EventHandlerRequest from './EventHandlerRequest'; import type EventHandlerBase from './EventHandlerBase'; import type { EventSignature } from './types'; -import _LastIndexedBlockModel from '../models/_LastIndexedBlockModel'; +import LastIndexedBlockModel from '../models/LastIndexedBlockModel'; import logger from '../core/logger'; import appSettings from '../config/appSettings'; async function getLatestIndexedBlock() { - const record = await _LastIndexedBlockModel.findOne({ - order: [['blockNumber', 'DESC']], + const record = await LastIndexedBlockModel.findOne({ + order: [['block_number', 'DESC']], }); return record?.blockNumber ? Number(record.blockNumber) : 0; } function setLatestIndexedBlock(blockNumber: number) { - return _LastIndexedBlockModel.upsert({ + return LastIndexedBlockModel.upsert({ id: 1, blockNumber: BigInt(blockNumber), }); @@ -86,14 +86,19 @@ export default async function poll( ); await handler?.createJob( - new EventHandlerRequest({ - logIndex: log.index, - blockNumber: log.blockNumber, - blockTimestamp: new Date((await log.getBlock()).timestamp * 1000), - transactionHash: log.transactionHash, - args: parsedLog.args as KnownAny, - eventSignature: signature, - }), + new EventHandlerRequest( + { + logIndex: log.index, + blockNumber: log.blockNumber, + blockTimestamp: new Date( + (await log.getBlock()).timestamp * 1000, + ), + transactionHash: log.transactionHash, + args: parsedLog.args as KnownAny, + eventSignature: signature, + }, + `${log.blockNumber}:${log.transactionHash}:${log.index}`, + ), ); } }), diff --git a/src/events/registrations.ts b/src/events/registrations.ts index ab36fcf..7f45011 100644 --- a/src/events/registrations.ts +++ b/src/events/registrations.ts @@ -1,33 +1,17 @@ import { AccountMetadataEmittedEventHandler, GivenEventHandler, - OwnerUpdateRequestedEventHandler, - OwnerUpdatedEventHandler, SplitEventHandler, - SplitsSetEventHandler, TransferEventHandler, StreamReceiverSeenEventHandler, StreamsSetEventHandler, SqueezedStreamsEventHandler, } from '../eventHandlers'; +import OwnerUpdatedEventHandler from '../eventHandlers/OwnerUpdatedEventHandler'; +import SplitsSetEventHandler from '../eventHandlers/SplitsSetEvent/SplitsSetEventHandler'; import { registerEventHandler } from './eventHandlerUtils'; export function registerEventHandlers(): void { - registerEventHandler< - | 'OwnerUpdateRequested(uint256,uint8,bytes,address)' - | 'OwnerUpdateRequested(uint256,uint8,bytes)' - >( - [ - 'OwnerUpdateRequested(uint256,uint8,bytes,address)', - 'OwnerUpdateRequested(uint256,uint8,bytes)', - ], - OwnerUpdateRequestedEventHandler, - ); - - registerEventHandler<'OwnerUpdated(uint256,address)'>( - 'OwnerUpdated(uint256,address)', - OwnerUpdatedEventHandler, - ); registerEventHandler<'AccountMetadataEmitted(uint256,bytes32,bytes)'>( 'AccountMetadataEmitted(uint256,bytes32,bytes)', AccountMetadataEmittedEventHandler, @@ -44,14 +28,14 @@ export function registerEventHandlers(): void { 'Split(uint256,uint256,address,uint128)', SplitEventHandler, ); - registerEventHandler<'SplitsSet(uint256,bytes32)'>( - 'SplitsSet(uint256,bytes32)', - SplitsSetEventHandler, - ); registerEventHandler<'StreamsSet(uint256,address,bytes32,bytes32,uint128,uint32)'>( 'StreamsSet(uint256,address,bytes32,bytes32,uint128,uint32)', StreamsSetEventHandler, ); + registerEventHandler<'SplitsSet(uint256,bytes32)'>( + 'SplitsSet(uint256,bytes32)', + SplitsSetEventHandler, + ); registerEventHandler<'StreamReceiverSeen(bytes32,uint256,uint256)'>( 'StreamReceiverSeen(bytes32,uint256,uint256)', StreamReceiverSeenEventHandler, @@ -60,4 +44,8 @@ export function registerEventHandlers(): void { 'SqueezedStreams(uint256,address,uint256,uint128,bytes32[])', SqueezedStreamsEventHandler, ); + registerEventHandler<'OwnerUpdated(uint256,address)'>( + 'OwnerUpdated(uint256,address)', + OwnerUpdatedEventHandler, + ); } diff --git a/src/events/types.ts b/src/events/types.ts index cd3ff3a..a7f9a5f 100644 --- a/src/events/types.ts +++ b/src/events/types.ts @@ -2,6 +2,7 @@ import type EventHandlerBase from './EventHandlerBase'; import type { ValuesOf } from '../core/types'; import type { AnyChainDripsFilters, + AnyChainImmutableSplitsDriverFilters, AnyChainNftDriverFilters, AnyChainRepoDriverFilters, AnyChainTypedLogDescription, @@ -10,11 +11,14 @@ import type { // flat object type with all keys and values from the above type AllFilters = AnyChainDripsFilters & AnyChainNftDriverFilters & - AnyChainRepoDriverFilters; + AnyChainRepoDriverFilters & + AnyChainImmutableSplitsDriverFilters; export type DripsContractEvent = ValuesOf; export type NftDriverContractEvent = ValuesOf; export type RepoDriverContractEvent = ValuesOf; +export type ImmutableSplitsDriverContractEvent = + ValuesOf; type OnlySignatures = T extends `${infer Prefix}(${infer Suffix})` ? `${Prefix}(${Suffix})` diff --git a/src/health.ts b/src/health.ts index 3c0ef40..af9f7be 100644 --- a/src/health.ts +++ b/src/health.ts @@ -1,7 +1,7 @@ import type { RequestHandler } from 'express'; import logger from './core/logger'; import getProvider from './core/getProvider'; -import _LastIndexedBlockModel from './models/_LastIndexedBlockModel'; +import LastIndexedBlockModel from './models/LastIndexedBlockModel'; export const healthEndpoint: RequestHandler = async (req, res) => { const HEALTH_THRESHOLD = 10; @@ -10,7 +10,7 @@ export const healthEndpoint: RequestHandler = async (req, res) => { const provider = getProvider(); const latestChainBlock = await provider.getBlockNumber(); - const lastIndexedBlockRecord = await _LastIndexedBlockModel.findOne({ + const lastIndexedBlockRecord = await LastIndexedBlockModel.findOne({ order: [['blockNumber', 'DESC']], }); @@ -21,7 +21,7 @@ export const healthEndpoint: RequestHandler = async (req, res) => { const blockDifference = latestChainBlock - lastIndexedBlock; if (blockDifference < HEALTH_THRESHOLD) { - return res.status(200).send({ + res.status(200).send({ status: 'OK', latestChainBlock, lastIndexedBlock, @@ -32,7 +32,7 @@ export const healthEndpoint: RequestHandler = async (req, res) => { logger.warn( `Health check failed: Service is ${blockDifference} blocks behind (Threshold: ${HEALTH_THRESHOLD}).`, ); - return res.status(503).send({ + res.status(503).send({ status: 'Unhealthy', latestChainBlock, lastIndexedBlock, @@ -41,11 +41,9 @@ export const healthEndpoint: RequestHandler = async (req, res) => { }); } catch (error: any) { logger.error(`Health check endpoint error: ${error.message}`, error); - return res - .status(500) - .send({ - status: 'Error', - message: 'Internal server error during health check.', - }); + res.status(500).send({ + status: 'Error', + message: 'Internal server error during health check.', + }); } }; diff --git a/src/index.ts b/src/index.ts index 57b2696..ef0db74 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import express from 'express'; - import logger from './core/logger'; + import appSettings from './config/appSettings'; import initJobProcessingQueue from './queue/initJobProcessingQueue'; import { arenaConfig } from './queue/queueMonitoring'; @@ -22,7 +22,10 @@ import networkConstant from '../contracts/CURRENT_NETWORK/network-constant'; import { healthEndpoint } from './health'; process.on('uncaughtException', (error: Error) => { - logger.error(`Uncaught Exception: ${error.message}`); + logger.error('Uncaught Exception', { + message: error.message, + stack: error.stack, + }); // Railway will restart the process if it exits with a non-zero exit code. process.exit(1); @@ -80,9 +83,9 @@ async function init() { app.use('/health', healthEndpoint); } - app.listen(appSettings.monitoringUiPort, () => { + app.listen(appSettings.queueUiPort, () => { logger.info( - `Monitoring available on port ${appSettings.monitoringUiPort}. Routes: /health, /arena`, + `Monitoring available on port ${appSettings.queueUiPort}. Routes: /health, /arena`, ); }); } diff --git a/src/metadata/schemas/common/repoSubAccountDriverSplitReceiverSchema.ts b/src/metadata/schemas/common/repoSubAccountDriverSplitReceiverSchema.ts new file mode 100644 index 0000000..7deb5f5 --- /dev/null +++ b/src/metadata/schemas/common/repoSubAccountDriverSplitReceiverSchema.ts @@ -0,0 +1,10 @@ +import z from 'zod'; +import { sourceSchema } from './sources'; + +// Here, until there is a need to create specific `RepoSubAccountDriver` metadata. +export const repoSubAccountDriverSplitReceiverSchema = z.object({ + type: z.literal('repoSubAccountDriver'), + weight: z.number(), + accountId: z.string(), + source: sourceSchema, +}); diff --git a/src/metadata/schemas/immutable-splits-driver/v1.ts b/src/metadata/schemas/immutable-splits-driver/v1.ts new file mode 100644 index 0000000..171668f --- /dev/null +++ b/src/metadata/schemas/immutable-splits-driver/v1.ts @@ -0,0 +1,41 @@ +import z from 'zod'; +import { addressDriverSplitReceiverSchema } from '../repo-driver/v2'; +import { dripListSplitReceiverSchema } from '../nft-driver/v2'; +import { repoSubAccountDriverSplitReceiverSchema } from '../common/repoSubAccountDriverSplitReceiverSchema'; + +export const subListSplitReceiverSchema = z.object({ + type: z.literal('subList'), + weight: z.number(), + accountId: z.string(), +}); + +export const subListMetadataSchemaV1 = z.object({ + driver: z.literal('immutable-splits'), + type: z.literal('subList'), + recipients: z.array( + z.union([ + addressDriverSplitReceiverSchema, + dripListSplitReceiverSchema, + repoSubAccountDriverSplitReceiverSchema, + subListSplitReceiverSchema, + ]), + ), + parent: z.object({ + accountId: z.string(), + driver: z.union([z.literal('nft'), z.literal('immutable-splits')]), + type: z.union([ + z.literal('dripList'), + z.literal('ecosystem'), + z.literal('subList'), + ]), + }), + root: z.object({ + accountId: z.string(), + driver: z.union([z.literal('nft'), z.literal('immutable-splits')]), + type: z.union([ + z.literal('dripList'), + z.literal('ecosystem'), + z.literal('subList'), + ]), + }), +}); diff --git a/src/metadata/schemas/index.ts b/src/metadata/schemas/index.ts index 5fe89e0..1f3c0fa 100644 --- a/src/metadata/schemas/index.ts +++ b/src/metadata/schemas/index.ts @@ -10,8 +10,11 @@ import { repoDriverAccountMetadataSchemaV4 } from './repo-driver/v4'; import { nftDriverAccountMetadataSchemaV4 } from './nft-driver/v4'; import { repoDriverAccountMetadataSchemaV5 } from './repo-driver/v5'; import { nftDriverAccountMetadataSchemaV5 } from './nft-driver/v5'; +import { subListMetadataSchemaV1 } from './immutable-splits-driver/v1'; +import { nftDriverAccountMetadataSchemaV6 } from './nft-driver/v6'; export const nftDriverAccountMetadataParser = createVersionedParser([ + nftDriverAccountMetadataSchemaV6.parse, nftDriverAccountMetadataSchemaV5.parse, nftDriverAccountMetadataSchemaV4.parse, nftDriverAccountMetadataSchemaV3.parse, @@ -30,3 +33,7 @@ export const repoDriverAccountMetadataParser = createVersionedParser([ repoDriverAccountMetadataSchemaV2.parse, repoDriverAccountMetadataSchemaV1.parse, ]); + +export const immutableSplitsDriverMetadataParser = createVersionedParser([ + subListMetadataSchemaV1.parse, +]); diff --git a/src/metadata/schemas/nft-driver/v1.ts b/src/metadata/schemas/nft-driver/v1.ts index ee826df..0834562 100644 --- a/src/metadata/schemas/nft-driver/v1.ts +++ b/src/metadata/schemas/nft-driver/v1.ts @@ -12,7 +12,6 @@ const repoDriverSplitReceiverSchema = z.object({ source: sourceSchema, }); -// eslint-disable-next-line import/prefer-default-export export const nftDriverAccountMetadataSchemaV1 = z.object({ driver: z.literal('nft'), describes: z.object({ diff --git a/src/metadata/schemas/nft-driver/v2.ts b/src/metadata/schemas/nft-driver/v2.ts index 886e0c4..ba56b61 100644 --- a/src/metadata/schemas/nft-driver/v2.ts +++ b/src/metadata/schemas/nft-driver/v2.ts @@ -17,7 +17,7 @@ const repoDriverSplitReceiverSchema = z.object({ /** * A splits entry that splits directly to a different Drip List. */ -const dripListSplitReceiverSchema = z.object({ +export const dripListSplitReceiverSchema = z.object({ type: z.literal('dripList'), weight: z.number(), accountId: z.string(), diff --git a/src/metadata/schemas/nft-driver/v6.ts b/src/metadata/schemas/nft-driver/v6.ts new file mode 100644 index 0000000..2d6a3ed --- /dev/null +++ b/src/metadata/schemas/nft-driver/v6.ts @@ -0,0 +1,49 @@ +import { z } from 'zod'; +import { nftDriverAccountMetadataSchemaV5 } from './v5'; +import { + addressDriverSplitReceiverSchema, + repoDriverSplitReceiverSchema, +} from '../repo-driver/v2'; +import { subListSplitReceiverSchema } from '../immutable-splits-driver/v1'; +import { dripListSplitReceiverSchema } from './v2'; +import { repoSubAccountDriverSplitReceiverSchema } from '../common/repoSubAccountDriverSplitReceiverSchema'; +import { emojiAvatarSchema } from '../repo-driver/v4'; + +const base = nftDriverAccountMetadataSchemaV5 + .omit({ + isDripList: true, + projects: true, + }) + .extend({ + isDripList: z.undefined().optional(), + projects: z.undefined().optional(), + }); + +const ecosystemVariant = base.extend({ + type: z.literal('ecosystem'), + recipients: z.array( + z.union([ + repoSubAccountDriverSplitReceiverSchema, + subListSplitReceiverSchema, + ]), + ), + color: z.string(), + avatar: emojiAvatarSchema, +}); + +const dripListVariant = base.extend({ + type: z.literal('dripList'), + recipients: z.array( + z.union([ + repoDriverSplitReceiverSchema, + subListSplitReceiverSchema, + addressDriverSplitReceiverSchema, + dripListSplitReceiverSchema, + ]), + ), +}); + +export const nftDriverAccountMetadataSchemaV6 = z.discriminatedUnion('type', [ + ecosystemVariant, + dripListVariant, +]); diff --git a/src/metadata/schemas/repo-driver/v4.ts b/src/metadata/schemas/repo-driver/v4.ts index b8b2f68..3a2eb53 100644 --- a/src/metadata/schemas/repo-driver/v4.ts +++ b/src/metadata/schemas/repo-driver/v4.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { repoDriverAccountMetadataSchemaV3 } from './v3'; -const emojiAvatarSchema = z.object({ +export const emojiAvatarSchema = z.object({ type: z.literal('emoji'), emoji: z.string(), }); diff --git a/src/models/AccountMetadataEmittedEventModel.ts b/src/models/AccountMetadataEmittedEventModel.ts index 907c097..c67054e 100644 --- a/src/models/AccountMetadataEmittedEventModel.ts +++ b/src/models/AccountMetadataEmittedEventModel.ts @@ -7,6 +7,7 @@ import { DataTypes, Model } from 'sequelize'; import { COMMON_EVENT_INIT_ATTRIBUTES } from '../core/constants'; import getSchema from '../utils/getSchema'; import type { IEventModel } from '../events/types'; +import type { AccountId } from '../core/types'; export default class AccountMetadataEmittedEventModel extends Model< @@ -15,43 +16,41 @@ export default class AccountMetadataEmittedEventModel > implements IEventModel { - // Properties from event output. - public declare key: string; - public declare value: string; - public declare accountId: string; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public key: string; + declare public value: string; + declare public accountId: AccountId; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { key: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, value: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'AccountMetadataEmittedEvents', + tableName: 'account_metadata_emitted_events', + underscored: true, + timestamps: true, indexes: [ { fields: ['accountId'], - name: `IX_AccountMetadataEmittedEvents_accountId`, - unique: false, + name: 'idx_account_metadata_emitted_events_accountId', }, ], }, diff --git a/src/models/AddressDriverSplitReceiverModel.ts b/src/models/AddressDriverSplitReceiverModel.ts deleted file mode 100644 index bf93699..0000000 --- a/src/models/AddressDriverSplitReceiverModel.ts +++ /dev/null @@ -1,105 +0,0 @@ -import type { - CreationOptional, - InferAttributes, - InferCreationAttributes, - Sequelize, -} from 'sequelize'; -import { DataTypes, Model } from 'sequelize'; -import type { AddressLike } from 'ethers'; -import getSchema from '../utils/getSchema'; -import GitProjectModel from './GitProjectModel'; -import type { AddressDriverId, DripListId, ProjectId } from '../core/types'; -import DripListModel from './DripListModel'; - -export enum AddressDriverSplitReceiverType { - ProjectMaintainer = 'ProjectMaintainer', - ProjectDependency = 'ProjectDependency', - DripListDependency = 'DripListDependency', -} - -export default class AddressDriverSplitReceiverModel extends Model< - InferAttributes, - InferCreationAttributes -> { - public declare id: CreationOptional; // Primary key - public declare funderProjectId: ProjectId | null; // Foreign key - public declare funderDripListId: DripListId | null; // Foreign key - - public declare weight: number; - public declare type: AddressDriverSplitReceiverType; - public declare fundeeAccountId: AddressDriverId; - public declare fundeeAccountAddress: AddressLike; - public declare blockTimestamp: Date; - - public static initialize(sequelize: Sequelize): void { - this.init( - { - id: { - type: DataTypes.INTEGER, - autoIncrement: true, - primaryKey: true, - }, - fundeeAccountId: { - type: DataTypes.STRING, - allowNull: false, - }, - fundeeAccountAddress: { - type: DataTypes.STRING, - allowNull: false, - }, - funderProjectId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: GitProjectModel, - key: 'id', - }, - allowNull: true, - }, - funderDripListId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: DripListModel, - key: 'id', - }, - allowNull: true, - }, - weight: { - type: DataTypes.INTEGER, - allowNull: true, - }, - type: { - type: DataTypes.ENUM( - ...Object.values(AddressDriverSplitReceiverType), - ), - allowNull: false, - }, - blockTimestamp: { - type: DataTypes.DATE, - allowNull: false, - }, - }, - { - sequelize, - schema: getSchema(), - tableName: 'AddressDriverSplitReceivers', - indexes: [ - { - fields: ['fundeeAccountId'], - name: `IX_AddressDriverSplitReceivers_fundeeAccountId`, - unique: false, - }, - { - fields: ['funderDripListId'], - name: `IX_AddressDriverSplitReceivers_funderDripListId`, - where: { - type: AddressDriverSplitReceiverType.DripListDependency, - }, - unique: false, - }, - ], - }, - ); - } -} diff --git a/src/models/DripListModel.ts b/src/models/DripListModel.ts index 2016c6e..559b9e8 100644 --- a/src/models/DripListModel.ts +++ b/src/models/DripListModel.ts @@ -1,90 +1,106 @@ import type { + CreationOptional, InferAttributes, InferCreationAttributes, Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import type { AddressLike } from 'ethers'; import type { UUID } from 'crypto'; -import type { AccountId, DripListId } from '../core/types'; +import type { AccountId, Address, NftDriverId } from '../core/types'; import getSchema from '../utils/getSchema'; export default class DripListModel extends Model< InferAttributes, InferCreationAttributes > { - public declare id: DripListId; // The `tokenId` from `TransferEvent` event. - public declare isValid: boolean; - public declare name: string | null; - public declare creator: AddressLike; - public declare description: string | null; - public declare ownerAddress: AddressLike; - public declare ownerAccountId: AccountId; - public declare previousOwnerAddress: AddressLike; - public declare latestVotingRoundId: UUID | null; - public declare isVisible: boolean; - public declare lastProcessedIpfsHash: string | null; + declare public accountId: NftDriverId; + declare public isValid: boolean; + declare public name: string | null; + declare public creator: Address | null; + declare public description: string | null; + declare public ownerAddress: Address; + declare public ownerAccountId: AccountId; + declare public previousOwnerAddress: Address | null; + declare public latestVotingRoundId: UUID | null; + declare public isVisible: boolean; + declare public lastProcessedIpfsHash: string; + declare public lastProcessedVersion: string; + declare public createdAt: CreationOptional; + declare public updatedAt: CreationOptional; public static initialize(sequelize: Sequelize): void { this.init( { - id: { - type: DataTypes.STRING, + accountId: { primaryKey: true, + type: DataTypes.STRING, }, isValid: { - type: DataTypes.BOOLEAN, allowNull: false, + type: DataTypes.BOOLEAN, }, ownerAddress: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ownerAccountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, name: { - type: DataTypes.STRING, allowNull: true, + type: DataTypes.STRING, }, latestVotingRoundId: { - type: DataTypes.UUID, allowNull: true, + type: DataTypes.UUID, }, description: { - type: DataTypes.TEXT, allowNull: true, + type: DataTypes.TEXT, }, creator: { + allowNull: true, type: DataTypes.STRING, - allowNull: false, }, previousOwnerAddress: { + allowNull: true, type: DataTypes.STRING, - allowNull: false, }, isVisible: { - type: DataTypes.BOOLEAN, allowNull: false, + type: DataTypes.BOOLEAN, }, lastProcessedIpfsHash: { + allowNull: false, type: DataTypes.TEXT, - allowNull: true, + }, + lastProcessedVersion: { + allowNull: false, + type: DataTypes.BIGINT, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, }, }, { sequelize, schema: getSchema(), - tableName: 'DripLists', + tableName: 'drip_lists', + underscored: true, + timestamps: true, indexes: [ { fields: ['ownerAddress'], - name: `IX_DripLists_ownerAddress`, + name: `idx_drip_lists_owner_address`, where: { isValid: true, }, - unique: false, }, ], }, diff --git a/src/models/DripListSplitReceiverModel.ts b/src/models/DripListSplitReceiverModel.ts deleted file mode 100644 index 0da0755..0000000 --- a/src/models/DripListSplitReceiverModel.ts +++ /dev/null @@ -1,105 +0,0 @@ -import type { - CreationOptional, - InferAttributes, - InferCreationAttributes, - Sequelize, -} from 'sequelize'; -import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; -import { DependencyType } from '../core/types'; -import type { DripListId, ProjectId } from '../core/types'; -import DripListModel from './DripListModel'; -import GitProjectModel from './GitProjectModel'; - -export default class DripListSplitReceiverModel extends Model< - InferAttributes, - InferCreationAttributes -> { - public declare id: CreationOptional; // Primary key - public declare fundeeDripListId: DripListId; // Foreign key - public declare funderProjectId: ProjectId | null; // Foreign key - public declare funderDripListId: DripListId | null; // Foreign key - - public declare weight: number; - public declare type: DependencyType; - public declare blockTimestamp: Date; - - public static initialize(sequelize: Sequelize): void { - this.init( - { - id: { - type: DataTypes.INTEGER, - autoIncrement: true, - primaryKey: true, - }, - fundeeDripListId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: DripListModel, - key: 'id', - }, - allowNull: false, - }, - funderProjectId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: GitProjectModel, - key: 'id', - }, - allowNull: true, - }, - funderDripListId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: DripListModel, - key: 'id', - }, - allowNull: true, - }, - weight: { - type: DataTypes.INTEGER, - allowNull: true, - }, - type: { - type: DataTypes.ENUM(...Object.values(DependencyType)), - allowNull: false, - }, - blockTimestamp: { - type: DataTypes.DATE, - allowNull: false, - }, - }, - { - sequelize, - schema: getSchema(), - tableName: 'DripListSplitReceivers', - indexes: [ - { - fields: ['fundeeDripListId'], - name: `IX_DripListSplitReceivers_fundeeDripListId`, - unique: false, - }, - { - fields: ['funderProjectId'], - name: `IX_DripListSplitReceivers_funderProjectId`, - where: { - type: DependencyType.ProjectDependency, - }, - unique: false, - }, - { - fields: ['funderDripListId'], - name: `IX_DripListSplitReceivers_funderDripListId`, - where: { - type: DependencyType.DripListDependency, - }, - unique: false, - }, - ], - }, - ); - } -} diff --git a/src/models/EcosystemMainAccountModel.ts b/src/models/EcosystemMainAccountModel.ts new file mode 100644 index 0000000..c1d3e71 --- /dev/null +++ b/src/models/EcosystemMainAccountModel.ts @@ -0,0 +1,113 @@ +import type { + CreationOptional, + InferAttributes, + InferCreationAttributes, + Sequelize, +} from 'sequelize'; +import { DataTypes, Model } from 'sequelize'; +import type { AccountId, Address, NftDriverId } from '../core/types'; +import getSchema from '../utils/getSchema'; + +export default class EcosystemMainAccountModel extends Model< + InferAttributes, + InferCreationAttributes +> { + declare public accountId: NftDriverId; + declare public isValid: boolean; + declare public name: string | null; + declare public creator: Address | null; + declare public description: string | null; + declare public ownerAddress: Address; + declare public ownerAccountId: AccountId; + declare public previousOwnerAddress: Address; + declare public isVisible: boolean; + declare public lastProcessedIpfsHash: string; + declare public lastProcessedVersion: string; + declare public avatar: string; + declare public color: string; + declare public createdAt: CreationOptional; + declare public updatedAt: CreationOptional; + + public static initialize(sequelize: Sequelize): void { + this.init( + { + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + ownerAddress: { + allowNull: false, + type: DataTypes.STRING, + }, + ownerAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + name: { + allowNull: true, + type: DataTypes.STRING, + }, + description: { + allowNull: true, + type: DataTypes.TEXT, + }, + creator: { + allowNull: true, + type: DataTypes.STRING, + }, + previousOwnerAddress: { + allowNull: false, + type: DataTypes.STRING, + }, + isVisible: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + lastProcessedIpfsHash: { + allowNull: false, + type: DataTypes.TEXT, + }, + lastProcessedVersion: { + allowNull: false, + type: DataTypes.BIGINT, + }, + avatar: { + allowNull: false, + type: DataTypes.STRING, + }, + color: { + allowNull: false, + type: DataTypes.STRING, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }, + { + sequelize, + schema: getSchema(), + tableName: 'ecosystem_main_accounts', + underscored: true, + timestamps: true, + indexes: [ + { + fields: ['ownerAddress'], + name: `idx_ecosystem_main_accounts_owner_address`, + where: { + isValid: true, + }, + }, + ], + }, + ); + } +} diff --git a/src/models/GitProjectModel.ts b/src/models/GitProjectModel.ts deleted file mode 100644 index ede3012..0000000 --- a/src/models/GitProjectModel.ts +++ /dev/null @@ -1,165 +0,0 @@ -import type { - InferAttributes, - InferCreationAttributes, - Sequelize, -} from 'sequelize'; -import { DataTypes, Model } from 'sequelize'; -import type { AddressLike } from 'ethers'; -import getSchema from '../utils/getSchema'; -import type { AccountId, Forge, ProjectId } from '../core/types'; -import { FORGES_MAP } from '../core/constants'; - -export enum ProjectVerificationStatus { - Claimed = 'Claimed', - OwnerUpdateRequested = 'OwnerUpdateRequested', - OwnerUpdated = 'OwnerUpdated', - Unclaimed = 'Unclaimed', - PendingOwner = 'PendingOwner', - PendingMetadata = 'PendingMetadata', -} - -export default class GitProjectModel extends Model< - InferAttributes, - InferCreationAttributes -> { - public declare id: ProjectId; // The `accountId` from `OwnerUpdatedRequested` event. - public declare isValid: boolean; - public declare name: string | null; - public declare forge: Forge | null; - public declare ownerAddress: AddressLike | null; - public declare ownerAccountId: AccountId | null; - - public declare url: string | null; - public declare emoji: string | null; - public declare avatarCid: string | null; - public declare color: string | null; - public declare description: string | null; - public declare verificationStatus: ProjectVerificationStatus; - public declare isVisible: boolean; - public declare lastProcessedIpfsHash: string | null; - - public declare claimedAt: Date | null; - - public static initialize(sequelize: Sequelize): void { - this.init( - { - id: { - type: DataTypes.STRING, - primaryKey: true, - }, - isValid: { - type: DataTypes.BOOLEAN, - allowNull: false, - }, - name: { - type: DataTypes.STRING, - allowNull: true, - validate: { - isValidName(value: string) { - if (!value) { - throw new Error('Project name is required.'); - } - - const components = value?.split('/'); - - if (components.length !== 2) { - throw new Error(`Invalid project name: '${value}'.`); - } - - const ownerName = components[0]; - const repoName = components[1]; - - const validProjectNameRegex: RegExp = /^[\w.-]+$/; - - if ( - !validProjectNameRegex.test(ownerName) || - !validProjectNameRegex.test(repoName) - ) { - throw new Error(`Invalid project name: '${value}'.`); - } - }, - }, - }, - verificationStatus: { - type: DataTypes.ENUM(...Object.values(ProjectVerificationStatus)), - allowNull: false, - }, - claimedAt: { - type: DataTypes.DATE, - allowNull: true, - }, - forge: { - type: DataTypes.ENUM(...Object.values(FORGES_MAP)), - allowNull: true, - }, - ownerAddress: { - type: DataTypes.STRING, - allowNull: true, - }, - ownerAccountId: { - type: DataTypes.STRING, - allowNull: true, - }, - url: { - type: DataTypes.STRING, - allowNull: true, - }, - emoji: { - type: DataTypes.STRING, - allowNull: true, - }, - avatarCid: { - type: DataTypes.STRING, - allowNull: true, - }, - color: { - type: DataTypes.STRING, - allowNull: true, - }, - description: { - type: DataTypes.TEXT, - allowNull: true, - }, - isVisible: { - type: DataTypes.BOOLEAN, - allowNull: false, - }, - lastProcessedIpfsHash: { - type: DataTypes.TEXT, - allowNull: true, - }, - }, - { - sequelize, - schema: getSchema(), - tableName: 'GitProjects', - indexes: [ - { - fields: ['ownerAddress'], - name: `IX_GitProjects_ownerAddress`, - unique: false, - where: { - isValid: true, - }, - }, - { - fields: ['verificationStatus'], - name: `IX_GitProjects_verificationStatus`, - where: { - isValid: true, - }, - unique: false, - }, - { - fields: ['url'], - name: `IX_GitProjects_url`, - where: { - isValid: true, - }, - unique: false, - }, - ], - }, - ); - } -} diff --git a/src/models/GivenEventModel.ts b/src/models/GivenEventModel.ts index 71e5045..2650521 100644 --- a/src/models/GivenEventModel.ts +++ b/src/models/GivenEventModel.ts @@ -16,62 +16,58 @@ export default class GivenEventModel > implements IEventModel { - public declare accountId: AccountId; // Sender of the Give - public declare receiver: AccountId; - public declare erc20: Address; - public declare amt: BigIntString; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public accountId: AccountId; // Sender of the Give + declare public receiver: AccountId; + declare public erc20: Address; + declare public amt: BigIntString; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, receiver: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, erc20: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, amt: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'GivenEvents', + tableName: 'given_events', + underscored: true, + timestamps: true, indexes: [ { fields: ['accountId'], - name: `IX_GivenEvents_accountId`, - unique: false, + name: `idx_given_events_accountId`, }, { fields: ['receiver'], - name: `IX_GivenEvents_receiver`, - unique: false, + name: `idx_given_events_receiver`, }, { fields: ['erc20'], - name: `IX_GivenEvents_erc20`, - unique: false, + name: `idx_given_events_erc20`, }, { fields: ['transactionHash', 'logIndex'], - name: `IX_GivenEvents_transactionHash_logIndex`, - unique: false, + name: `idx_given_events_transactionHash_logIndex`, }, ], }, diff --git a/src/models/_LastIndexedBlockModel.ts b/src/models/LastIndexedBlockModel.ts similarity index 50% rename from src/models/_LastIndexedBlockModel.ts rename to src/models/LastIndexedBlockModel.ts index 144a92f..bdf2896 100644 --- a/src/models/_LastIndexedBlockModel.ts +++ b/src/models/LastIndexedBlockModel.ts @@ -1,4 +1,5 @@ import type { + CreationOptional, InferAttributes, InferCreationAttributes, Sequelize, @@ -6,31 +7,42 @@ import type { import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -export default class _LastIndexedBlockModel extends Model< - InferAttributes<_LastIndexedBlockModel>, - InferCreationAttributes<_LastIndexedBlockModel> +export default class LastIndexedBlockModel extends Model< + InferAttributes, + InferCreationAttributes > { - public declare blockNumber: bigint; - public declare id: number; + declare public blockNumber: bigint; + declare public id: number; + declare public createdAt: CreationOptional; + declare public updatedAt: CreationOptional; public static initialize(sequelize: Sequelize): void { this.init( { id: { - type: DataTypes.INTEGER, - autoIncrement: true, primaryKey: true, + autoIncrement: true, + type: DataTypes.INTEGER, }, blockNumber: { + unique: true, + allowNull: false, type: DataTypes.BIGINT, + }, + createdAt: { allowNull: false, - unique: true, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, }, }, { sequelize, schema: getSchema(), - tableName: '_LastIndexedBlock', + tableName: 'last_indexed_block', + underscored: true, }, ); } diff --git a/src/models/OwnerUpdateRequestedEventModel.ts b/src/models/OwnerUpdateRequestedEventModel.ts deleted file mode 100644 index 9c7176d..0000000 --- a/src/models/OwnerUpdateRequestedEventModel.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { - InferAttributes, - InferCreationAttributes, - Sequelize, -} from 'sequelize'; -import { DataTypes, Model } from 'sequelize'; -import type { Forge, RepoDriverId } from '../core/types'; -import getSchema from '../utils/getSchema'; -import { COMMON_EVENT_INIT_ATTRIBUTES, FORGES_MAP } from '../core/constants'; -import type { IEventModel } from '../events/types'; - -export default class OwnerUpdateRequestedEventModel - extends Model< - InferAttributes, - InferCreationAttributes - > - implements IEventModel -{ - // Properties from event output. - public declare forge: Forge; - public declare name: string; - public declare accountId: RepoDriverId; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; - - public static initialize(sequelize: Sequelize): void { - this.init( - { - name: { - type: DataTypes.STRING, - allowNull: false, - }, - accountId: { - type: DataTypes.STRING, - allowNull: false, - }, - forge: { - type: DataTypes.ENUM(...Object.values(FORGES_MAP)), - allowNull: false, - }, - ...COMMON_EVENT_INIT_ATTRIBUTES, - }, - { - sequelize, - schema: getSchema(), - tableName: 'OwnerUpdateRequestedEvents', - }, - ); - } -} diff --git a/src/models/OwnerUpdatedEventModel.ts b/src/models/OwnerUpdatedEventModel.ts index 905e773..4ff4af1 100644 --- a/src/models/OwnerUpdatedEventModel.ts +++ b/src/models/OwnerUpdatedEventModel.ts @@ -17,33 +17,32 @@ export default class OwnerUpdatedEventModel > implements IEventModel { - // Properties from event output. - public declare owner: AddressLike; - public declare accountId: RepoDriverId; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public owner: AddressLike; + declare public accountId: RepoDriverId; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { owner: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, + underscored: true, + timestamps: true, schema: getSchema(), - tableName: 'OwnerUpdatedEvents', + tableName: 'owner_updated_events', }, ); } diff --git a/src/models/ProjectModel.ts b/src/models/ProjectModel.ts new file mode 100644 index 0000000..797ce07 --- /dev/null +++ b/src/models/ProjectModel.ts @@ -0,0 +1,146 @@ +import type { + CreationOptional, + InferAttributes, + InferCreationAttributes, + Sequelize, +} from 'sequelize'; +import { DataTypes, Model } from 'sequelize'; +import getSchema from '../utils/getSchema'; +import type { Address, AddressDriverId, RepoDriverId } from '../core/types'; + +export const PROJECT_VERIFICATION_STATUSES = [ + 'claimed', + 'unclaimed', + 'pending_metadata', +] as const; +export type ProjectVerificationStatus = + (typeof PROJECT_VERIFICATION_STATUSES)[number]; + +export type ProjectName = `${string}/${string}`; + +export const FORGES = ['github', 'gitlab'] as const; +export type Forge = (typeof FORGES)[number]; + +export default class ProjectModel extends Model< + InferAttributes, + InferCreationAttributes +> { + // Populated by `OwnerUpdated` + declare public accountId: RepoDriverId; + declare public ownerAddress: Address | null; + declare public ownerAccountId: AddressDriverId | null; + declare public claimedAt: Date | null; + + // Populated by `AccountMetadataEmitted` + declare public url: string | null; + declare public forge: Forge | null; + declare public name: ProjectName | null; + declare public emoji: string | null; + declare public color: string | null; + declare public avatarCid: string | null; + declare public lastProcessedIpfsHash: string | null; + + // Common + declare public verificationStatus: ProjectVerificationStatus; + declare public isValid: boolean; + declare public isVisible: boolean; + declare public lastProcessedVersion: string; + declare public createdAt: CreationOptional; + declare public updatedAt: CreationOptional; + + public static initialize(sequelize: Sequelize): void { + this.init( + { + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + isVisible: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + name: { + allowNull: true, + type: DataTypes.STRING, + }, + verificationStatus: { + allowNull: false, + type: DataTypes.ENUM(...PROJECT_VERIFICATION_STATUSES), + }, + ownerAddress: { + allowNull: true, + type: DataTypes.STRING, + }, + ownerAccountId: { + allowNull: true, + type: DataTypes.STRING, + }, + forge: { + allowNull: true, + type: DataTypes.ENUM(...FORGES), + }, + url: { + allowNull: true, + type: DataTypes.STRING, + }, + emoji: { + allowNull: true, + type: DataTypes.STRING, + }, + avatarCid: { + allowNull: true, + type: DataTypes.STRING, + }, + color: { + allowNull: true, + type: DataTypes.STRING, + }, + lastProcessedIpfsHash: { + allowNull: true, + type: DataTypes.TEXT, + }, + lastProcessedVersion: { + allowNull: false, + type: DataTypes.STRING, + }, + claimedAt: { + allowNull: true, + type: DataTypes.DATE, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }, + { + sequelize, + schema: getSchema(), + tableName: 'projects', + underscored: true, + timestamps: true, + indexes: [ + { + fields: ['ownerAddress'], + name: 'idx_projects_owner_address', + }, + { + fields: ['verificationStatus'], + name: 'idx_projects_verification_status', + }, + { + fields: ['url'], + name: 'idx_projects_url', + }, + ], + }, + ); + } +} diff --git a/src/models/RepoDriverSplitReceiverModel.ts b/src/models/RepoDriverSplitReceiverModel.ts deleted file mode 100644 index c1cdcb3..0000000 --- a/src/models/RepoDriverSplitReceiverModel.ts +++ /dev/null @@ -1,105 +0,0 @@ -import type { - CreationOptional, - InferAttributes, - InferCreationAttributes, - Sequelize, -} from 'sequelize'; -import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; -import GitProjectModel from './GitProjectModel'; -import { DependencyType } from '../core/types'; -import type { DripListId, ProjectId } from '../core/types'; -import DripListModel from './DripListModel'; - -export default class RepoDriverSplitReceiverModel extends Model< - InferAttributes, - InferCreationAttributes -> { - public declare id: CreationOptional; // Primary key - public declare fundeeProjectId: ProjectId; // Foreign key - public declare funderProjectId: ProjectId | null; // Foreign key - public declare funderDripListId: DripListId | null; // Foreign key - - public declare weight: number; - public declare type: DependencyType; - public declare blockTimestamp: Date; - - public static initialize(sequelize: Sequelize): void { - this.init( - { - id: { - type: DataTypes.INTEGER, - autoIncrement: true, - primaryKey: true, - }, - fundeeProjectId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: GitProjectModel, - key: 'id', - }, - allowNull: false, - }, - funderProjectId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: GitProjectModel, - key: 'id', - }, - allowNull: true, - }, - funderDripListId: { - // Foreign key - type: DataTypes.STRING, - references: { - model: DripListModel, - key: 'id', - }, - allowNull: true, - }, - weight: { - type: DataTypes.INTEGER, - allowNull: true, - }, - type: { - type: DataTypes.ENUM(...Object.values(DependencyType)), - allowNull: false, - }, - blockTimestamp: { - type: DataTypes.DATE, - allowNull: false, - }, - }, - { - sequelize, - schema: getSchema(), - tableName: 'RepoDriverSplitReceivers', - indexes: [ - { - fields: ['fundeeProjectId'], - name: `IX_RepoDriverSplitReceivers_fundeeProjectId`, - unique: false, - }, - { - fields: ['funderProjectId'], - name: `IX_RepoDriverSplitReceivers_funderProjectId`, - where: { - type: DependencyType.ProjectDependency, - }, - unique: false, - }, - { - fields: ['funderDripListId'], - name: `IX_RepoDriverSplitReceivers_funderDripListId`, - where: { - type: DependencyType.DripListDependency, - }, - unique: false, - }, - ], - }, - ); - } -} diff --git a/src/models/SplitEventModel.ts b/src/models/SplitEventModel.ts index a8c2a25..956bb54 100644 --- a/src/models/SplitEventModel.ts +++ b/src/models/SplitEventModel.ts @@ -16,52 +16,51 @@ export default class SplitEventModel > implements IEventModel { - public declare accountId: AccountId; - public declare receiver: AccountId; - public declare erc20: Address; - public declare amt: BigIntString; + declare public accountId: AccountId; + declare public receiver: AccountId; + declare public erc20: Address; + declare public amt: BigIntString; - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, receiver: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, erc20: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, amt: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'SplitEvents', + tableName: 'split_events', + underscored: true, + timestamps: true, indexes: [ { fields: ['receiver'], - name: `IX_SplitEvents_receiver`, - unique: false, + name: `idx_split_events_receiver`, }, { fields: ['accountId', 'receiver'], - name: `IX_SplitEvents_accountId_receiver`, - unique: false, + name: `idx_split_events_accountId_receiver`, }, ], }, diff --git a/src/models/SplitsReceiverModel.ts b/src/models/SplitsReceiverModel.ts new file mode 100644 index 0000000..2940c32 --- /dev/null +++ b/src/models/SplitsReceiverModel.ts @@ -0,0 +1,115 @@ +import type { + CreationOptional, + InferAttributes, + InferCreationAttributes, + Sequelize, +} from 'sequelize'; +import { DataTypes, Model } from 'sequelize'; +import getSchema from '../utils/getSchema'; +import type { AccountId } from '../core/types'; +import { + type RelationshipType, + type AccountType, + ACCOUNT_TYPES, + RELATIONSHIP_TYPES, +} from '../core/splitRules'; + +export default class SplitsReceiverModel extends Model< + InferAttributes, + InferCreationAttributes +> { + declare public id: CreationOptional; + declare public receiverAccountId: AccountId; + declare public receiverAccountType: AccountType; + declare public senderAccountId: AccountId; + declare public senderAccountType: AccountType; + declare public relationshipType: RelationshipType; + declare public weight: number; + declare public blockTimestamp: Date; + declare public splitsToRepoDriverSubAccount: boolean | undefined; + declare public createdAt: CreationOptional; + declare public updatedAt: CreationOptional; + + public static initialize(sequelize: Sequelize): void { + this.init( + { + id: { + primaryKey: true, + autoIncrement: true, + type: DataTypes.INTEGER, + }, + receiverAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + receiverAccountType: { + allowNull: false, + type: DataTypes.ENUM(...ACCOUNT_TYPES), + }, + senderAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + senderAccountType: { + allowNull: false, + type: DataTypes.ENUM(...ACCOUNT_TYPES), + }, + relationshipType: { + allowNull: false, + type: DataTypes.ENUM(...RELATIONSHIP_TYPES), + }, + splitsToRepoDriverSubAccount: { + type: DataTypes.BOOLEAN, + allowNull: true, + validate: { + splitsToRepoDriverSubAccountValidation(value: boolean | null) { + if (this.receiverAccountType === 'project' && !value) { + throw new Error( + `'splitsToRepoDriverSubAccount' must have a value when 'receiverAccountType' is 'project'.`, + ); + } + if (this.receiverAccountType !== 'project' && value) { + throw new Error( + `'splitsToRepoDriverSubAccount' must be 'null' when 'receiverAccountType' is not 'project'.`, + ); + } + }, + }, + }, + weight: { + type: DataTypes.INTEGER, + allowNull: false, + }, + blockTimestamp: { + type: DataTypes.DATE, + allowNull: false, + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false, + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false, + }, + }, + { + sequelize, + schema: getSchema(), + tableName: 'splits_receivers', + underscored: true, + timestamps: true, + indexes: [ + { + fields: ['receiverAccountId', 'senderAccountId'], + name: 'idx_splits_receivers_receiver_sender', + }, + { + fields: ['senderAccountId', 'receiverAccountId'], + name: 'idx_splits_receivers_sender_receiver', + }, + ], + }, + ); + } +} diff --git a/src/models/SplitsSetEventModel.ts b/src/models/SplitsSetEventModel.ts index 2b0e716..5809437 100644 --- a/src/models/SplitsSetEventModel.ts +++ b/src/models/SplitsSetEventModel.ts @@ -16,32 +16,32 @@ export default class SplitsSetEventModel > implements IEventModel { - public declare accountId: AccountId; - public declare receiversHash: string; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public accountId: AccountId; + declare public receiversHash: string; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, receiversHash: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, + timestamps: true, + underscored: true, schema: getSchema(), - tableName: 'SplitsSetEvents', + tableName: 'splits_set_events', }, ); } diff --git a/src/models/SqueezedStreamsEventModel.ts b/src/models/SqueezedStreamsEventModel.ts index 6fc51d4..0fe58ca 100644 --- a/src/models/SqueezedStreamsEventModel.ts +++ b/src/models/SqueezedStreamsEventModel.ts @@ -21,18 +21,15 @@ export default class SqueezedStreamsEventModel > implements IEventModel { - // Properties from event output. - public declare accountId: AccountId; - public declare erc20: Address; - public declare senderId: AccountId; - public declare amount: BigIntString; - public declare streamsHistoryHashes: StreamHistoryHashes; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public accountId: AccountId; + declare public erc20: Address; + declare public senderId: AccountId; + declare public amount: BigIntString; + declare public streamsHistoryHashes: StreamHistoryHashes; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static toStreamHistoryHashes( streamsHistoryHashes: string[], @@ -44,31 +41,33 @@ export default class SqueezedStreamsEventModel this.init( { accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, erc20: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, senderId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, amount: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, streamsHistoryHashes: { - type: DataTypes.JSON, allowNull: false, + type: DataTypes.JSON, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'SqueezedStreamsEvents', + tableName: 'squeezed_streams_events', + underscored: true, + timestamps: true, }, ); } diff --git a/src/models/StreamReceiverSeenEventModel.ts b/src/models/StreamReceiverSeenEventModel.ts index 356f576..3f45b5a 100644 --- a/src/models/StreamReceiverSeenEventModel.ts +++ b/src/models/StreamReceiverSeenEventModel.ts @@ -16,41 +16,41 @@ export default class StreamReceiverSeenEventModel > implements IEventModel { - public declare receiversHash: string; - public declare accountId: AccountId; - public declare config: BigIntString; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public receiversHash: string; + declare public accountId: AccountId; + declare public config: BigIntString; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, config: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, receiversHash: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'StreamReceiverSeenEvents', + tableName: 'stream_receiver_seen_events', + underscored: true, + timestamps: true, indexes: [ { fields: ['accountId'], - name: `IX_StreamReceiverSeenEvents_accountId`, + name: `idx_stream_receiver_seen_events_accountId`, unique: false, }, ], diff --git a/src/models/StreamsSetEventModel.ts b/src/models/StreamsSetEventModel.ts index a5c21ab..1e64e70 100644 --- a/src/models/StreamsSetEventModel.ts +++ b/src/models/StreamsSetEventModel.ts @@ -16,61 +16,61 @@ export default class StreamsSetEventModel > implements IEventModel { - public declare accountId: AccountId; - public declare erc20: string; - public declare receiversHash: string; - public declare streamsHistoryHash: string; - public declare balance: BigIntString; - public declare maxEnd: BigIntString; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public accountId: AccountId; + declare public erc20: string; + declare public receiversHash: string; + declare public streamsHistoryHash: string; + declare public balance: BigIntString; + declare public maxEnd: BigIntString; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { accountId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, erc20: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, receiversHash: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, streamsHistoryHash: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, balance: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, maxEnd: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'StreamsSetEvents', + tableName: 'streams_set_events', + underscored: true, + timestamps: true, indexes: [ { fields: ['receiversHash'], - name: `IX_StreamsSetEvents_receiversHash`, + name: `idx_streams_set_events_receiversHash`, unique: false, }, { fields: ['accountId'], - name: `IX_StreamsSetEvents}_accountId`, + name: `idx_streams_set_events_accountId`, unique: false, }, ], diff --git a/src/models/SubListModel.ts b/src/models/SubListModel.ts new file mode 100644 index 0000000..626cca8 --- /dev/null +++ b/src/models/SubListModel.ts @@ -0,0 +1,89 @@ +import type { + CreationOptional, + InferAttributes, + InferCreationAttributes, + Sequelize, +} from 'sequelize'; +import { DataTypes, Model } from 'sequelize'; +import type { ImmutableSplitsDriverId, AccountId } from '../core/types'; +import getSchema from '../utils/getSchema'; +import type { AccountType } from '../core/splitRules'; + +export default class SubListModel extends Model< + InferAttributes, + InferCreationAttributes +> { + declare public accountId: ImmutableSplitsDriverId; + declare public parentAccountId: AccountId; + declare public parentAccountType: AccountType; + declare public rootAccountId: AccountId; + declare public rootAccountType: AccountType; + declare public lastProcessedIpfsHash: string; + declare public isValid: boolean; + declare public createdAt: CreationOptional; + declare public updatedAt: CreationOptional; + + public static initialize(sequelize: Sequelize): void { + this.init( + { + accountId: { + primaryKey: true, + type: DataTypes.STRING, + }, + isValid: { + allowNull: false, + type: DataTypes.BOOLEAN, + }, + parentAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + parentAccountType: { + allowNull: false, + type: DataTypes.STRING, + }, + rootAccountId: { + allowNull: false, + type: DataTypes.STRING, + }, + rootAccountType: { + type: DataTypes.STRING, + allowNull: false, + }, + lastProcessedIpfsHash: { + type: DataTypes.TEXT, + allowNull: false, + }, + createdAt: { + allowNull: false, + type: DataTypes.DATE, + }, + updatedAt: { + allowNull: false, + type: DataTypes.DATE, + }, + }, + { + sequelize, + schema: getSchema(), + tableName: 'sub_lists', + underscored: true, + timestamps: true, + indexes: [ + { + fields: ['accountId'], + name: 'idx_sub_lists_account_id', + }, + { + fields: ['parentId'], + name: 'idx_sub_lists_parent_id', + }, + { + fields: ['rootId'], + name: 'idx_sub_lists_root_id', + }, + ], + }, + ); + } +} diff --git a/src/models/TransferEventModel.ts b/src/models/TransferEventModel.ts index f20a601..3a3841e 100644 --- a/src/models/TransferEventModel.ts +++ b/src/models/TransferEventModel.ts @@ -1,11 +1,10 @@ -import type { AddressLike } from 'ethers'; import type { InferAttributes, InferCreationAttributes, Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import type { NftDriverId } from '../core/types'; +import type { Address, NftDriverId } from '../core/types'; import getSchema from '../utils/getSchema'; import { COMMON_EVENT_INIT_ATTRIBUTES } from '../core/constants'; import type { IEventModel } from '../events/types'; @@ -17,37 +16,37 @@ export default class TransferEventModel > implements IEventModel { - public declare tokenId: NftDriverId; // The `tokenId` from `Transfer` event. - public declare from: AddressLike; - public declare to: AddressLike; - - // Common event log properties. - public declare logIndex: number; - public declare blockNumber: number; - public declare blockTimestamp: Date; - public declare transactionHash: string; + declare public tokenId: NftDriverId; // The `tokenId` from `Transfer` event. + declare public from: Address; + declare public to: Address; + declare public logIndex: number; + declare public blockNumber: number; + declare public blockTimestamp: Date; + declare public transactionHash: string; public static initialize(sequelize: Sequelize): void { this.init( { tokenId: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, from: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, to: { - type: DataTypes.STRING, allowNull: false, + type: DataTypes.STRING, }, ...COMMON_EVENT_INIT_ATTRIBUTES, }, { sequelize, schema: getSchema(), - tableName: 'TransferEvents', + tableName: 'transfer_events', + underscored: true, + timestamps: true, }, ); } diff --git a/src/models/index.ts b/src/models/index.ts index 61db940..d0a1513 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,15 +1,15 @@ +export { default as SubListModel } from './SubListModel'; +export { default as ProjectModel } from './ProjectModel'; export { default as DripListModel } from './DripListModel'; export { default as GivenEventModel } from './GivenEventModel'; export { default as SplitEventModel } from './SplitEventModel'; -export { default as GitProjectModel } from './GitProjectModel'; +export { default as SplitsReceiverModel } from './SplitsReceiverModel'; export { default as TransferEventModel } from './TransferEventModel'; -export { default as StreamsSetEventModel } from './StreamsSetEventModel'; export { default as SplitsSetEventModel } from './SplitsSetEventModel'; +export { default as StreamsSetEventModel } from './StreamsSetEventModel'; +export { default as LastIndexedBlockModel } from './LastIndexedBlockModel'; export { default as OwnerUpdatedEventModel } from './OwnerUpdatedEventModel'; export { default as SqueezedStreamsEventModel } from './SqueezedStreamsEventModel'; -export { default as DripListSplitReceiverModel } from './DripListSplitReceiverModel'; -export { default as RepoDriverSplitReceiverModel } from './RepoDriverSplitReceiverModel'; +export { default as EcosystemMainAccountModel } from './EcosystemMainAccountModel'; export { default as StreamReceiverSeenEventModel } from './StreamReceiverSeenEventModel'; -export { default as OwnerUpdateRequestedEventModel } from './OwnerUpdateRequestedEventModel'; -export { default as AddressDriverSplitReceiverModel } from './AddressDriverSplitReceiverModel'; export { default as AccountMetadataEmittedEventModel } from './AccountMetadataEmittedEventModel'; diff --git a/src/queue/initJobProcessingQueue.ts b/src/queue/initJobProcessingQueue.ts index 7f42e05..4a02d3d 100644 --- a/src/queue/initJobProcessingQueue.ts +++ b/src/queue/initJobProcessingQueue.ts @@ -1,12 +1,11 @@ import { getEventHandler } from '../events/eventHandlerUtils'; import type { KnownAny } from '../core/types'; import eventProcessingQueue from './queue'; -import { assertRequestId } from '../utils/assert'; import EventHandlerRequest from '../events/EventHandlerRequest'; import logger from '../core/logger'; export default async function initJobProcessingQueue() { - eventProcessingQueue.process(100, async (job) => { + eventProcessingQueue.process(10, async (job) => { const handler = getEventHandler(job.data.eventSignature); const { @@ -18,8 +17,6 @@ export default async function initJobProcessingQueue() { blockTimestamp, } = job.data; - assertRequestId(job.id); - const handleContext = new EventHandlerRequest( { args: JSON.parse(args, (_, value) => { @@ -47,9 +44,12 @@ export default async function initJobProcessingQueue() { await handler.afterHandle({ args: handleContext.event.args.concat(accountIdsToInvalidate), blockTimestamp: handleContext.event.blockTimestamp, + requestId: handleContext.id, }); } catch (error: any) { - logger.error(`❌ ${handler.name} 'afterHandle' error: ${error.message}.`); + logger.error( + `❌ [${handleContext.id}] ${handler.name} 'afterHandle' error: ${error.message}.`, + ); } }); } diff --git a/src/queue/queue.ts b/src/queue/queue.ts index 4b37c5b..32a0933 100644 --- a/src/queue/queue.ts +++ b/src/queue/queue.ts @@ -28,19 +28,15 @@ eventProcessingQueue.on('error', (error: Error) => { }); eventProcessingQueue.on('job succeeded', (job) => { - logger.info(`✅ SUCCESS: Job with ID ${job} completed successfully.`); + logger.info(`✅ [${job}] completed successfully.`); }); eventProcessingQueue.on('job failed', (job, err) => { - logger.error( - `❌ FAILED: Job with ID ${job} failed with error '${err.message}'.`, - ); + logger.error(`❌ [${job}] failed: ${err.message}`); }); eventProcessingQueue.on('job retrying', (job, err) => { - logger.info( - `♻️ Job with ID ${job} failed with error '${err.message}' but is being retried...`, - ); + logger.info(`♻️ [${job}] failed (will be retried): ${err.message}`); }); export default eventProcessingQueue; diff --git a/src/queue/saveEventProcessingJob.ts b/src/queue/saveEventProcessingJob.ts index 350992a..43ec301 100644 --- a/src/queue/saveEventProcessingJob.ts +++ b/src/queue/saveEventProcessingJob.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto'; import { assertEventSignature } from '../utils/assert'; import eventProcessingQueue from './queue'; import type { EventSignature } from '../events/types'; @@ -6,7 +5,6 @@ import type EventHandlerRequest from '../events/EventHandlerRequest'; export default async function saveEventProcessingJob( request: EventHandlerRequest, - expectedEventSignature: T, ) { const { blockNumber, @@ -17,7 +15,7 @@ export default async function saveEventProcessingJob( eventSignature, } = request.event; - assertEventSignature(eventSignature, expectedEventSignature); + assertEventSignature(eventSignature, eventSignature); return eventProcessingQueue .createJob({ @@ -33,8 +31,8 @@ export default async function saveEventProcessingJob( return value; }), }) - .setId(randomUUID()) - .retries(10) - .backoff('exponential', 500) + .setId(request.id) + .retries(20) + .backoff('fixed', 30000) .save(); } diff --git a/src/utils/accountIdUtils.ts b/src/utils/accountIdUtils.ts index fe4d3be..74ac35c 100644 --- a/src/utils/accountIdUtils.ts +++ b/src/utils/accountIdUtils.ts @@ -1,54 +1,117 @@ -import type { AddressLike } from 'ethers'; +/* eslint-disable no-bitwise */ +import { repoSubAccountDriverContract } from '../core/contractClients'; import type { AccountId, AddressDriverId, + DripsContract, + ImmutableSplitsDriverId, NftDriverId, RepoDriverId, + RepoSubAccountDriverId, } from '../core/types'; -import { addressDriverContract } from '../core/contractClients'; -import { getContractNameFromAccountId } from './contractUtils'; +import unreachableError from './unreachableError'; -export function toRepoDriverId(id: bigint): RepoDriverId { - const repoDriverId = id.toString(); +export function getContractNameFromAccountId(id: string): DripsContract { + if (Number.isNaN(Number(id))) { + throw new Error(`Could not get bits: ${id} is not a number.`); + } + + const accountIdAsBigInt = BigInt(id); + + if (accountIdAsBigInt < 0n || accountIdAsBigInt > 2n ** 256n - 1n) { + throw new Error( + `Could not get bits: ${id} is not a valid positive number within the range of a uint256.`, + ); + } + + const mask = 2n ** 32n - 1n; // 32 bits mask + + const bits = (accountIdAsBigInt >> 224n) & mask; // eslint-disable-line no-bitwise + + switch (bits) { + case 0n: + return 'addressDriver'; + case 1n: + return 'nftDriver'; + case 2n: + return 'immutableSplitsDriver'; + case 3n: + return 'repoDriver'; + case 4n: + return 'repoSubAccountDriver'; + default: + throw new Error(`Unknown driver for ID ${id}.`); + } +} + +// RepoDriver +export function isRepoDriverId(id: string | bigint): id is RepoDriverId { + const idStr = typeof id === 'bigint' ? id.toString() : id; + const isNaN = Number.isNaN(Number(idStr)); + const isAccountIdOfRepoDriver = + getContractNameFromAccountId(idStr) === 'repoDriver'; + + if (isNaN || !isAccountIdOfRepoDriver) { + return false; + } + + return true; +} + +export function convertToRepoDriverId(id: bigint | string): RepoDriverId { + const repoDriverId = typeof id === 'bigint' ? id.toString() : id; if (!isRepoDriverId(repoDriverId)) { - throw new Error(`Invalid 'RepoDriver' account ID: ${id}.`); + throw new Error(`Failed to convert: '${id}' is not a valid RepoDriver ID.`); } return repoDriverId as RepoDriverId; } -export function toNftDriverId(id: bigint): NftDriverId { - const nftDriverId = id.toString(); +export function assertIsRepoDriverId(id: string): asserts id is RepoDriverId { + if (!isRepoDriverId(id)) { + throw new Error(`Failed to assert: '${id}' is not a valid RepoDriver ID.`); + } +} - if (!isNftDriverId(nftDriverId)) { - throw new Error(`Invalid 'NftDriver' account ID: ${id}.`); +// NftDriver +export function isNftDriverId(id: string | bigint): id is NftDriverId { + const idStr = typeof id === 'bigint' ? id.toString() : id; + const isNaN = Number.isNaN(Number(idStr)); + const isAccountIdOfNftDriver = + getContractNameFromAccountId(idStr) === 'nftDriver'; + + if (isNaN || !isAccountIdOfNftDriver) { + return false; } - return nftDriverId as NftDriverId; + return true; } -export function toAccountId(id: bigint): AccountId { - const accountIdAsString = id.toString(); +export function convertToNftDriverId(id: bigint | string): NftDriverId { + const nftDriverId = typeof id === 'bigint' ? id.toString() : id; - if ( - isRepoDriverId(accountIdAsString) || - isNftDriverId(accountIdAsString) || - isAddressDriverId(accountIdAsString) - ) { - return accountIdAsString as AccountId; + if (!isNftDriverId(nftDriverId)) { + throw new Error(`Failed to convert: '${id}' is not a valid NftDriver ID.`); } - throw new Error(`Invalid account ID: ${id}.`); + return nftDriverId as NftDriverId; +} + +export function assertIsNftDriverId(id: string): asserts id is NftDriverId { + if (!isNftDriverId(id)) { + throw new Error(`Failed to assert: '${id}' is not a valid NftDriver ID.`); + } } +// AddressDriver export function isAddressDriverId( - idAsString: string, -): idAsString is AddressDriverId { - const isNaN = Number.isNaN(Number(idAsString)); + idString: string, +): idString is AddressDriverId { + const isNaN = Number.isNaN(Number(idString)); const isAccountIdOfAddressDriver = - getContractNameFromAccountId(idAsString) === 'addressDriver'; + getContractNameFromAccountId(idString) === 'addressDriver'; if (isNaN || !isAccountIdOfAddressDriver) { return false; @@ -57,56 +120,166 @@ export function isAddressDriverId( return true; } -export function assertAddressDiverId( +export function convertToAddressDriverId(id: string): AddressDriverId { + if (!isAddressDriverId(id)) { + throw new Error( + `Failed to convert: '${id}' is not a valid AddressDriver ID.`, + ); + } + + return id as AddressDriverId; +} + +export function assertIsAddressDiverId( id: string, ): asserts id is AddressDriverId { if (!isAddressDriverId(id)) { - throw new Error(`String ${id} is not a valid 'AddressDriverId'.`); + throw new Error( + `Failed to assert: '${id}' is not a valid AddressDriver ID.`, + ); } } -export function isNftDriverId(id: string): id is NftDriverId { - const isNaN = Number.isNaN(Number(id)); - const isAccountIdOfNftDriver = - getContractNameFromAccountId(id) === 'nftDriver'; +// ImmutableSplitsDriver +export function isImmutableSplitsDriverId( + id: string | bigint, +): id is ImmutableSplitsDriverId { + const idString = typeof id === 'bigint' ? id.toString() : id; + const isNaN = Number.isNaN(Number(idString)); + const immutableSplitsDriverId = + getContractNameFromAccountId(idString) === 'immutableSplitsDriver'; - if (isNaN || !isAccountIdOfNftDriver) { + if (isNaN || !immutableSplitsDriverId) { return false; } return true; } -export function assertNftDriverAccountId( +export function convertToImmutableSplitsDriverId( + id: string | bigint, +): ImmutableSplitsDriverId { + const stringId = typeof id === 'bigint' ? id.toString() : id; + + if (!isImmutableSplitsDriverId(stringId)) { + throw new Error( + `Failed to convert: '${id}' is not a valid ImmutableSplitsDriver ID.`, + ); + } + + return stringId as ImmutableSplitsDriverId; +} + +export function assertIsImmutableSplitsDriverId( id: string, -): asserts id is NftDriverId { - if (!isNftDriverId(id)) { - throw new Error(`String ${id} is not a valid 'NftDriverId'.`); +): asserts id is ImmutableSplitsDriverId { + if (!isImmutableSplitsDriverId(id)) { + throw new Error( + `Failed to assert: '${id}' is not a valid ImmutableSplitsDriver ID.`, + ); } } -export function isRepoDriverId(id: string): id is RepoDriverId { - const isNaN = Number.isNaN(Number(id)); - const isAccountIdOfRepoDriver = - getContractNameFromAccountId(id) === 'repoDriver'; +// RepoSubAccountDriver +export function isRepoSubAccountDriverId( + id: string | bigint, +): id is RepoSubAccountDriverId { + const idString = typeof id === 'bigint' ? id.toString() : id; + const isNaN = Number.isNaN(Number(idString)); + const isAccountIdOfRepoSubAccountDriver = + getContractNameFromAccountId(idString) === 'repoSubAccountDriver'; - if (isNaN || !isAccountIdOfRepoDriver) { + if (isNaN || !isAccountIdOfRepoSubAccountDriver) { return false; } return true; } -export function assertRepoDiverAccountId( +export function assertIsRepoSubAccountDriverId( id: string, -): asserts id is RepoDriverId { - if (!isRepoDriverId(id)) { - throw new Error(`String ${id} is not a valid 'RepoDriverId'.`); +): asserts id is RepoSubAccountDriverId { + if (!isRepoSubAccountDriverId(id)) { + throw new Error( + `Failed to assert: '${id}' is not a valid RepoSubAccountDriverId ID.`, + ); + } +} + +export async function transformRepoDriverId( + id: string, + direction: 'toParent' | 'toSub', +): Promise { + if (direction === 'toParent') { + assertIsRepoSubAccountDriverId(id); + } else { + assertIsRepoDriverId(id); + } + + const transformedId = ( + await repoSubAccountDriverContract.calcAccountId(id) + ).toString(); + + if (direction === 'toParent') { + assertIsRepoDriverId(transformedId); + } else { + assertIsRepoSubAccountDriverId(transformedId); + } + + const recalculatedId = ( + await repoSubAccountDriverContract.calcAccountId(transformedId) + ).toString(); + + if (recalculatedId !== id) { + unreachableError( + `Failed to transform RepoDriver ID: '${id}' does not match the recalculated ID '${recalculatedId}'.`, + ); } + + return transformedId as RepoDriverId; } -export async function calcAccountId(owner: AddressLike): Promise { - return ( - await addressDriverContract.calcAccountId(owner as string) - ).toString() as AccountId; +export async function calcParentRepoDriverId( + subAccountId: string, +): Promise { + return transformRepoDriverId(subAccountId, 'toParent'); +} + +export async function calcSubRepoDriverId( + parentId: string, +): Promise { + return transformRepoDriverId(parentId, 'toSub'); +} + +// Account ID +export function convertToAccountId(id: bigint | string): AccountId { + const accountIdAsString = typeof id === 'bigint' ? id.toString() : id; + + if ( + isRepoDriverId(accountIdAsString) || + isNftDriverId(accountIdAsString) || + isAddressDriverId(accountIdAsString) || + isImmutableSplitsDriverId(accountIdAsString) + ) { + return accountIdAsString as AccountId; + } + + throw new Error(`Failed to convert: '${id}' is not a valid account ID.`); +} + +export function assertIsAccountId( + id: string | bigint, +): asserts id is AccountId { + const accountId = typeof id === 'bigint' ? id.toString() : id; + + if ( + !isRepoDriverId(accountId) && + !isNftDriverId(accountId) && + !isAddressDriverId(accountId) && + !isImmutableSplitsDriverId(accountId) + ) { + throw new Error( + `Failed to assert: '${accountId}' is not a valid account ID.`, + ); + } } diff --git a/src/utils/assert.ts b/src/utils/assert.ts index 7183609..59e0a1a 100644 --- a/src/utils/assert.ts +++ b/src/utils/assert.ts @@ -1,6 +1,4 @@ -import type { UUID } from 'crypto'; import type { Transaction } from 'sequelize'; -import type { Dependency, DependencyOfProjectType } from '../core/types'; import type { EventSignature } from '../events/types'; export function assertTransaction( @@ -11,15 +9,6 @@ export function assertTransaction( } } -export function assertRequestId(requestId: string): asserts requestId is UUID { - const uuidRegExp = - /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/; - - if (!uuidRegExp.test(requestId)) { - throw new Error(`Request ID ${requestId} is not a valid UUID.`); - } -} - export function assertEventSignature( eventSignature: string, expectedEventSignature: EventSignature, @@ -30,19 +19,3 @@ export function assertEventSignature( ); } } - -export function isDependencyOfProjectType( - dependency: Dependency, -): dependency is DependencyOfProjectType { - return 'source' in dependency; -} - -export function assertDependencyOfProjectType( - project: Dependency, -): asserts project is DependencyOfProjectType { - if (!isDependencyOfProjectType(project)) { - throw new Error( - `Dependency with account ID ${project.accountId} is not a valid DependencyOfProjectType.`, - ); - } -} diff --git a/src/utils/contractUtils.ts b/src/utils/contractUtils.ts deleted file mode 100644 index dfb293e..0000000 --- a/src/utils/contractUtils.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { DripsContract } from '../core/types'; - -export function getContractNameFromAccountId(id: string): DripsContract { - if (Number.isNaN(Number(id))) { - throw new Error(`Could not get bits: ${id} is not a number.`); - } - - const accountIdAsBigInt = BigInt(id); - - if (accountIdAsBigInt < 0n || accountIdAsBigInt > 2n ** 256n - 1n) { - throw new Error( - `Could not get bits: ${id} is not a valid positive number within the range of a uint256.`, - ); - } - - const mask = 2n ** 32n - 1n; // 32 bits mask - - const bits = (accountIdAsBigInt >> 224n) & mask; // eslint-disable-line no-bitwise - - switch (bits) { - case 0n: - return 'addressDriver'; - case 1n: - return 'nftDriver'; - case 2n: - return 'immutableSplitsDriver'; - case 3n: - return 'repoDriver'; - default: - throw new Error(`Unknown driver for ID ${id}.`); - } -} diff --git a/src/utils/formatSplitReceivers.ts b/src/utils/formatSplitReceivers.ts new file mode 100644 index 0000000..a31ba24 --- /dev/null +++ b/src/utils/formatSplitReceivers.ts @@ -0,0 +1,34 @@ +import type { SplitsReceiverStruct } from '../../contracts/CURRENT_NETWORK/Drips'; + +export function formatSplitReceivers( + receivers: SplitsReceiverStruct[], +): SplitsReceiverStruct[] { + // Splits receivers must be sorted by user ID, deduplicated, and without weights <= 0. + + const uniqueReceivers = receivers.reduce( + (unique: SplitsReceiverStruct[], o) => { + if ( + !unique.some( + (obj: SplitsReceiverStruct) => + obj.accountId === o.accountId && obj.weight === o.weight, + ) + ) { + unique.push(o); + } + return unique; + }, + [], + ); + + const sortedReceivers = uniqueReceivers.sort((a, b) => + // Sort by user ID. + // eslint-disable-next-line no-nested-ternary + BigInt(a.accountId) > BigInt(b.accountId) + ? 1 + : BigInt(a.accountId) < BigInt(b.accountId) + ? -1 + : 0, + ); + + return sortedReceivers; +} diff --git a/src/utils/getAccountAddress.ts b/src/utils/getAccountAddress.ts deleted file mode 100644 index 5d30adc..0000000 --- a/src/utils/getAccountAddress.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-disable no-bitwise */ -import { ethers } from 'ethers'; -import { isAddressDriverId } from './accountIdUtils'; - -export default function getUserAddress(accountId: string): string { - if (!accountId) { - throw new Error(`Could not get user address: accountId is missing.`); - } - - const accountIdAsBn = BigInt(accountId); - - if (accountIdAsBn < 0 || accountIdAsBn > ethers.MaxUint256) { - throw new Error( - `Could not get user address: ${accountId} is not a valid positive number within the range of a uint256.`, - ); - } - - if (isAddressDriverId(accountId)) { - const mid64BitsMask = (BigInt(2) ** BigInt(64) - BigInt(1)) << BigInt(160); - - if ((accountIdAsBn & mid64BitsMask) !== BigInt(0)) { - throw new Error( - `Could not get user address: ${accountId} is not a valid user ID. The first 64 (after first 32) bits must be 0.`, - ); - } - } - - const mask = BigInt(2) ** BigInt(160) - BigInt(1); - const address = accountIdAsBn & mask; - - // Convert BigInt to a hex string and pad with zeros - const paddedAddress = address.toString(16).padStart(40, '0').toLowerCase(); - - // You would still use ethers.js to checksum the address - return ethers.getAddress(`0x${paddedAddress}`); -} diff --git a/src/utils/getCurrentSplits.ts b/src/utils/getCurrentSplits.ts deleted file mode 100644 index 1f07e70..0000000 --- a/src/utils/getCurrentSplits.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Op } from 'sequelize'; -import type { AccountId } from '../core/types'; -import { - AddressDriverSplitReceiverModel, - DripListSplitReceiverModel, - RepoDriverSplitReceiverModel, - StreamReceiverSeenEventModel, -} from '../models'; - -export async function getCurrentSplitsByAccountId( - emmiterAccountId: AccountId, -): Promise { - const [addressSplits, dripListSplits, projectSplits] = await Promise.all([ - await AddressDriverSplitReceiverModel.findAll({ - where: { - [Op.or]: [ - { funderProjectId: emmiterAccountId }, - { funderDripListId: emmiterAccountId }, - ], - }, - lock: true, - }), - await DripListSplitReceiverModel.findAll({ - where: { - [Op.or]: [ - { funderProjectId: emmiterAccountId }, - { funderDripListId: emmiterAccountId }, - ], - }, - lock: true, - }), - await RepoDriverSplitReceiverModel.findAll({ - where: { - [Op.or]: [ - { funderProjectId: emmiterAccountId }, - { funderDripListId: emmiterAccountId }, - ], - }, - lock: true, - }), - ]); - - const accountIds = [ - ...addressSplits.map((receiver) => receiver.fundeeAccountId), - ...dripListSplits.map((receiver) => receiver.fundeeDripListId), - ...projectSplits.map((receiver) => receiver.fundeeProjectId), - ]; - - return Array.from(new Set(accountIds)); -} - -export async function getCurrentSplitsByReceiversHash( - receiversHash: string, -): Promise { - const streamReceiverSeenEvents = await StreamReceiverSeenEventModel.findAll({ - where: { - receiversHash, - }, - lock: true, - }); - - const accountIds = streamReceiverSeenEvents.map((event) => event.accountId); - - return Array.from(new Set(accountIds)); -} diff --git a/src/utils/gitProjectUtils.ts b/src/utils/gitProjectUtils.ts deleted file mode 100644 index cd9d8eb..0000000 --- a/src/utils/gitProjectUtils.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { AddressLike } from 'ethers'; -import { ethers } from 'ethers'; -import { FORGES_MAP } from '../core/constants'; -import type { Forge } from '../core/types'; -import type { GitProjectModel } from '../models'; -import { ProjectVerificationStatus } from '../models/GitProjectModel'; -import unreachableError from './unreachableError'; - -export function toProjectOwnerAddress(address: string): AddressLike { - if (!ethers.isAddress(address)) { - throw new Error(`Invalid owner address: ${address}.`); - } - - return address as AddressLike; -} - -export function toUrl(forge: Forge, projectName: string): string { - switch (forge) { - case 'GitHub': - return `https://github.com/${projectName}`; - default: - throw new Error(`Unsupported forge: ${forge}.`); - } -} - -export function toForge(forge: bigint): Forge { - const forgeAsString = FORGES_MAP[Number(forge) as keyof typeof FORGES_MAP]; - - if (!forgeAsString) { - throw new Error(`Invalid forge value: ${forge}.`); - } - - return forgeAsString; -} - -export function toReadable(bytes: string): string { - return ethers.toUtf8String(bytes); -} - -export function calculateProjectStatus( - project: GitProjectModel, -): ProjectVerificationStatus { - if (!project.ownerAddress && !project.color) { - return ProjectVerificationStatus.Unclaimed; - } - - if (project.ownerAddress && project.color) { - return ProjectVerificationStatus.Claimed; - } - - if (project.ownerAddress && !project.color) { - return ProjectVerificationStatus.PendingMetadata; - } - - if (!project.ownerAddress && project.color) { - return ProjectVerificationStatus.PendingOwner; - } - - return unreachableError( - `Project with ID ${project.id} (${project.name}) has an invalid status. - \r\tProject: ${JSON.stringify(project, null, 2)}`, - ); -} diff --git a/src/utils/eventUtils.ts b/src/utils/isLatestEvent.ts similarity index 100% rename from src/utils/eventUtils.ts rename to src/utils/isLatestEvent.ts diff --git a/src/utils/lastProcessedVersion.ts b/src/utils/lastProcessedVersion.ts new file mode 100644 index 0000000..4b794cf --- /dev/null +++ b/src/utils/lastProcessedVersion.ts @@ -0,0 +1,23 @@ +/* eslint-disable no-bitwise */ + +/** + * Packs a blockNumber and logIndex into a single BigInt “version.” + */ +export function makeVersion(blockNumber: number, logIndex: number): bigint { + // shift `blockNumber` into the high‐32 bits, OR in the low‐32‐bit `logIndex`. + return (BigInt(blockNumber) << 32n) | BigInt(logIndex); +} + +/** + * Unpacks a BigInt “version” back into its `blockNumber` and `logIndex` parts. + */ +export function decodeVersion(version: bigint): { + blockNumber: number; + logIndex: number; +} { + // High 32 bits contain the blockNumber. + const blockNumber = Number(version >> 32n); + // Low 32 bits contain the logIndex. + const logIndex = Number(version & ((1n << 32n) - 1n)); + return { blockNumber, logIndex }; +} diff --git a/src/utils/metadataUtils.ts b/src/utils/metadataUtils.ts index 6a112b0..25ce1d5 100644 --- a/src/utils/metadataUtils.ts +++ b/src/utils/metadataUtils.ts @@ -1,19 +1,20 @@ -import { ethers } from 'ethers'; +import { toUtf8String } from 'ethers'; import type { AnyVersion } from '@efstajas/versioned-parser'; import type { IpfsHash } from '../core/types'; import { + immutableSplitsDriverMetadataParser, nftDriverAccountMetadataParser, repoDriverAccountMetadataParser, } from '../metadata/schemas'; import appSettings from '../config/appSettings'; -export function toIpfsHash(str: string): IpfsHash { - const ipfsHash = ethers.toUtf8String(str); +export function convertToIpfsHash(str: string): IpfsHash { + const ipfsHash = toUtf8String(str); const isIpfsHash = /^(Qm[a-zA-Z0-9]{44})$/.test(ipfsHash); if (!isIpfsHash) { - throw new Error('The provided string is not a valid IPFS hash.'); + throw new Error(`Failed to convert: '${str}' is not a valid IPFS hash.`); } return ipfsHash as IpfsHash; @@ -32,11 +33,24 @@ async function getIpfsFile(hash: IpfsHash): Promise { return fetch(`${appSettings.ipfsGatewayUrl}/ipfs/${hash}`); } -export default async function getNftDriverMetadata( +export async function getNftDriverMetadata( ipfsHash: IpfsHash, ): Promise> { + try { + const ipfsFile = await (await getIpfsFile(ipfsHash)).json(); + const metadata = nftDriverAccountMetadataParser.parseAny(ipfsFile); + + return metadata; + } catch (error) { + throw new Error(`Failed to fetch NFT driver metadata from IPFS: ${error}`); + } +} + +export async function getImmutableSpitsDriverMetadata( + ipfsHash: IpfsHash, +): Promise> { const ipfsFile = await (await getIpfsFile(ipfsHash)).json(); - const metadata = nftDriverAccountMetadataParser.parseAny(ipfsFile); + const metadata = immutableSplitsDriverMetadataParser.parseAny(ipfsFile); return metadata; } diff --git a/src/utils/projectUtils.ts b/src/utils/projectUtils.ts new file mode 100644 index 0000000..b2516e4 --- /dev/null +++ b/src/utils/projectUtils.ts @@ -0,0 +1,100 @@ +import { hexlify, toUtf8Bytes } from 'ethers'; +import type { z } from 'zod'; +import unreachableError from './unreachableError'; +import type ProjectModel from '../models/ProjectModel'; +import type { Forge, ProjectVerificationStatus } from '../models/ProjectModel'; +import { repoDriverContract } from '../core/contractClients'; +import type { sourceSchema } from '../metadata/schemas/common/sources'; +import { + calcParentRepoDriverId, + isRepoDriverId, + isRepoSubAccountDriverId, +} from './accountIdUtils'; + +export function convertForgeToNumber(forge: Forge) { + switch (forge) { + case 'github': + return 0; + case 'gitlab': + return 1; + default: + return unreachableError( + `Failed to convert: '${forge}' is not a valid forge.`, + ); + } +} + +export function calculateProjectStatus( + project: ProjectModel, +): ProjectVerificationStatus { + const hasOwner = Boolean(project.ownerAddress); + const hasMetadata = Boolean(project.lastProcessedIpfsHash); + + if (hasOwner && hasMetadata) { + return 'claimed'; + } + + if (!hasOwner && !hasMetadata) { + return 'unclaimed'; + } + + if (hasOwner) { + return 'pending_metadata'; + } + + return unreachableError( + `Invalid project status: hasOwner=${hasOwner}, hasMetadata=${hasMetadata}`, + ); +} + +export async function verifyProjectSources( + projects: { + accountId: string; + source: z.infer; + }[], +): Promise<{ + areProjectsValid: boolean; + message?: string; +}> { + const errors: string[] = []; + for (const { + accountId, + source: { forge, ownerName, repoName }, + } of projects) { + const isSubAccount = isRepoSubAccountDriverId(accountId.toString()); + const isParentAccount = isRepoDriverId(accountId.toString()); + + if (!isSubAccount && !isParentAccount) { + unreachableError( + `Invalid account ID: '${accountId}' is not a valid RepoDriver or RepoSubAccount ID.`, + ); + } + const calculatedParentAccountId = await repoDriverContract.calcAccountId( + convertForgeToNumber(forge), + hexlify(toUtf8Bytes(`${ownerName}/${repoName}`)), + ); + + if (isSubAccount) { + const parentId = await calcParentRepoDriverId(accountId); + + if (parentId !== calculatedParentAccountId.toString()) { + errors.push( + `Mismatch for '${ownerName}/${repoName}' on '${forge}': for sub account '${accountId}', expected parent '${calculatedParentAccountId}', got '${parentId}'.`, + ); + } + } else if (accountId !== calculatedParentAccountId.toString()) { + errors.push( + `Mismatch for '${ownerName}/${repoName}' on '${forge}': expected parent account '${calculatedParentAccountId}', got '${accountId}'.`, + ); + } + } + if (errors.length > 0) { + return { + areProjectsValid: false, + message: `Failed to verify project sources:\n${errors.join('\n')}`, + }; + } + return { + areProjectsValid: true, + }; +} diff --git a/src/utils/recoverableError.ts b/src/utils/recoverableError.ts new file mode 100644 index 0000000..a47f87c --- /dev/null +++ b/src/utils/recoverableError.ts @@ -0,0 +1,5 @@ +export default class RecoverableError extends Error { + constructor(message: string) { + super(message); + } +} diff --git a/src/utils/retryOperation.ts b/src/utils/retryOperation.ts deleted file mode 100644 index 1d2456d..0000000 --- a/src/utils/retryOperation.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { Result } from '../core/types'; - -async function sleep(milliseconds: number): Promise { - return new Promise((resolve) => setTimeout(resolve, milliseconds)); // eslint-disable-line no-promise-executor-return -} - -type RetryError = { - message: string; - errors: string[]; - attempts: number; -}; - -export function isRetryError(err: unknown): err is RetryError { - return ( - typeof err === 'object' && - err !== null && - 'message' in err && - 'errors' in err && - 'attempts' in err - ); -} - -export default async function retryOperation( - operation: () => T | Promise, - maxRetries: number = 3, -): Promise> { - let attempts = 0; - const baseDelay = 100; - const errors: string[] = []; - - while (attempts < maxRetries) { - attempts += 1; - - try { - const result = await Promise.resolve(operation()); - return { - ok: true, - value: result, - }; - } catch (error: any) { - errors.push(error.message); - - if (attempts < maxRetries) { - const delay = baseDelay * 2 ** attempts; - await sleep(delay); - } - } - } - - return { - ok: false, - error: { - message: errors[errors.length - 1], - errors, - attempts, - }, - }; -} diff --git a/tests/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata.test.ts b/tests/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/tests/eventHandlers/AccountMetadataEmittedEventHandler.test.ts b/tests/eventHandlers/AccountMetadataEmittedEventHandler.test.ts index b94a328..e7fed9e 100644 --- a/tests/eventHandlers/AccountMetadataEmittedEventHandler.test.ts +++ b/tests/eventHandlers/AccountMetadataEmittedEventHandler.test.ts @@ -1,28 +1,32 @@ /* eslint-disable dot-notation */ import { randomUUID } from 'crypto'; +import { hexlify, toUtf8Bytes } from 'ethers'; import { AccountMetadataEmittedEventHandler } from '../../src/eventHandlers'; import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import type { EventData } from '../../src/events/types'; import { dbConnection } from '../../src/db/database'; import AccountMetadataEmittedEventModel from '../../src/models/AccountMetadataEmittedEventModel'; -import { isLatestEvent } from '../../src/utils/eventUtils'; -import { toAccountId } from '../../src/utils/accountIdUtils'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; import { DRIPS_APP_USER_METADATA_KEY } from '../../src/core/constants'; -import * as handleGitProjectMetadata from '../../src/eventHandlers/AccountMetadataEmittedEvent/gitProject/handleGitProjectMetadata'; -import { toIpfsHash } from '../../src/utils/metadataUtils'; -import * as handleDripListMetadata from '../../src/eventHandlers/AccountMetadataEmittedEvent/dripList/handleDripListMetadata'; +import * as handleProjectMetadata from '../../src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata'; +import { + convertToIpfsHash, + getNftDriverMetadata, +} from '../../src/utils/metadataUtils'; +import * as handleDripListMetadata from '../../src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleDripListMetadata'; jest.mock('../../src/models/AccountMetadataEmittedEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); -jest.mock('../../src/utils/eventUtils'); +jest.mock('../../src/core/ScopedLogger'); +jest.mock('../../src/events/eventHandlerUtils'); jest.mock( - '../../src/eventHandlers/AccountMetadataEmittedEvent/gitProject/handleGitProjectMetadata', + '../../src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleProjectMetadata', ); jest.mock( - '../../src/eventHandlers/AccountMetadataEmittedEvent/dripList/handleDripListMetadata', + '../../src/eventHandlers/AccountMetadataEmittedEvent/handlers/handleDripListMetadata', ); +jest.mock('../../src/utils/metadataUtils'); describe('AccountMetadataEmittedHandler', () => { let mockDbTransaction: {}; @@ -51,6 +55,8 @@ describe('AccountMetadataEmittedHandler', () => { mockDbTransaction = {}; + (convertToIpfsHash as jest.Mock).mockReturnValue('ipfsHash'); + dbConnection.transaction = jest .fn() .mockImplementation((callback) => callback(mockDbTransaction)); @@ -64,8 +70,29 @@ describe('AccountMetadataEmittedHandler', () => { event: { args: [ 80920745289880686872077472087501508459438916877610571750365932290048n, - 'key', - 'value', + hexlify(toUtf8Bytes('key')), + '0x516d65444e625169575257666333395844754d354d69796337725755465156666b706d5a7675723965757767584a', + ], + logIndex: 1, + blockNumber: 1, + blockTimestamp: new Date(), + transactionHash: 'requestTransactionHash', + } as EventData<'AccountMetadataEmitted(uint256,bytes32,bytes)'>, + }); + + // Assert + expect(dbConnection.transaction).not.toHaveBeenCalled(); + }); + + test('should return if the metadata are not emitted by a supported Driver', async () => { + // Act + await handler['_handle']({ + id: randomUUID(), + event: { + args: [ + 1n, + DRIPS_APP_USER_METADATA_KEY, + '0x516d65444e625169575257666333395844754d354d69796337725755465156666b706d5a7675723965757767584a', ], logIndex: 1, blockNumber: 1, @@ -78,19 +105,14 @@ describe('AccountMetadataEmittedHandler', () => { expect(dbConnection.transaction).not.toHaveBeenCalled(); }); - test('should create a new AccountMetadataEmittedEventModel', async () => { + test('should create a new AccountMetadataEmittedEvent', async () => { // Arrange - AccountMetadataEmittedEventModel.findOrCreate = jest - .fn() - .mockResolvedValue([ - { - transactionHash: 'AccountMetadataEmittedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - (isLatestEvent as jest.Mock).mockResolvedValue(false); + AccountMetadataEmittedEventModel.create = jest.fn().mockResolvedValue([ + { + transactionHash: 'AccountMetadataEmittedEventTransactionHash', + logIndex: 1, + }, + ]); // Act await handler['_handle'](mockRequest); @@ -106,69 +128,56 @@ describe('AccountMetadataEmittedHandler', () => { }, } = mockRequest; - expect( - AccountMetadataEmittedEventModel.findOrCreate, - ).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { + expect(AccountMetadataEmittedEventModel.create).toHaveBeenCalledWith( + { key, value, logIndex, blockNumber, blockTimestamp, transactionHash, - accountId: toAccountId(accountId), + accountId: convertToAccountId(accountId), }, - }); + { + transaction: mockDbTransaction, + }, + ); }); test('should handle Project metadata when metadata are coming from a Project and the incoming event is the latest', async () => { // Arrange - AccountMetadataEmittedEventModel.findOrCreate = jest - .fn() - .mockResolvedValue([ - { - transactionHash: 'AccountMetadataEmittedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - (isLatestEvent as jest.Mock).mockResolvedValue(true); + AccountMetadataEmittedEventModel.create = jest.fn().mockResolvedValue([ + { + transactionHash: 'AccountMetadataEmittedEventTransactionHash', + logIndex: 1, + }, + true, + ]); - (handleGitProjectMetadata.default as jest.Mock) = jest.fn(); + (handleProjectMetadata.default as jest.Mock) = jest.fn(); // Act await handler['_handle'](mockRequest); // Assert - expect(handleGitProjectMetadata.default).toHaveBeenCalledWith( - expect.anything(), - toAccountId(mockRequest.event.args[0]), - mockDbTransaction, - toIpfsHash(mockRequest.event.args[2]), - mockRequest.event.blockTimestamp, - ); + expect(handleProjectMetadata.default).toHaveBeenCalledWith({ + scopedLogger: expect.anything(), + emitterAccountId: convertToAccountId(mockRequest.event.args[0]), + transaction: mockDbTransaction, + ipfsHash: convertToIpfsHash(mockRequest.event.args[2]), + blockTimestamp: mockRequest.event.blockTimestamp, + }); }); test('should handle Drip List metadata when metadata are coming from a Drip List and the incoming event is the latest', async () => { // Arrange - AccountMetadataEmittedEventModel.findOrCreate = jest - .fn() - .mockResolvedValue([ - { - transactionHash: 'AccountMetadataEmittedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - (isLatestEvent as jest.Mock).mockResolvedValue(true); + AccountMetadataEmittedEventModel.create = jest.fn().mockResolvedValue([ + { + transactionHash: 'AccountMetadataEmittedEventTransactionHash', + logIndex: 1, + }, + true, + ]); (handleDripListMetadata.default as jest.Mock) = jest.fn(); @@ -178,7 +187,7 @@ describe('AccountMetadataEmittedHandler', () => { args: [ 42090747530143187925772296541596488845753594998762284015257144913834n, DRIPS_APP_USER_METADATA_KEY, - '0x516d65444e625169575257666333395844754d354d69796337725755465156666b706d5a7675723965757767584a', + '0x516d647379466476796f35484b554d4158795478737163786d795a6f3233556e31764e52786b3331707176587571', ], logIndex: 1, blockNumber: 1, @@ -187,18 +196,25 @@ describe('AccountMetadataEmittedHandler', () => { } as EventData<'AccountMetadataEmitted(uint256,bytes32,bytes)'>, }; + const mockMetadata = { + type: 'dripList', + }; + (getNftDriverMetadata as jest.Mock).mockResolvedValue(mockMetadata); + // Act await new AccountMetadataEmittedEventHandler()['_handle'](request); // Assert - expect(handleDripListMetadata.default).toHaveBeenCalledWith( - expect.anything(), - toAccountId(request.event.args[0]), - mockDbTransaction, - toIpfsHash(request.event.args[2]), - request.event.blockTimestamp, - 1, - ); + expect(handleDripListMetadata.default).toHaveBeenCalledWith({ + ipfsHash: convertToIpfsHash(request.event.args[2]), + metadata: mockMetadata, + scopedLogger: expect.anything(), + logIndex: request.event.logIndex, + transaction: mockDbTransaction, + blockTimestamp: request.event.blockTimestamp, + blockNumber: request.event.blockNumber, + emitterAccountId: convertToAccountId(request.event.args[0]), + }); }); }); }); diff --git a/tests/eventHandlers/GivenEventHandler.test.ts b/tests/eventHandlers/GivenEventHandler.test.ts index 36e96a7..eaa482a 100644 --- a/tests/eventHandlers/GivenEventHandler.test.ts +++ b/tests/eventHandlers/GivenEventHandler.test.ts @@ -4,16 +4,16 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; import GivenEventModel from '../../src/models/GivenEventModel'; -import LogManager from '../../src/core/LogManager'; +import ScopedLogger from '../../src/core/ScopedLogger'; import GivenEventHandler from '../../src/eventHandlers/GivenEventHandler'; -import { toAccountId } from '../../src/utils/accountIdUtils'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; import { toAddress } from '../../src/utils/ethereumAddressUtils'; import { toBigIntString } from '../../src/utils/bigintUtils'; jest.mock('../../src/models/GivenEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); +jest.mock('../../src/core/ScopedLogger'); describe('GivenEventHandler', () => { let mockDbTransaction: {}; @@ -51,15 +51,14 @@ describe('GivenEventHandler', () => { describe('_handle', () => { test('should create a new GivenEventModel', async () => { // Arrange - GivenEventModel.findOrCreate = jest.fn().mockResolvedValue([ + GivenEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'GivenEventTransactionHash', logIndex: 1, }, - true, ]); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); // Act await handler['_handle'](mockRequest); @@ -75,16 +74,10 @@ describe('GivenEventHandler', () => { }, } = mockRequest; - expect(GivenEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId: toAccountId(rawAccountId), - receiver: toAccountId(rawReceiver), + expect(GivenEventModel.create).toHaveBeenCalledWith( + { + accountId: convertToAccountId(rawAccountId), + receiver: convertToAccountId(rawReceiver), erc20: toAddress(rawErc20), amt: toBigIntString(rawAmt.toString()), logIndex, @@ -92,7 +85,10 @@ describe('GivenEventHandler', () => { blockTimestamp, transactionHash, }, - }); + { + transaction: mockDbTransaction, + }, + ); }); }); }); diff --git a/tests/eventHandlers/OwnerUpdateRequestedEventHandler.test.ts b/tests/eventHandlers/OwnerUpdateRequestedEventHandler.test.ts deleted file mode 100644 index 1bcbe74..0000000 --- a/tests/eventHandlers/OwnerUpdateRequestedEventHandler.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -/* eslint-disable dot-notation */ -import { randomUUID } from 'crypto'; -import { ethers } from 'ethers'; -import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; -import { OwnerUpdateRequestedEventHandler } from '../../src/eventHandlers'; -import { dbConnection } from '../../src/db/database'; -import type { EventData } from '../../src/events/types'; -import { toRepoDriverId } from '../../src/utils/accountIdUtils'; -import { - calculateProjectStatus, - toForge, - toReadable, - toUrl, -} from '../../src/utils/gitProjectUtils'; -import OwnerUpdateRequestedEventModel from '../../src/models/OwnerUpdateRequestedEventModel'; -import GitProjectModel, { - ProjectVerificationStatus, -} from '../../src/models/GitProjectModel'; -import LogManager from '../../src/core/LogManager'; -import { isLatestEvent } from '../../src/utils/eventUtils'; - -jest.mock('../../src/models/OwnerUpdateRequestedEventModel'); -jest.mock('../../src/models/GitProjectModel'); -jest.mock('../../src/db/database'); -jest.mock('bee-queue'); -jest.mock('../../src/utils/eventUtils'); -jest.mock('../../src/core/LogManager'); - -describe('OwnerUpdateRequestedEventHandler', () => { - let mockDbTransaction: {}; - let handler: OwnerUpdateRequestedEventHandler; - let mockRequest: EventHandlerRequest<'OwnerUpdateRequested(uint256,uint8,bytes)'>; - - beforeAll(() => { - jest.clearAllMocks(); - - handler = new OwnerUpdateRequestedEventHandler(); - - mockRequest = { - id: randomUUID(), - event: { - args: [ - 80920745289880686872077472087501508459438916877610571750365932290048n, - 0n, - ethers.encodeBytes32String('name'), - ], - logIndex: 1, - blockNumber: 1, - blockTimestamp: new Date(), - transactionHash: 'requestTransactionHash', - } as EventData<'OwnerUpdateRequested(uint256,uint8,bytes)'>, - }; - - mockDbTransaction = {}; - - dbConnection.transaction = jest - .fn() - .mockImplementation((callback) => callback(mockDbTransaction)); - }); - - describe('_handle', () => { - test('should create new OwnerUpdateRequestedEventModel and GitProjectModel', async () => { - // Arrange - OwnerUpdateRequestedEventModel.findOrCreate = jest - .fn() - .mockResolvedValue([ - { - transactionHash: 'OwnerUpdateRequestedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - GitProjectModel.findOrCreate = jest.fn().mockResolvedValue([ - { - id: toRepoDriverId(mockRequest.event.args[0]), - }, - true, - ]); - - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); - - // Act - await handler['_handle'](mockRequest); - - // Assert - const { - event: { - args: [accountId, forge, name], - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - } = mockRequest; - - expect(OwnerUpdateRequestedEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - name: toReadable(name), - forge: toForge(forge), - accountId: toRepoDriverId(accountId), - }, - }); - - expect(GitProjectModel.findOrCreate).toHaveBeenCalledWith({ - transaction: mockDbTransaction, - lock: true, - where: { - id: toRepoDriverId(accountId), - }, - defaults: { - id: toRepoDriverId(accountId), - isValid: true, - isVisible: true, - name: toReadable(name), - forge: toForge(forge), - url: toUrl(toForge(forge), toReadable(name)), - verificationStatus: ProjectVerificationStatus.OwnerUpdateRequested, - }, - }); - }); - - test('should update the GitProjectModel when the incoming event is the latest', async () => { - // Arrange - OwnerUpdateRequestedEventModel.findOrCreate = jest - .fn() - .mockResolvedValue([ - { - transactionHash: 'OwnerUpdateRequestedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - const mockGitProject = { - name: '', - forge: '', - url: '', - verificationStatus: ProjectVerificationStatus.Unclaimed, - save: jest.fn(), - }; - GitProjectModel.findOrCreate = jest - .fn() - .mockResolvedValue([mockGitProject, false]); - - (isLatestEvent as jest.Mock).mockResolvedValue(true); - - LogManager.prototype.appendIsLatestEventLog = jest.fn().mockReturnThis(); - - // Act - await handler['_handle'](mockRequest); - - // Assert - const { - event: { - // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars - args: [_, forge, name], - }, - } = mockRequest; - - expect(mockGitProject.name).toBe(toReadable(name)); - expect(mockGitProject.forge).toBe(toForge(forge)); - expect(mockGitProject.url).toBe(toUrl(toForge(forge), toReadable(name))); - expect(mockGitProject.verificationStatus).toBe( - calculateProjectStatus(mockGitProject as any), - ); - expect(mockGitProject.save).toHaveBeenCalledWith({ - transaction: mockDbTransaction, - }); - }); - }); -}); diff --git a/tests/eventHandlers/OwnerUpdatedEventHandler.test.ts b/tests/eventHandlers/OwnerUpdatedEventHandler.test.ts deleted file mode 100644 index 01f6320..0000000 --- a/tests/eventHandlers/OwnerUpdatedEventHandler.test.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* eslint-disable dot-notation */ -import { randomUUID } from 'crypto'; -import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; -import { OwnerUpdatedEventHandler } from '../../src/eventHandlers'; -import { dbConnection } from '../../src/db/database'; -import type { EventData } from '../../src/events/types'; -import { calcAccountId, toRepoDriverId } from '../../src/utils/accountIdUtils'; -import { calculateProjectStatus } from '../../src/utils/gitProjectUtils'; -import OwnerUpdatedEventModel from '../../src/models/OwnerUpdatedEventModel'; -import GitProjectModel, { - ProjectVerificationStatus, -} from '../../src/models/GitProjectModel'; -import LogManager from '../../src/core/LogManager'; -import { isLatestEvent } from '../../src/utils/eventUtils'; - -jest.mock('../../src/models/OwnerUpdatedEventModel'); -jest.mock('../../src/models/GitProjectModel'); -jest.mock('../../src/db/database'); -jest.mock('bee-queue'); -jest.mock('../../src/utils/eventUtils'); -jest.mock('../../src/core/LogManager'); -jest.mock('../../src/utils/accountIdUtils'); - -describe('OwnerUpdatedEventHandler', () => { - let mockDbTransaction: {}; - let handler: OwnerUpdatedEventHandler; - let mockRequest: EventHandlerRequest<'OwnerUpdated(uint256,address)'>; - - beforeAll(() => { - jest.clearAllMocks(); - - handler = new OwnerUpdatedEventHandler(); - - mockRequest = { - id: randomUUID(), - event: { - args: [ - 80920745289880686872077472087501508459438916877610571750365932290048n, - '0x20a9273a452268E5a034951ae5381a45E14aC2a3', - ], - logIndex: 1, - blockNumber: 1, - blockTimestamp: new Date(), - transactionHash: 'requestTransactionHash', - } as EventData<'OwnerUpdated(uint256,address)'>, - }; - - mockDbTransaction = {}; - - dbConnection.transaction = jest - .fn() - .mockImplementation((callback) => callback(mockDbTransaction)); - }); - - describe('_handle', () => { - test('should create new OwnerUpdatedEventModel and GitProjectModel', async () => { - // Arrange - OwnerUpdatedEventModel.findOrCreate = jest.fn().mockResolvedValue([ - { - transactionHash: 'OwnerUpdatedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - (toRepoDriverId as jest.Mock).mockReturnValue('1'); - - GitProjectModel.findOrCreate = jest.fn().mockResolvedValue([ - { - id: toRepoDriverId(mockRequest.event.args[0]), - }, - true, - ]); - - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); - - (calcAccountId as jest.Mock).mockResolvedValue('ownerAccountId'); - - // Act - await handler['_handle'](mockRequest); - - // Assert - const { - event: { - args: [accountId, owner], - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - }, - } = mockRequest; - - expect(OwnerUpdatedEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - owner, - logIndex, - blockNumber, - blockTimestamp, - transactionHash, - accountId: toRepoDriverId(accountId), - }, - }); - - expect(GitProjectModel.findOrCreate).toHaveBeenCalledWith({ - transaction: mockDbTransaction, - lock: true, - where: { - id: toRepoDriverId(accountId), - }, - defaults: { - id: toRepoDriverId(accountId), - isValid: true, - isVisible: true, - ownerAddress: owner, - claimedAt: blockTimestamp, - ownerAccountId: await calcAccountId(owner), - verificationStatus: ProjectVerificationStatus.OwnerUpdated, - }, - }); - }); - - test('should update the GitProjectModel when the incoming event is the latest', async () => { - // Arrange - OwnerUpdatedEventModel.findOrCreate = jest.fn().mockResolvedValue([ - { - transactionHash: 'OwnerUpdatedEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - const mockGitProject = { - ownerAddress: '', - ownerAccountId: '', - verificationStatus: ProjectVerificationStatus.Unclaimed, - save: jest.fn(), - }; - GitProjectModel.findOrCreate = jest - .fn() - .mockResolvedValue([mockGitProject, false]); - - (isLatestEvent as jest.Mock).mockResolvedValue(true); - - LogManager.prototype.appendIsLatestEventLog = jest.fn().mockReturnThis(); - - (calcAccountId as jest.Mock).mockResolvedValue('ownerAccountId'); - - // Act - await handler['_handle'](mockRequest); - - // Assert - const { - event: { - // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars - args: [accountId, owner], - }, - } = mockRequest; - - expect(mockGitProject.ownerAddress).toBe(owner); - expect(mockGitProject.ownerAccountId).toBe(await calcAccountId(owner)); - expect(mockGitProject.verificationStatus).toBe( - calculateProjectStatus(mockGitProject as any), - ); - expect(mockGitProject.save).toHaveBeenCalledWith({ - transaction: mockDbTransaction, - }); - }); - }); -}); diff --git a/tests/eventHandlers/SplitEventHandler.test.ts b/tests/eventHandlers/SplitEventHandler.test.ts index aabb747..bd9f5a6 100644 --- a/tests/eventHandlers/SplitEventHandler.test.ts +++ b/tests/eventHandlers/SplitEventHandler.test.ts @@ -4,16 +4,16 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; import SplitEventModel from '../../src/models/SplitEventModel'; -import LogManager from '../../src/core/LogManager'; +import ScopedLogger from '../../src/core/ScopedLogger'; import SplitEventHandler from '../../src/eventHandlers/SplitEventHandler'; -import { toAccountId } from '../../src/utils/accountIdUtils'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; import { toAddress } from '../../src/utils/ethereumAddressUtils'; import { toBigIntString } from '../../src/utils/bigintUtils'; jest.mock('../../src/models/SplitEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); +jest.mock('../../src/core/ScopedLogger'); describe('SplitEventHandler', () => { let mockDbTransaction: {}; @@ -51,15 +51,14 @@ describe('SplitEventHandler', () => { describe('_handle', () => { test('should create a new SplitEventModel', async () => { // Arrange - SplitEventModel.findOrCreate = jest.fn().mockResolvedValue([ + SplitEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'SplitEventTransactionHash', logIndex: 1, }, - true, ]); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); // Act await handler['_handle'](mockRequest); @@ -75,16 +74,10 @@ describe('SplitEventHandler', () => { }, } = mockRequest; - expect(SplitEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId: toAccountId(rawAccountId), - receiver: toAccountId(rawReceiver), + expect(SplitEventModel.create).toHaveBeenCalledWith( + { + accountId: convertToAccountId(rawAccountId), + receiver: convertToAccountId(rawReceiver), erc20: toAddress(rawErc20), amt: toBigIntString(rawAmt.toString()), logIndex, @@ -92,7 +85,10 @@ describe('SplitEventHandler', () => { blockTimestamp, transactionHash, }, - }); + { + transaction: mockDbTransaction, + }, + ); }); }); }); diff --git a/tests/eventHandlers/SplitsSetEventHandler.test.ts b/tests/eventHandlers/SplitsSetEventHandler.test.ts index 63b629e..3aa91f2 100644 --- a/tests/eventHandlers/SplitsSetEventHandler.test.ts +++ b/tests/eventHandlers/SplitsSetEventHandler.test.ts @@ -4,16 +4,16 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; import SplitsSetEventModel from '../../src/models/SplitsSetEventModel'; -import LogManager from '../../src/core/LogManager'; -import { toAccountId } from '../../src/utils/accountIdUtils'; -import { SplitsSetEventHandler } from '../../src/eventHandlers'; -import setIsValidFlag from '../../src/eventHandlers/SplitsSetEventHandler/setIsValidFlag'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; +import SplitsSetEventHandler from '../../src/eventHandlers/SplitsSetEvent/SplitsSetEventHandler'; +import ScopedLogger from '../../src/core/ScopedLogger'; +import setIsValidFlag from '../../src/eventHandlers/SplitsSetEvent/setIsValidFlag'; jest.mock('../../src/models/SplitsSetEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); -jest.mock('../../src/eventHandlers/SplitsSetEventHandler/setIsValidFlag'); +jest.mock('../../src/core/ScopedLogger'); +jest.mock('../../src/eventHandlers/SplitsSetEvent/setIsValidFlag'); describe('SplitsSetEventHandler', () => { let mockDbTransaction: {}; @@ -49,15 +49,14 @@ describe('SplitsSetEventHandler', () => { describe('_handle', () => { test('should create a new SplitsSetEventModel', async () => { // Arrange - SplitsSetEventModel.findOrCreate = jest.fn().mockResolvedValue([ + SplitsSetEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'SplitsSetTransactionHash', logIndex: 1, }, - true, ]); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); // Act await handler['_handle'](mockRequest); @@ -73,22 +72,19 @@ describe('SplitsSetEventHandler', () => { }, } = mockRequest; - expect(SplitsSetEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId: toAccountId(rawAccountId), + expect(SplitsSetEventModel.create).toHaveBeenCalledWith( + { + accountId: convertToAccountId(rawAccountId), receiversHash: rawReceiversHash, logIndex, blockNumber, blockTimestamp, transactionHash, }, - }); + { + transaction: mockDbTransaction, + }, + ); expect(setIsValidFlag).toHaveBeenCalled(); }); diff --git a/tests/eventHandlers/SqueezedStreamsEventHandler.test.ts b/tests/eventHandlers/SqueezedStreamsEventHandler.test.ts index f017586..e78619f 100644 --- a/tests/eventHandlers/SqueezedStreamsEventHandler.test.ts +++ b/tests/eventHandlers/SqueezedStreamsEventHandler.test.ts @@ -4,16 +4,16 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; import SqueezedStreamsEventModel from '../../src/models/SqueezedStreamsEventModel'; -import LogManager from '../../src/core/LogManager'; +import ScopedLogger from '../../src/core/ScopedLogger'; import SqueezedStreamsEventHandler from '../../src/eventHandlers/SqueezedStreamsEventHandler'; -import { toAccountId } from '../../src/utils/accountIdUtils'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; import { toAddress } from '../../src/utils/ethereumAddressUtils'; import { toBigIntString } from '../../src/utils/bigintUtils'; jest.mock('../../src/models/SqueezedStreamsEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); +jest.mock('../../src/core/ScopedLogger'); describe('SqueezedStreamsEventHandler', () => { let mockDbTransaction: {}; @@ -52,15 +52,14 @@ describe('SqueezedStreamsEventHandler', () => { describe('_handle', () => { test('should create a new SqueezedStreamsEventModel', async () => { // Arrange - SqueezedStreamsEventModel.findOrCreate = jest.fn().mockResolvedValue([ + SqueezedStreamsEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'SqueezedStreamsTransactionHash', logIndex: 1, }, - true, ]); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); // Act await handler['_handle'](mockRequest); @@ -82,17 +81,11 @@ describe('SqueezedStreamsEventHandler', () => { }, } = mockRequest; - expect(SqueezedStreamsEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId: toAccountId(rawAccountId), + expect(SqueezedStreamsEventModel.create).toHaveBeenCalledWith( + { + accountId: convertToAccountId(rawAccountId), erc20: toAddress(rawErc20), - senderId: toAccountId(rawSenderId), + senderId: convertToAccountId(rawSenderId), amount: toBigIntString(rawAmt.toString()), streamsHistoryHashes: SqueezedStreamsEventModel.toStreamHistoryHashes( rawStreamsHistoryHashes, @@ -102,7 +95,10 @@ describe('SqueezedStreamsEventHandler', () => { blockTimestamp, transactionHash, }, - }); + { + transaction: mockDbTransaction, + }, + ); }); }); }); diff --git a/tests/eventHandlers/StreamReceiverSeenEventHandler.test.ts b/tests/eventHandlers/StreamReceiverSeenEventHandler.test.ts index 49067a1..7bfd2ed 100644 --- a/tests/eventHandlers/StreamReceiverSeenEventHandler.test.ts +++ b/tests/eventHandlers/StreamReceiverSeenEventHandler.test.ts @@ -4,15 +4,15 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; import StreamReceiverSeenEventModel from '../../src/models/StreamReceiverSeenEventModel'; -import LogManager from '../../src/core/LogManager'; -import { toAccountId } from '../../src/utils/accountIdUtils'; +import ScopedLogger from '../../src/core/ScopedLogger'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; import { StreamReceiverSeenEventHandler } from '../../src/eventHandlers'; import { toBigIntString } from '../../src/utils/bigintUtils'; jest.mock('../../src/models/StreamReceiverSeenEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); +jest.mock('../../src/core/ScopedLogger'); describe('StreamReceiverSeenEventHandler', () => { let mockDbTransaction: {}; @@ -49,15 +49,14 @@ describe('StreamReceiverSeenEventHandler', () => { describe('_handle', () => { test('should create a new StreamReceiverSeenEventModel', async () => { // Arrange - StreamReceiverSeenEventModel.findOrCreate = jest.fn().mockResolvedValue([ + StreamReceiverSeenEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'StreamReceiverSeenTransactionHash', logIndex: 1, }, - true, ]); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); // Act await handler['_handle'](mockRequest); @@ -73,15 +72,9 @@ describe('StreamReceiverSeenEventHandler', () => { }, } = mockRequest; - expect(StreamReceiverSeenEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId: toAccountId(rawAccountId), + expect(StreamReceiverSeenEventModel.create).toHaveBeenCalledWith( + { + accountId: convertToAccountId(rawAccountId), receiversHash: rawReceiversHash, config: toBigIntString(rawConfig.toString()), logIndex, @@ -89,7 +82,10 @@ describe('StreamReceiverSeenEventHandler', () => { blockTimestamp, transactionHash, }, - }); + { + transaction: mockDbTransaction, + }, + ); }); }); }); diff --git a/tests/eventHandlers/StreamsSetEventHandler.test.ts b/tests/eventHandlers/StreamsSetEventHandler.test.ts index 12faf5c..8b9d6a8 100644 --- a/tests/eventHandlers/StreamsSetEventHandler.test.ts +++ b/tests/eventHandlers/StreamsSetEventHandler.test.ts @@ -4,15 +4,15 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; import StreamsSetEventModel from '../../src/models/StreamsSetEventModel'; -import LogManager from '../../src/core/LogManager'; -import { toAccountId } from '../../src/utils/accountIdUtils'; +import ScopedLogger from '../../src/core/ScopedLogger'; +import { convertToAccountId } from '../../src/utils/accountIdUtils'; import { StreamsSetEventHandler } from '../../src/eventHandlers'; import { toBigIntString } from '../../src/utils/bigintUtils'; jest.mock('../../src/models/StreamsSetEventModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/core/LogManager'); +jest.mock('../../src/core/ScopedLogger'); describe('StreamsSetEventHandler', () => { let mockDbTransaction: {}; @@ -52,7 +52,7 @@ describe('StreamsSetEventHandler', () => { describe('_handle', () => { test('should create a new StreamsSetEventModel', async () => { // Arrange - StreamsSetEventModel.findOrCreate = jest.fn().mockResolvedValue([ + StreamsSetEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'StreamsSetTransactionHash', logIndex: 1, @@ -60,7 +60,7 @@ describe('StreamsSetEventHandler', () => { true, ]); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); // Act await handler['_handle'](mockRequest); @@ -83,15 +83,9 @@ describe('StreamsSetEventHandler', () => { }, } = mockRequest; - expect(StreamsSetEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - accountId: toAccountId(rawAccountId), + expect(StreamsSetEventModel.create).toHaveBeenCalledWith( + { + accountId: convertToAccountId(rawAccountId), erc20: rawErc20, receiversHash: rawReceiversHash, streamsHistoryHash: rawStreamsHistoryHash, @@ -102,7 +96,10 @@ describe('StreamsSetEventHandler', () => { blockTimestamp, transactionHash, }, - }); + { + transaction: mockDbTransaction, + }, + ); }); }); }); diff --git a/tests/eventHandlers/TransferEventHandler.test.ts b/tests/eventHandlers/TransferEventHandler.test.ts index fa74fcd..6ed1688 100644 --- a/tests/eventHandlers/TransferEventHandler.test.ts +++ b/tests/eventHandlers/TransferEventHandler.test.ts @@ -4,19 +4,20 @@ import type EventHandlerRequest from '../../src/events/EventHandlerRequest'; import { TransferEventHandler } from '../../src/eventHandlers'; import { dbConnection } from '../../src/db/database'; import type { EventData } from '../../src/events/types'; -import { calcAccountId, toNftDriverId } from '../../src/utils/accountIdUtils'; -import { isLatestEvent } from '../../src/utils/eventUtils'; -import LogManager from '../../src/core/LogManager'; +import { convertToNftDriverId } from '../../src/utils/accountIdUtils'; +import ScopedLogger from '../../src/core/ScopedLogger'; import TransferEventModel from '../../src/models/TransferEventModel'; import DripListModel from '../../src/models/DripListModel'; +import * as contractClients from '../../src/core/contractClients'; jest.mock('../../src/models/TransferEventModel'); jest.mock('../../src/models/DripListModel'); jest.mock('../../src/db/database'); jest.mock('bee-queue'); -jest.mock('../../src/utils/eventUtils'); +jest.mock('../../src/events/eventHandlerUtils'); jest.mock('../../src/utils/accountIdUtils'); -jest.mock('../../src/core/LogManager'); +jest.mock('../../src/core/ScopedLogger'); +jest.mock('../../src/core/contractClients'); describe('TransferEventHandler', () => { let mockDbTransaction: {}; @@ -43,7 +44,9 @@ describe('TransferEventHandler', () => { } as EventData<'Transfer(address,address,uint256)'>, }; - mockDbTransaction = {}; + mockDbTransaction = { + LOCK: { UPDATE: jest.fn() }, + }; dbConnection.transaction = jest .fn() @@ -53,19 +56,22 @@ describe('TransferEventHandler', () => { describe('_handle', () => { test('should create a new TransferEventModel', async () => { // Arrange - TransferEventModel.findOrCreate = jest.fn().mockResolvedValue([ + TransferEventModel.create = jest.fn().mockResolvedValue([ { transactionHash: 'TransferEventTransactionHash', logIndex: 1, }, - true, ]); - DripListModel.findOrCreate = jest + DripListModel.findByPk = jest .fn() - .mockResolvedValue([{ save: jest.fn() }, true]); + .mockResolvedValue({ save: jest.fn(), lastProcessedVersion: '0' }); + + ScopedLogger.prototype.bufferCreation = jest.fn().mockReturnThis(); - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); + contractClients.nftDriverContract.ownerOf = jest + .fn() + .mockResolvedValue(mockRequest.event.args[1]) as any; // Act await handler['_handle'](mockRequest); @@ -81,15 +87,9 @@ describe('TransferEventHandler', () => { }, } = mockRequest; - expect(TransferEventModel.findOrCreate).toHaveBeenCalledWith({ - lock: true, - transaction: mockDbTransaction, - where: { - logIndex, - transactionHash, - }, - defaults: { - tokenId: toNftDriverId(tokenId), + expect(TransferEventModel.create).toHaveBeenCalledWith( + { + tokenId: convertToNftDriverId(tokenId), to, from, logIndex, @@ -97,97 +97,10 @@ describe('TransferEventHandler', () => { blockTimestamp, transactionHash, }, - }); - }); - - test('should create a new DripListModel when the token is representing a Drip List', async () => { - // Arrange - TransferEventModel.findOrCreate = jest.fn().mockResolvedValue([ { - transactionHash: 'TransferEventTransactionHash', - logIndex: 1, + transaction: mockDbTransaction, }, - true, - ]); - - (calcAccountId as jest.Mock).mockResolvedValue('ownerAccountId'); - - DripListModel.findOrCreate = jest - .fn() - .mockResolvedValue([{ save: jest.fn() }, true]); - - LogManager.prototype.appendFindOrCreateLog = jest.fn().mockReturnThis(); - - // Act - await handler['_handle'](mockRequest); - - // Assert - const { - event: { - args: [from, to, tokenId], - }, - } = mockRequest; - - expect(DripListModel.findOrCreate).toHaveBeenCalledWith({ - transaction: mockDbTransaction, - lock: true, - where: { - id: toNftDriverId(tokenId), - }, - defaults: { - id: toNftDriverId(tokenId), - creator: to, - isValid: true, - isVisible: false, - ownerAddress: to, - ownerAccountId: 'ownerAccountId', - previousOwnerAddress: from, - }, - }); - }); - - test('should update the DripListModel when the incoming event is the latest', async () => { - // Arrange - TransferEventModel.findOrCreate = jest.fn().mockResolvedValue([ - { - transactionHash: 'TransferEventTransactionHash', - logIndex: 1, - }, - true, - ]); - - (calcAccountId as jest.Mock).mockResolvedValue('ownerAccountId'); - - const mockDripList = { - ownerAddress: '', - previousOwnerAddress: '', - ownerAccountId: '', - save: jest.fn(), - }; - DripListModel.findOrCreate = jest - .fn() - .mockResolvedValue([mockDripList, false]); - - (isLatestEvent as jest.Mock).mockResolvedValue(true); - - LogManager.prototype.appendIsLatestEventLog = jest.fn().mockReturnThis(); - - // Act - await handler['_handle'](mockRequest); - - // Assert - const { - event: { - args: [from, to], - }, - } = mockRequest; - - expect(mockDripList.ownerAddress).toBe(to); - expect(mockDripList.previousOwnerAddress).toBe(from); - expect(mockDripList.ownerAccountId).toBe('ownerAccountId'); - expect(mockDripList.save).toHaveBeenCalledWith({ - transaction: mockDbTransaction, - }); + ); }); }); }); diff --git a/tsconfig.json b/tsconfig.json index 544d2fb..028c5be 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,109 +1,12 @@ { "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": "ES2020" /* 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. */ - // "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": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* 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. */ - // "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. */ - "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": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* 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 */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript 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. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "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. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* 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. */ - // "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. */ - // "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. */ + "target": "ES2020", + "module": "commonjs", + "resolveJsonModule": true, + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true } }