diff --git a/.github/workflows/chain-simulator-e2e-tests.yml b/.github/workflows/chain-simulator-e2e-tests.yml index b93ea059f..5ae37f9a6 100644 --- a/.github/workflows/chain-simulator-e2e-tests.yml +++ b/.github/workflows/chain-simulator-e2e-tests.yml @@ -4,7 +4,7 @@ on: push: branches: [main, development] pull_request: - branches: [main, development] + branches: [main, development, feat/*, feature/*] jobs: test-chainsimulator-e2e: @@ -15,6 +15,9 @@ jobs: steps: - uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.ref }} - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bda7f1a37..b3083a236 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,7 +7,7 @@ on: push: branches: [main, development] pull_request: - branches: [main, development] + branches: [main, development, feat/*, feature/*] jobs: build: diff --git a/.github/workflows/load-tests.yml b/.github/workflows/load-tests.yml index 50568016a..ddda4c046 100644 --- a/.github/workflows/load-tests.yml +++ b/.github/workflows/load-tests.yml @@ -2,7 +2,7 @@ name: Load Tests on: pull_request: - branches: [main, development] + branches: [main, development, feat/*, feature/*] jobs: test-base: diff --git a/.github/workflows/unit.tests.yml b/.github/workflows/unit.tests.yml index d53e29e0e..c2bf4f559 100644 --- a/.github/workflows/unit.tests.yml +++ b/.github/workflows/unit.tests.yml @@ -7,7 +7,7 @@ on: push: branches: [main, development] pull_request: - branches: [main, development] + branches: [main, development, feat/*, feature/*] jobs: build: diff --git a/config/config.devnet-old.yaml b/config/config.devnet-old.yaml index 8f61aac89..8a5023d16 100644 --- a/config/config.devnet-old.yaml +++ b/config/config.devnet-old.yaml @@ -24,6 +24,14 @@ flags: processNfts: true collectionPropertiesFromGateway: false features: + stateChanges: + enabled: false + port: 5675 + rabbitUrl: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' + queueName: 'api_state_accesses_queue-test' + deadLetterExchange: 'api_state_accesses_queue_dlx' + esdtEnabled: false eventsNotifier: enabled: false port: 5674 @@ -97,7 +105,8 @@ indexer: maxPagination: 10000 database: enabled: false - url: 'mongodb://127.0.0.1:27017/api?authSource=admin' + url: 'mongodb://root:secret@127.0.0.1:27017/api?authSource=admin' + tls: false type: 'mysql' host: 'localhost' port: 3306 @@ -129,3 +138,5 @@ inflation: nftProcess: parallelism: 1 maxRetries: 3 +pubSubListener: + enabled: true diff --git a/config/config.devnet.yaml b/config/config.devnet.yaml index 8d76292b7..04b87966c 100644 --- a/config/config.devnet.yaml +++ b/config/config.devnet.yaml @@ -26,6 +26,14 @@ features: maxSubscriptionsPerInstance: 10000 maxSubscriptionsPerClient: 10 broadcastIntervalMs: 6000 + stateChanges: + enabled: false + port: 5675 + rabbitUrl: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' + queueName: 'api_state_accesses_queue-test' + deadLetterExchange: 'api_state_accesses_queue_dlx' + esdtEnabled: false eventsNotifier: enabled: false port: 5674 @@ -37,7 +45,7 @@ features: hitsThreshold: 100 ttl: 12 transactionPool: - enabled: false + enabled: true transactionPoolWarmer: enabled: false cronExpression: '*/5 * * * * *' @@ -162,7 +170,8 @@ indexer: maxPagination: 10000 database: enabled: false - url: 'mongodb://127.0.0.1:27017/api?authSource=admin' + url: 'mongodb://root:secret@127.0.0.1:27017/api?authSource=admin' + tls: false type: 'mysql' host: 'localhost' port: 3306 @@ -204,3 +213,7 @@ compression: level: 6 threshold: 1024 chunkSize: 16384 + +pubSubListener: + enabled: true + \ No newline at end of file diff --git a/config/config.e2e-mocked.mainnet.yaml b/config/config.e2e-mocked.mainnet.yaml index f65f05065..2b9d32037 100644 --- a/config/config.e2e-mocked.mainnet.yaml +++ b/config/config.e2e-mocked.mainnet.yaml @@ -11,6 +11,14 @@ features: maxSubscriptionsPerInstance: 10000 maxSubscriptionsPerClient: 10 broadcastIntervalMs: 6000 + stateChanges: + enabled: false + port: 5675 + rabbitUrl: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' + queueName: 'api_state_accesses_queue-test' + deadLetterExchange: 'api_state_accesses_queue_dlx' + esdtEnabled: false dataApi: enabled: false serviceUrl: 'https://data-api.multiversx.com' @@ -47,7 +55,8 @@ urls: maiarId: 'https://id-api.multiversx.com' database: enabled: false - url: 'mongodb://127.0.0.1:27017/api?authSource=admin' + url: 'mongodb://root:secret@127.0.0.1:27017/api?authSource=admin' + tls: false host: 'localhost' port: 3306 username: 'root' @@ -86,3 +95,5 @@ test: transaction-action: mex: microServiceUrl: 'https://graph.xexchange.com/graphql' +pubSubListener: + enabled: true diff --git a/config/config.e2e.mainnet.yaml b/config/config.e2e.mainnet.yaml index 50da09bff..a2769eaea 100644 --- a/config/config.e2e.mainnet.yaml +++ b/config/config.e2e.mainnet.yaml @@ -26,6 +26,14 @@ features: maxSubscriptionsPerInstance: 10000 maxSubscriptionsPerClient: 10 broadcastIntervalMs: 6000 + stateChanges: + enabled: false + port: 5675 + rabbitUrl: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' + queueName: 'api_state_accesses_queue-test' + deadLetterExchange: 'api_state_accesses_queue_dlx' + esdtEnabled: false eventsNotifier: enabled: false port: 5674 @@ -163,7 +171,8 @@ indexer: maxPagination: 10000 database: enabled: false - url: 'mongodb://127.0.0.1:27017/api?authSource=admin' + url: 'mongodb://root:secret@127.0.0.1:27017/api?authSource=admin' + tls: false type: 'mysql' host: 'localhost' port: 3306 @@ -197,4 +206,6 @@ stakingV5Inflation: - 1262802 nftProcess: parallelism: 1 - maxRetries: 3 \ No newline at end of file + maxRetries: 3 +pubSubListener: + enabled: true diff --git a/config/config.mainnet.yaml b/config/config.mainnet.yaml index a90823e54..5423f8498 100644 --- a/config/config.mainnet.yaml +++ b/config/config.mainnet.yaml @@ -26,12 +26,19 @@ features: maxSubscriptionsPerInstance: 10000 maxSubscriptionsPerClient: 10 broadcastIntervalMs: 6000 + stateChanges: + enabled: false + port: 5675 + url: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' eventsNotifier: enabled: false port: 5674 - url: 'amqp://guest:guest@127.0.0.1:5672' - exchange: 'all_events' - queue: 'api-process-logs-and-events' + rabbitUrl: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' + queueName: 'api_state_accesses_queue-test' + deadLetterExchange: 'api_state_accesses_queue_dlx' + esdtEnabled: false guestCaching: enabled: false hitsThreshold: 100 @@ -166,7 +173,8 @@ indexer: maxPagination: 10000 database: enabled: false - url: 'mongodb://127.0.0.1:27017/api?authSource=admin' + url: 'mongodb://root:secret@127.0.0.1:27017/api?authSource=admin' + tls: false type: 'mysql' host: 'localhost' port: 3306 @@ -212,3 +220,5 @@ customUrlHeaders: - urlPattern: '' headers: x-custom-auth: '' +pubSubListener: + enabled: true diff --git a/config/config.testnet.yaml b/config/config.testnet.yaml index c897aa17b..253b76db3 100644 --- a/config/config.testnet.yaml +++ b/config/config.testnet.yaml @@ -26,6 +26,14 @@ features: maxSubscriptionsPerInstance: 10000 maxSubscriptionsPerClient: 10 broadcastIntervalMs: 6000 + stateChanges: + enabled: false + port: 5675 + rabbitUrl: 'amqp://guest:guest@127.0.0.1:5672' + exchange: 'state_accesses' + queueName: 'api_state_accesses_queue-test' + deadLetterExchange: 'api_state_accesses_queue_dlx' + esdtEnabled: false eventsNotifier: enabled: false port: 5674 @@ -162,7 +170,8 @@ urls: maiarId: 'https://testnet-id-api.multiversx.com' database: enabled: false - url: 'mongodb://127.0.0.1:27017/api?authSource=admin' + url: 'mongodb://root:secret@127.0.0.1:27017/api?authSource=admin' + tls: false type: 'mysql' host: 'localhost' port: 3306 @@ -207,3 +216,5 @@ compression: level: 6 threshold: 1024 chunkSize: 16384 +pubSubListener: + enabled: true diff --git a/package-lock.json b/package-lock.json index 74dba9da3..2f97a0536 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@nestjs/event-emitter": "^2.0.3", "@nestjs/graphql": "^12.0.11", "@nestjs/microservices": "10.2.4", + "@nestjs/mongoose": "^11.0.3", "@nestjs/platform-express": "10.4.19", "@nestjs/platform-socket.io": "^10.2.4", "@nestjs/schedule": "3.0.3", @@ -65,12 +66,13 @@ "node-object-hash": "^2.3.10", "pg": "^8.7.3", "prom-client": "^14.0.1", + "protobufjs": "^7.5.4", "redis": "^3.1.2", "reflect-metadata": "^0.1.13", "request-ip": "^3.3.0", "rimraf": "^5.0.0", "rxjs": "^7.1.0", - "sharp": "^0.34.2", + "sharp": "^0.34.4", "simple-git": "^3.16.0", "socket.io": "^4.8.1", "socket.io-client": "^4.8.1", @@ -89,6 +91,7 @@ "@nestjs/schematics": "10.0.2", "@nestjs/testing": "10.2.4", "@testing-library/jest-dom": "6.1.4", + "@types/amqplib": "^0.10.7", "@types/compression": "^1.8.1", "@types/cron": "^1.7.3", "@types/crypto-js": "^4.0.2", @@ -111,6 +114,7 @@ "eslint-plugin-prettier": "^4.0.0", "jest": "29.5.0", "prettier": "^2.5.1", + "protobufjs-cli": "^1.1.3", "run-script-os": "^1.1.6", "supertest": "^6.2.2", "ts-jest": "^29.0.5", @@ -122,9 +126,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.3.tgz", - "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", "dev": true, "license": "MIT" }, @@ -223,9 +227,9 @@ } }, "node_modules/@angular-devkit/schematics-cli/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "engines": { @@ -341,6 +345,7 @@ "version": "4.12.2", "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.12.2.tgz", "integrity": "sha512-jKRlf+sBMMdKYrjMoiWKne42Eb6paBfDOr08KJnUaeaiyWFj+/040FjVPQI7YGLfdwnYIsl1NUUqS2UdgezJDg==", + "deprecated": "Apollo Server v4 is deprecated and will transition to end-of-life on January 26, 2026. As long as you are already using a non-EOL version of Node.js, upgrading to v5 should take only a few minutes. See https://www.apollographql.com/docs/apollo-server/previous-versions for details.", "license": "MIT", "peer": true, "dependencies": { @@ -380,6 +385,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz", "integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==", + "deprecated": "@apollo/server-gateway-interface v1 is part of Apollo Server v4, which is deprecated and will transition to end-of-life on January 26, 2026. As long as you are already using a non-EOL version of Node.js, upgrading to v2 should take only a few minutes. See https://www.apollographql.com/docs/apollo-server/previous-versions for details.", "license": "MIT", "peer": true, "dependencies": { @@ -867,66 +873,66 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.840.0.tgz", - "integrity": "sha512-dRuo03EqGBbl9+PTogpwY9bYmGWIjn8nB82HN5Qj20otgjUvhLOdEkkip9mroYsrvqNoKbMedWdCudIcB/YY1w==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.879.0.tgz", + "integrity": "sha512-1bD2Do/OdCIzl72ncHKYamDhPijUErLYpuLvciyYD4Ywt4cVLHjWtVIqb22XOOHYYHE3NqHMd4uRhvXMlsBRoQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/credential-provider-node": "3.840.0", - "@aws-sdk/middleware-bucket-endpoint": "3.840.0", - "@aws-sdk/middleware-expect-continue": "3.840.0", - "@aws-sdk/middleware-flexible-checksums": "3.840.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-location-constraint": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-sdk-s3": "3.840.0", - "@aws-sdk/middleware-ssec": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/signature-v4-multi-region": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", - "@aws-sdk/xml-builder": "3.821.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/eventstream-serde-browser": "^4.0.4", - "@smithy/eventstream-serde-config-resolver": "^4.1.2", - "@smithy/eventstream-serde-node": "^4.0.4", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-blob-browser": "^4.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/hash-stream-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/md5-js": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/credential-provider-node": "3.879.0", + "@aws-sdk/middleware-bucket-endpoint": "3.873.0", + "@aws-sdk/middleware-expect-continue": "3.873.0", + "@aws-sdk/middleware-flexible-checksums": "3.879.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-location-constraint": "3.873.0", + "@aws-sdk/middleware-logger": "3.876.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-sdk-s3": "3.879.0", + "@aws-sdk/middleware-ssec": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.879.0", + "@aws-sdk/region-config-resolver": "3.873.0", + "@aws-sdk/signature-v4-multi-region": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/util-endpoints": "3.879.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.879.0", + "@aws-sdk/xml-builder": "3.873.0", + "@smithy/config-resolver": "^4.1.5", + "@smithy/core": "^3.9.0", + "@smithy/eventstream-serde-browser": "^4.0.5", + "@smithy/eventstream-serde-config-resolver": "^4.1.3", + "@smithy/eventstream-serde-node": "^4.0.5", + "@smithy/fetch-http-handler": "^5.1.1", + "@smithy/hash-blob-browser": "^4.0.5", + "@smithy/hash-node": "^4.0.5", + "@smithy/hash-stream-node": "^4.0.5", + "@smithy/invalid-dependency": "^4.0.5", + "@smithy/md5-js": "^4.0.5", + "@smithy/middleware-content-length": "^4.0.5", + "@smithy/middleware-endpoint": "^4.1.19", + "@smithy/middleware-retry": "^4.1.20", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/middleware-stack": "^4.0.5", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/node-http-handler": "^4.1.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/smithy-client": "^4.5.0", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", "@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.21", - "@smithy/util-defaults-mode-node": "^4.0.21", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-defaults-mode-browser": "^4.0.27", + "@smithy/util-defaults-mode-node": "^4.0.27", + "@smithy/util-endpoints": "^3.0.7", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-retry": "^4.0.7", + "@smithy/util-stream": "^4.2.4", "@smithy/util-utf8": "^4.0.0", - "@smithy/util-waiter": "^4.0.6", + "@smithy/util-waiter": "^4.0.7", "@types/uuid": "^9.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" @@ -936,47 +942,47 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.840.0.tgz", - "integrity": "sha512-3Zp+FWN2hhmKdpS0Ragi5V2ZPsZNScE3jlbgoJjzjI/roHZqO+e3/+XFN4TlM0DsPKYJNp+1TAjmhxN6rOnfYA==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.879.0.tgz", + "integrity": "sha512-+Pc3OYFpRYpKLKRreovPM63FPPud1/SF9vemwIJfz6KwsBCJdvg7vYD1xLSIp5DVZLeetgf4reCyAA5ImBfZuw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.876.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.879.0", + "@aws-sdk/region-config-resolver": "3.873.0", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/util-endpoints": "3.879.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.879.0", + "@smithy/config-resolver": "^4.1.5", + "@smithy/core": "^3.9.0", + "@smithy/fetch-http-handler": "^5.1.1", + "@smithy/hash-node": "^4.0.5", + "@smithy/invalid-dependency": "^4.0.5", + "@smithy/middleware-content-length": "^4.0.5", + "@smithy/middleware-endpoint": "^4.1.19", + "@smithy/middleware-retry": "^4.1.20", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/middleware-stack": "^4.0.5", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/node-http-handler": "^4.1.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/smithy-client": "^4.5.0", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", "@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.21", - "@smithy/util-defaults-mode-node": "^4.0.21", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", + "@smithy/util-defaults-mode-browser": "^4.0.27", + "@smithy/util-defaults-mode-node": "^4.0.27", + "@smithy/util-endpoints": "^3.0.7", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-retry": "^4.0.7", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -985,25 +991,25 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.840.0.tgz", - "integrity": "sha512-x3Zgb39tF1h2XpU+yA4OAAQlW6LVEfXNlSedSYJ7HGKXqA/E9h3rWQVpYfhXXVVsLdYXdNw5KBUkoAoruoZSZA==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.879.0.tgz", + "integrity": "sha512-AhNmLCrx980LsK+SfPXGh7YqTyZxsK0Qmy18mWmkfY0TSq7WLaSDB5zdQbgbnQCACCHy8DUYXbi4KsjlIhv3PA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@aws-sdk/xml-builder": "3.821.0", - "@smithy/core": "^3.6.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/xml-builder": "3.873.0", + "@smithy/core": "^3.9.0", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/property-provider": "^4.0.5", + "@smithy/protocol-http": "^5.1.3", + "@smithy/signature-v4": "^5.1.3", + "@smithy/smithy-client": "^4.5.0", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", + "@smithy/util-middleware": "^4.0.5", "@smithy/util-utf8": "^4.0.0", - "fast-xml-parser": "4.4.1", + "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, "engines": { @@ -1011,15 +1017,15 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.840.0.tgz", - "integrity": "sha512-EzF6VcJK7XvQ/G15AVEfJzN2mNXU8fcVpXo4bRyr1S6t2q5zx6UPH/XjDbn18xyUmOq01t+r8gG+TmHEVo18fA==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.879.0.tgz", + "integrity": "sha512-JgG7A8SSbr5IiCYL8kk39Y9chdSB5GPwBorDW8V8mr19G9L+qd6ohED4fAocoNFaDnYJ5wGAHhCfSJjzcsPBVQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1027,20 +1033,20 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.840.0.tgz", - "integrity": "sha512-wbnUiPGLVea6mXbUh04fu+VJmGkQvmToPeTYdHE8eRZq3NRDi3t3WltT+jArLBKD/4NppRpMjf2ju4coMCz91g==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.879.0.tgz", + "integrity": "sha512-2hM5ByLpyK+qORUexjtYyDZsgxVCCUiJQZRMGkNXFEGz6zTpbjfTIWoh3zRgWHEBiqyPIyfEy50eIF69WshcuA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/fetch-http-handler": "^5.1.1", + "@smithy/node-http-handler": "^4.1.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/protocol-http": "^5.1.3", + "@smithy/smithy-client": "^4.5.0", + "@smithy/types": "^4.3.2", + "@smithy/util-stream": "^4.2.4", "tslib": "^2.6.2" }, "engines": { @@ -1048,23 +1054,23 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.840.0.tgz", - "integrity": "sha512-7F290BsWydShHb+7InXd+IjJc3mlEIm9I0R57F/Pjl1xZB69MdkhVGCnuETWoBt4g53ktJd6NEjzm/iAhFXFmw==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.879.0.tgz", + "integrity": "sha512-07M8zfb73KmMBqVO5/V3Ea9kqDspMX0fO0kaI1bsjWI6ngnMye8jCE0/sIhmkVAI0aU709VA0g+Bzlopnw9EoQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/credential-provider-env": "3.840.0", - "@aws-sdk/credential-provider-http": "3.840.0", - "@aws-sdk/credential-provider-process": "3.840.0", - "@aws-sdk/credential-provider-sso": "3.840.0", - "@aws-sdk/credential-provider-web-identity": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/credential-provider-env": "3.879.0", + "@aws-sdk/credential-provider-http": "3.879.0", + "@aws-sdk/credential-provider-process": "3.879.0", + "@aws-sdk/credential-provider-sso": "3.879.0", + "@aws-sdk/credential-provider-web-identity": "3.879.0", + "@aws-sdk/nested-clients": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/credential-provider-imds": "^4.0.7", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1072,22 +1078,22 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.840.0.tgz", - "integrity": "sha512-KufP8JnxA31wxklLm63evUPSFApGcH8X86z3mv9SRbpCm5ycgWIGVCTXpTOdgq6rPZrwT9pftzv2/b4mV/9clg==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.879.0.tgz", + "integrity": "sha512-FYaAqJbnSTrVL2iZkNDj2hj5087yMv2RN2GA8DJhe7iOJjzhzRojrtlfpWeJg6IhK0sBKDH+YXbdeexCzUJvtA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.840.0", - "@aws-sdk/credential-provider-http": "3.840.0", - "@aws-sdk/credential-provider-ini": "3.840.0", - "@aws-sdk/credential-provider-process": "3.840.0", - "@aws-sdk/credential-provider-sso": "3.840.0", - "@aws-sdk/credential-provider-web-identity": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/credential-provider-env": "3.879.0", + "@aws-sdk/credential-provider-http": "3.879.0", + "@aws-sdk/credential-provider-ini": "3.879.0", + "@aws-sdk/credential-provider-process": "3.879.0", + "@aws-sdk/credential-provider-sso": "3.879.0", + "@aws-sdk/credential-provider-web-identity": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/credential-provider-imds": "^4.0.7", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1095,16 +1101,16 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.840.0.tgz", - "integrity": "sha512-HkDQWHy8tCI4A0Ps2NVtuVYMv9cB4y/IuD/TdOsqeRIAT12h8jDb98BwQPNLAImAOwOWzZJ8Cu0xtSpX7CQhMw==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.879.0.tgz", + "integrity": "sha512-7r360x1VyEt35Sm1JFOzww2WpnfJNBbvvnzoyLt7WRfK0S/AfsuWhu5ltJ80QvJ0R3AiSNbG+q/btG2IHhDYPQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1112,18 +1118,18 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.840.0.tgz", - "integrity": "sha512-2qgdtdd6R0Z1y0KL8gzzwFUGmhBHSUx4zy85L2XV1CXhpRNwV71SVWJqLDVV5RVWVf9mg50Pm3AWrUC0xb0pcA==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.879.0.tgz", + "integrity": "sha512-gd27B0NsgtKlaPNARj4IX7F7US5NuU691rGm0EUSkDsM7TctvJULighKoHzPxDQlrDbVI11PW4WtKS/Zg5zPlQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.840.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/token-providers": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/client-sso": "3.879.0", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/token-providers": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1131,16 +1137,16 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.840.0.tgz", - "integrity": "sha512-dpEeVXG8uNZSmVXReE4WP0lwoioX2gstk4RnUgrdUE3YaPq8A+hJiVAyc3h+cjDeIqfbsQbZm9qFetKC2LF9dQ==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.879.0.tgz", + "integrity": "sha512-Jy4uPFfGzHk1Mxy+/Wr43vuw9yXsE2yiF4e4598vc3aJfO0YtA2nSfbKD3PNKRORwXbeKqWPfph9SCKQpWoxEg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/nested-clients": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1148,16 +1154,16 @@ } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.840.0.tgz", - "integrity": "sha512-+gkQNtPwcSMmlwBHFd4saVVS11In6ID1HczNzpM3MXKXRBfSlbZJbCt6wN//AZ8HMklZEik4tcEOG0qa9UY8SQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.873.0.tgz", + "integrity": "sha512-b4bvr0QdADeTUs+lPc9Z48kXzbKHXQKgTvxx/jXDgSW9tv4KmYPO1gIj6Z9dcrBkRWQuUtSW3Tu2S5n6pe+zeg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/util-arn-parser": "3.873.0", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "@smithy/util-config-provider": "^4.0.0", "tslib": "^2.6.2" }, @@ -1166,14 +1172,14 @@ } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.840.0.tgz", - "integrity": "sha512-iJg2r6FKsKKvdiU4oCOuCf7Ro/YE0Q2BT/QyEZN3/Rt8Nr4SAZiQOlcBXOCpGvuIKOEAhvDOUnW3aDHL01PdVw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.873.0.tgz", + "integrity": "sha512-GIqoc8WgRcf/opBOZXFLmplJQKwOMjiOMmDz9gQkaJ8FiVJoAp8EGVmK2TOWZMQUYsavvHYsHaor5R2xwPoGVg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1181,22 +1187,22 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.840.0.tgz", - "integrity": "sha512-Kg/o2G6o72sdoRH0J+avdcf668gM1bp6O4VeEXpXwUj/urQnV5qiB2q1EYT110INHUKWOLXPND3sQAqh6sTqHw==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.879.0.tgz", + "integrity": "sha512-U1rcWToy2rlQPQLsx5h73uTC1XYo/JpnlJGCc3Iw7b1qrK8Mke4+rgMPKCfnXELD5TTazGrbT03frxH4Y1Ycvw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/types": "3.840.0", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/types": "3.862.0", "@smithy/is-array-buffer": "^4.0.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-stream": "^4.2.4", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1205,14 +1211,14 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz", - "integrity": "sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.873.0.tgz", + "integrity": "sha512-KZ/W1uruWtMOs7D5j3KquOxzCnV79KQW9MjJFZM/M0l6KI8J6V3718MXxFHsTjUE4fpdV6SeCNLV1lwGygsjJA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1220,13 +1226,13 @@ } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.840.0.tgz", - "integrity": "sha512-KVLD0u0YMF3aQkVF8bdyHAGWSUY6N1Du89htTLgqCcIhSxxAJ9qifrosVZ9jkAzqRW99hcufyt2LylcVU2yoKQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.873.0.tgz", + "integrity": "sha512-r+hIaORsW/8rq6wieDordXnA/eAu7xAPLue2InhoEX6ML7irP52BgiibHLpt9R0psiCzIHhju8qqKa4pJOrmiw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1234,13 +1240,13 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz", - "integrity": "sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA==", + "version": "3.876.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.876.0.tgz", + "integrity": "sha512-cpWJhOuMSyz9oV25Z/CMHCBTgafDCbv7fHR80nlRrPdPZ8ETNsahwRgltXP1QJJ8r3X/c1kwpOR7tc+RabVzNA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1248,14 +1254,14 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz", - "integrity": "sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.873.0.tgz", + "integrity": "sha512-OtgY8EXOzRdEWR//WfPkA/fXl0+WwE8hq0y9iw2caNyKPtca85dzrrZWnPqyBK/cpImosrpR1iKMYr41XshsCg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1263,23 +1269,23 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.840.0.tgz", - "integrity": "sha512-rOUji7CayWN3O09zvvgLzDVQe0HiJdZkxoTS6vzOS3WbbdT7joGdVtAJHtn+x776QT3hHzbKU5gnfhel0o6gQA==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.879.0.tgz", + "integrity": "sha512-ZTpLr2AbZcCsEzu18YCtB8Tp8tjAWHT0ccfwy3HiL6g9ncuSMW+7BVi1hDYmBidFwpPbnnIMtM0db3pDMR6/WA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-arn-parser": "3.804.0", - "@smithy/core": "^3.6.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/util-arn-parser": "3.873.0", + "@smithy/core": "^3.9.0", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/protocol-http": "^5.1.3", + "@smithy/signature-v4": "^5.1.3", + "@smithy/smithy-client": "^4.5.0", + "@smithy/types": "^4.3.2", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-stream": "^4.2.4", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1288,13 +1294,13 @@ } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.840.0.tgz", - "integrity": "sha512-CBZP9t1QbjDFGOrtnUEHL1oAvmnCUUm7p0aPNbIdSzNtH42TNKjPRN3TuEIJDGjkrqpL3MXyDSmNayDcw/XW7Q==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.873.0.tgz", + "integrity": "sha512-AF55J94BoiuzN7g3hahy0dXTVZahVi8XxRBLgzNp6yQf0KTng+hb/V9UQZVYY1GZaDczvvvnqC54RGe9OZZ9zQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1302,17 +1308,17 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.840.0.tgz", - "integrity": "sha512-hiiMf7BP5ZkAFAvWRcK67Mw/g55ar7OCrvrynC92hunx/xhMkrgSLM0EXIZ1oTn3uql9kH/qqGF0nqsK6K555A==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.879.0.tgz", + "integrity": "sha512-DDSV8228lQxeMAFKnigkd0fHzzn5aauZMYC3CSj6e5/qE7+9OwpkUcjHfb7HZ9KWG6L2/70aKZXHqiJ4xKhOZw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", - "@smithy/core": "^3.6.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/util-endpoints": "3.879.0", + "@smithy/core": "^3.9.0", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1320,47 +1326,47 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.840.0.tgz", - "integrity": "sha512-LXYYo9+n4hRqnRSIMXLBb+BLz+cEmjMtTudwK1BF6Bn2RfdDv29KuyeDRrPCS3TwKl7ZKmXUmE9n5UuHAPfBpA==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.879.0.tgz", + "integrity": "sha512-7+n9NpIz9QtKYnxmw1fHi9C8o0GrX8LbBR4D50c7bH6Iq5+XdSuL5AFOWWQ5cMD0JhqYYJhK/fJsVau3nUtC4g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.840.0", - "@aws-sdk/middleware-host-header": "3.840.0", - "@aws-sdk/middleware-logger": "3.840.0", - "@aws-sdk/middleware-recursion-detection": "3.840.0", - "@aws-sdk/middleware-user-agent": "3.840.0", - "@aws-sdk/region-config-resolver": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@aws-sdk/util-endpoints": "3.840.0", - "@aws-sdk/util-user-agent-browser": "3.840.0", - "@aws-sdk/util-user-agent-node": "3.840.0", - "@smithy/config-resolver": "^4.1.4", - "@smithy/core": "^3.6.0", - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/hash-node": "^4.0.4", - "@smithy/invalid-dependency": "^4.0.4", - "@smithy/middleware-content-length": "^4.0.4", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-retry": "^4.1.14", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/protocol-http": "^5.1.2", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.876.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.879.0", + "@aws-sdk/region-config-resolver": "3.873.0", + "@aws-sdk/types": "3.862.0", + "@aws-sdk/util-endpoints": "3.879.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.879.0", + "@smithy/config-resolver": "^4.1.5", + "@smithy/core": "^3.9.0", + "@smithy/fetch-http-handler": "^5.1.1", + "@smithy/hash-node": "^4.0.5", + "@smithy/invalid-dependency": "^4.0.5", + "@smithy/middleware-content-length": "^4.0.5", + "@smithy/middleware-endpoint": "^4.1.19", + "@smithy/middleware-retry": "^4.1.20", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/middleware-stack": "^4.0.5", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/node-http-handler": "^4.1.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/smithy-client": "^4.5.0", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", "@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.21", - "@smithy/util-defaults-mode-node": "^4.0.21", - "@smithy/util-endpoints": "^3.0.6", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", + "@smithy/util-defaults-mode-browser": "^4.0.27", + "@smithy/util-defaults-mode-node": "^4.0.27", + "@smithy/util-endpoints": "^3.0.7", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-retry": "^4.0.7", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -1369,16 +1375,16 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz", - "integrity": "sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.873.0.tgz", + "integrity": "sha512-q9sPoef+BBG6PJnc4x60vK/bfVwvRWsPgcoQyIra057S/QGjq5VkjvNk6H8xedf6vnKlXNBwq9BaANBXnldUJg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/types": "^4.3.2", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", + "@smithy/util-middleware": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -1386,16 +1392,16 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.840.0.tgz", - "integrity": "sha512-8AoVgHrkSfhvGPtwx23hIUO4MmMnux2pjnso1lrLZGqxfElM6jm2w4jTNLlNXk8uKHGyX89HaAIuT0lL6dJj9g==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.879.0.tgz", + "integrity": "sha512-MDsw0EWOHyKac75X3gD8tLWtmPuRliS/s4IhWRhsdDCU13wewHIs5IlA5B65kT6ISf49yEIalEH3FHUSVqdmIQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/signature-v4": "^5.1.2", - "@smithy/types": "^4.3.1", + "@aws-sdk/middleware-sdk-s3": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/protocol-http": "^5.1.3", + "@smithy/signature-v4": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1403,17 +1409,17 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.840.0.tgz", - "integrity": "sha512-6BuTOLTXvmgwjK7ve7aTg9JaWFdM5UoMolLVPMyh3wTv9Ufalh8oklxYHUBIxsKkBGO2WiHXytveuxH6tAgTYg==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.879.0.tgz", + "integrity": "sha512-47J7sCwXdnw9plRZNAGVkNEOlSiLb/kR2slnDIHRK9NB/ECKsoqgz5OZQJ9E2f0yqOs8zSNJjn3T01KxpgW8Qw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.840.0", - "@aws-sdk/nested-clients": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@aws-sdk/core": "3.879.0", + "@aws-sdk/nested-clients": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1421,12 +1427,12 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.840.0.tgz", - "integrity": "sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA==", + "version": "3.862.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.862.0.tgz", + "integrity": "sha512-Bei+RL0cDxxV+lW2UezLbCYYNeJm6Nzee0TpW0FfyTRBhH9C1XQh4+x+IClriXvgBnRquTMMYsmJfvx8iyLKrg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1434,9 +1440,9 @@ } }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.804.0.tgz", - "integrity": "sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.873.0.tgz", + "integrity": "sha512-qag+VTqnJWDn8zTAXX4wiVioa0hZDQMtbZcGRERVnLar4/3/VIKBhxX2XibNQXFu1ufgcRn4YntT/XEPecFWcg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -1446,14 +1452,15 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.840.0.tgz", - "integrity": "sha512-eqE9ROdg/Kk0rj3poutyRCFauPDXIf/WSvCqFiRDDVi6QOnCv/M0g2XW8/jSvkJlOyaXkNCptapIp6BeeFFGYw==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.879.0.tgz", + "integrity": "sha512-aVAJwGecYoEmbEFju3127TyJDF9qJsKDUUTRMDuS8tGn+QiWQFnfInmbt+el9GU1gEJupNTXV+E3e74y51fb7A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", - "@smithy/util-endpoints": "^3.0.6", + "@aws-sdk/types": "3.862.0", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", + "@smithy/util-endpoints": "^3.0.7", "tslib": "^2.6.2" }, "engines": { @@ -1461,9 +1468,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz", - "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.873.0.tgz", + "integrity": "sha512-xcVhZF6svjM5Rj89T1WzkjQmrTF6dpR2UvIHPMTnSZoNe6CixejPZ6f0JJ2kAhO8H+dUHwNBlsUgOTIKiK/Syg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -1473,27 +1480,27 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz", - "integrity": "sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.873.0.tgz", + "integrity": "sha512-AcRdbK6o19yehEcywI43blIBhOCSo6UgyWcuOJX5CFF8k39xm1ILCjQlRRjchLAxWrm0lU0Q7XV90RiMMFMZtA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.840.0", - "@smithy/types": "^4.3.1", + "@aws-sdk/types": "3.862.0", + "@smithy/types": "^4.3.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.840.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.840.0.tgz", - "integrity": "sha512-Fy5JUEDQU1tPm2Yw/YqRYYc27W5+QD/J4mYvQvdWjUGZLB5q3eLFMGD35Uc28ZFoGMufPr4OCxK/bRfWROBRHQ==", + "version": "3.879.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.879.0.tgz", + "integrity": "sha512-A5KGc1S+CJRzYnuxJQQmH1BtGsz46AgyHkqReKfGiNQA8ET/9y9LQ5t2ABqnSBHHIh3+MiCcQSkUZ0S3rTodrQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.840.0", - "@aws-sdk/types": "3.840.0", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", + "@aws-sdk/middleware-user-agent": "3.879.0", + "@aws-sdk/types": "3.862.0", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1509,12 +1516,12 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.821.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz", - "integrity": "sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.873.0.tgz", + "integrity": "sha512-kLO7k7cGJ6KaHiExSJWojZurF7SnGMDHXRuQunFnEoD0n1yB6Lqy/S/zHiQ7oJnBhPr9q0TW9qFkrsZb1Uc54w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -1537,9 +1544,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.7.tgz", - "integrity": "sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true, "license": "MIT", "engines": { @@ -1547,22 +1554,22 @@ } }, "node_modules/@babel/core": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", - "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", + "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.27.7", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.7", - "@babel/types": "^7.27.7", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1588,16 +1595,16 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", - "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -1641,6 +1648,16 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", @@ -1656,15 +1673,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -1714,27 +1731,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" + "@babel/types": "^7.28.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", - "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.7" + "@babel/types": "^7.28.2" }, "bin": { "parser": "bin/babel-parser.js" @@ -1983,9 +2000,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2007,38 +2024,28 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.7.tgz", - "integrity": "sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", - "@babel/parser": "^7.27.7", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", - "@babel/types": "^7.27.7", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/types": "^7.28.2", + "debug": "^4.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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", - "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2056,6 +2063,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@borewit/text-codec": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz", + "integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2194,9 +2211,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", "license": "MIT", "optional": true, "dependencies": { @@ -2204,9 +2221,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.8.0.tgz", + "integrity": "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2381,6 +2398,12 @@ "node": ">=10" } }, + "node_modules/@golevelup/nestjs-rabbitmq/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, "node_modules/@golevelup/nestjs-rabbitmq/node_modules/promise-breaker": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-5.0.0.tgz", @@ -2508,10 +2531,19 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.2.tgz", - "integrity": "sha512-OfXHZPppddivUJnqyKoi5YVeHRkkNE2zUFT2gbpKxp/JZCFYEYubnMg+gOp6lWfasPrTS+KPosKqdI+ELYVDtg==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", "cpu": [ "arm64" ], @@ -2527,13 +2559,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.1.0" + "@img/sharp-libvips-darwin-arm64": "1.2.3" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.2.tgz", - "integrity": "sha512-dYvWqmjU9VxqXmjEtjmvHnGqF8GrVjM2Epj9rJ6BUIXvk8slvNDJbhGFvIoXzkDhrJC2jUxNLz/GUjjvSzfw+g==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", "cpu": [ "x64" ], @@ -2549,13 +2581,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.1.0" + "@img/sharp-libvips-darwin-x64": "1.2.3" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", - "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", "cpu": [ "arm64" ], @@ -2569,9 +2601,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", - "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", "cpu": [ "x64" ], @@ -2585,9 +2617,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", - "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", "cpu": [ "arm" ], @@ -2601,9 +2633,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", - "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", "cpu": [ "arm64" ], @@ -2617,9 +2649,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", - "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", "cpu": [ "ppc64" ], @@ -2633,9 +2665,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", - "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", "cpu": [ "s390x" ], @@ -2649,9 +2681,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", - "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", "cpu": [ "x64" ], @@ -2665,9 +2697,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", - "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", "cpu": [ "arm64" ], @@ -2681,9 +2713,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", - "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", "cpu": [ "x64" ], @@ -2697,9 +2729,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.2.tgz", - "integrity": "sha512-0DZzkvuEOqQUP9mo2kjjKNok5AmnOr1jB2XYjkaoNRwpAYMDzRmAqUIa1nRi58S2WswqSfPOWLNOr0FDT3H5RQ==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", "cpu": [ "arm" ], @@ -2715,13 +2747,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.1.0" + "@img/sharp-libvips-linux-arm": "1.2.3" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.2.tgz", - "integrity": "sha512-D8n8wgWmPDakc83LORcfJepdOSN6MvWNzzz2ux0MnIbOqdieRZwVYY32zxVx+IFUT8er5KPcyU3XXsn+GzG/0Q==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", "cpu": [ "arm64" ], @@ -2737,13 +2769,35 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.1.0" + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.2.tgz", - "integrity": "sha512-EGZ1xwhBI7dNISwxjChqBGELCWMGDvmxZXKjQRuqMrakhO8QoMgqCrdjnAqJq/CScxfRn+Bb7suXBElKQpPDiw==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", "cpu": [ "s390x" ], @@ -2759,13 +2813,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.1.0" + "@img/sharp-libvips-linux-s390x": "1.2.3" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.2.tgz", - "integrity": "sha512-sD7J+h5nFLMMmOXYH4DD9UtSNBD05tWSSdWAcEyzqW8Cn5UxXvsHAxmxSesYUsTOBmUnjtxghKDl15EvfqLFbQ==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", "cpu": [ "x64" ], @@ -2781,13 +2835,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" + "@img/sharp-libvips-linux-x64": "1.2.3" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.2.tgz", - "integrity": "sha512-NEE2vQ6wcxYav1/A22OOxoSOGiKnNmDzCYFOZ949xFmrWZOVII1Bp3NqVVpvj+3UeHMFyN5eP/V5hzViQ5CZNA==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", "cpu": [ "arm64" ], @@ -2803,13 +2857,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.2.tgz", - "integrity": "sha512-DOYMrDm5E6/8bm/yQLCWyuDJwUnlevR8xtF8bs+gjZ7cyUNYXiSf/E8Kp0Ss5xasIaXSHzb888V1BE4i1hFhAA==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", "cpu": [ "x64" ], @@ -2825,20 +2879,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.1.0" + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.2.tgz", - "integrity": "sha512-/VI4mdlJ9zkaq53MbIG6rZY+QRN3MLbR6usYlgITEzi4Rpx5S6LFKsycOQjkOGmqTNmkIdLjEvooFKwww6OpdQ==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.4.3" + "@emnapi/runtime": "^1.5.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -2848,9 +2902,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.2.tgz", - "integrity": "sha512-cfP/r9FdS63VA5k0xiqaNaEoGxBg9k7uE+RQGzuK9fHt7jib4zAVVseR9LsE4gJcNWgT6APKMNnCcnyOtmSEUQ==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", "cpu": [ "arm64" ], @@ -2867,9 +2921,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.2.tgz", - "integrity": "sha512-QLjGGvAbj0X/FXl8n1WbtQ6iVBpWU7JO94u/P2M4a8CFYsvQi4GW2mRy/JqkRx0qpBzaOdKJKw8uc930EX2AHw==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", "cpu": [ "ia32" ], @@ -2886,9 +2940,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.2.tgz", - "integrity": "sha512-aUdT6zEYtDKCaxkofmmJDJYGCf0+pJg3eU9/oBuqvEeoB9dKI6ZLc/1iLJCTuJQDO4ptntAlkUmHgGjyuobZbw==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", "cpu": [ "x64" ], @@ -2905,9 +2959,9 @@ } }, "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.1.tgz", + "integrity": "sha512-bYtU8avhGIcje3IhvF9aSjsa5URMZBHnwKtOvXsT4sfYy9gppW11gLPT/9oNqlJZD47yPKveQFTAFWpHjKvUoQ==", "license": "MIT" }, "node_modules/@isaacs/cliui": { @@ -2928,9 +2982,9 @@ } }, "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==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "license": "MIT", "engines": { "node": ">=12" @@ -3453,9 +3507,9 @@ "license": "ISC" }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.11.tgz", - "integrity": "sha512-C512c1ytBTio4MrpWKlJpyFHT6+qfFL8SZ58zBzJ1OOzUEjHeF1BtjY2fH7n4x/g2OV/KiiMLAivOp1DXmiMMw==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { @@ -3474,9 +3528,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.9.tgz", - "integrity": "sha512-amBU75CKOOkcQLfyM6J+DnWwz41yTsWI7o8MQ003LwUIWb4NYX/evAblTx1oBBYJySqL/zHPxHXDw5ewpQaUFw==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { @@ -3485,16 +3539,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.3.tgz", - "integrity": "sha512-AiR5uKpFxP3PjO4R19kQGIMwxyRyPuXmKEEy301V1C0+1rVjS94EZQXf1QKZYN8Q0YM+estSPhmx5JwNftv6nw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.28", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.28.tgz", - "integrity": "sha512-KNNHHwW3EIp4EDYOvYFGyIFfx36R2dNJYH4knnZlF8T5jdbD5Wx8xmSaQ2gP9URkJ04LGEtlcCtwArKcmFcwKw==", + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3502,6 +3556,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", + "integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", @@ -3604,9 +3671,9 @@ } }, "node_modules/@multiversx/sdk-exchange": { - "version": "0.2.22", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-exchange/-/sdk-exchange-0.2.22.tgz", - "integrity": "sha512-mRo1U9Fj9S+O4BNGR4Gs9g9+T7hUw/cGoGe2rzqUsGLimfudaGWtHLlkV20Wm3GITVMe2zcFbDFewxkprnSjhg==", + "version": "0.2.23", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-exchange/-/sdk-exchange-0.2.23.tgz", + "integrity": "sha512-eGOA9CeRfsf3aKf4/NXbk8VeHJsWSm9wuaMfrF4cUPhWoqpA93QGlW/iTxpM4u4WkLeaNITkGI3NgRL9MNrDDA==", "license": "MIT", "dependencies": { "@multiversx/sdk-core": "^13.6.3", @@ -3649,9 +3716,9 @@ } }, "node_modules/@multiversx/sdk-nestjs-auth/node_modules/@multiversx/sdk-core": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-14.2.3.tgz", - "integrity": "sha512-h52YIJ3udMyQSNX1QaZKbm7YpwIFvRI78QEJTes0UoboAUt5Vx5bTc8kZt8Lrfks7FKHEPaUeMdLochUcQbQ4Q==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-14.2.9.tgz", + "integrity": "sha512-tssRDroQpYTLX7ZNQyVzb6Bai4N1Nz3mUuJCW7k0i179bGUKR/VFVa0RviAXkv+d3pUkP/NepxdUaVTyaj5jmg==", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -3670,7 +3737,7 @@ }, "optionalDependencies": { "@multiversx/sdk-bls-wasm": "0.3.5", - "axios": "^1.7.4", + "axios": "^1.10.0", "bip39": "3.1.0" }, "peerDependencies": { @@ -3679,16 +3746,16 @@ } }, "node_modules/@multiversx/sdk-nestjs-auth/node_modules/@multiversx/sdk-native-auth-server": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-native-auth-server/-/sdk-native-auth-server-2.0.0.tgz", - "integrity": "sha512-DdjWyt60Chk6unMVprBV/5zA8rEXjufYdE67UG6XP8RRZiGU1+k6UU14E0TU/iii8K+/5Tj/zfrIrPfbDiASoA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-native-auth-server/-/sdk-native-auth-server-2.1.0.tgz", + "integrity": "sha512-fbDHeYF2cJpRaGpz3Cqv3jfYhm/nf2jlxZzCmBEeetsuRai0eZvDImm4O58GJu3JBkR0iokWrS/zctSgX37sjg==", "license": "GPL-3.0-or-later", "dependencies": { "axios": "^1.7.4", "bech32": "^2.0.0" }, "peerDependencies": { - "@multiversx/sdk-core": "^14.x" + "@multiversx/sdk-core": "^15.x" } }, "node_modules/@multiversx/sdk-nestjs-auth/node_modules/@multiversx/sdk-native-auth-server/node_modules/bech32": { @@ -3764,9 +3831,9 @@ } }, "node_modules/@multiversx/sdk-nestjs-common/node_modules/@multiversx/sdk-core": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-14.2.3.tgz", - "integrity": "sha512-h52YIJ3udMyQSNX1QaZKbm7YpwIFvRI78QEJTes0UoboAUt5Vx5bTc8kZt8Lrfks7FKHEPaUeMdLochUcQbQ4Q==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-14.2.9.tgz", + "integrity": "sha512-tssRDroQpYTLX7ZNQyVzb6Bai4N1Nz3mUuJCW7k0i179bGUKR/VFVa0RviAXkv+d3pUkP/NepxdUaVTyaj5jmg==", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -3785,7 +3852,7 @@ }, "optionalDependencies": { "@multiversx/sdk-bls-wasm": "0.3.5", - "axios": "^1.7.4", + "axios": "^1.10.0", "bip39": "3.1.0" }, "peerDependencies": { @@ -3831,9 +3898,9 @@ } }, "node_modules/@multiversx/sdk-nestjs-http/node_modules/@multiversx/sdk-core": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-14.2.3.tgz", - "integrity": "sha512-h52YIJ3udMyQSNX1QaZKbm7YpwIFvRI78QEJTes0UoboAUt5Vx5bTc8kZt8Lrfks7FKHEPaUeMdLochUcQbQ4Q==", + "version": "14.2.9", + "resolved": "https://registry.npmjs.org/@multiversx/sdk-core/-/sdk-core-14.2.9.tgz", + "integrity": "sha512-tssRDroQpYTLX7ZNQyVzb6Bai4N1Nz3mUuJCW7k0i179bGUKR/VFVa0RviAXkv+d3pUkP/NepxdUaVTyaj5jmg==", "license": "MIT", "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", @@ -3852,7 +3919,7 @@ }, "optionalDependencies": { "@multiversx/sdk-bls-wasm": "0.3.5", - "axios": "^1.7.4", + "axios": "^1.10.0", "bip39": "3.1.0" }, "peerDependencies": { @@ -3950,6 +4017,12 @@ "node": ">=10" } }, + "node_modules/@multiversx/sdk-nestjs-rabbitmq/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, "node_modules/@multiversx/sdk-nestjs-rabbitmq/node_modules/promise-breaker": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-5.0.0.tgz", @@ -4166,9 +4239,9 @@ } }, "node_modules/@nestjs/common": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.19.tgz", - "integrity": "sha512-0TZJ8H+7qtaqZt6YfZJkDRp0e+v6jjo5/pevPAjUy0WYxaTy16bNNQxFPRKLMe/v1hUr2oGV9imvL2477zNt5g==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.20.tgz", + "integrity": "sha512-hxJxZF7jcKGuUzM9EYbuES80Z/36piJbiqmPy86mk8qOn5gglFebBTvcx7PWVbRNSb4gngASYnefBj/Y2HAzpQ==", "license": "MIT", "dependencies": { "file-type": "20.4.1", @@ -4500,6 +4573,18 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "license": "0BSD" }, + "node_modules/@nestjs/mongoose": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-11.0.3.tgz", + "integrity": "sha512-tg7bbKD4MnNMPaiDLXK/JUyTNQxIn3rNnI+oYU1HorLpNiR2E8vPraWVvfptpIj+zferpT6LkrHMvtqvuIKNPw==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0", + "mongoose": "^7.0.0 || ^8.0.0", + "rxjs": "^7.0.0" + } + }, "node_modules/@nestjs/platform-express": { "version": "10.4.19", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.19.tgz", @@ -4522,9 +4607,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.19.tgz", - "integrity": "sha512-Pfz9dBcXaoUFdVpA/I96NoOTiTQ7eYfDNhQ2sZdQzne3oISEvts5G2SWyQNouoyjqkUPt6X5r/CQ++M4AzSlEQ==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.20.tgz", + "integrity": "sha512-8wqJ7kJnvRC6T1o1U3NNnuzjaMJU43R4hvzKKba7GSdMN6j2Jfzz/vq5gHDx9xbXOAmfsc9bvaIiZegXxvHoJA==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -4771,9 +4856,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.19.tgz", - "integrity": "sha512-3HhNZU40/ozB64ZZJ1W1bOOYSbxGuJwmM5Ui8y1uPwbzpL1Uov3wOG3eRp1IflSBK4Ia0wb8Iv3ChpFSTzrNiA==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.20.tgz", + "integrity": "sha512-tafsPPvQfAXc+cfxvuRDzS5V+Ixg8uVJq8xSocU24yVl/Xp6ajmhqiGiaVjYOX8mXY0NV836QwEZxHF7WvKHSw==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -5053,12 +5138,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", - "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.5.tgz", + "integrity": "sha512-jcrqdTQurIrBbUm4W2YdLVMQDoL0sA9DTxYd2s+R/y+2U9NLOP7Xf/YqfSg1FZhlZIYEnvk2mwbyvIfdLEPo8g==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5091,15 +5176,15 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", - "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.5.tgz", + "integrity": "sha512-viuHMxBAqydkB0AfWwHIdwf/PRH2z5KHGUzqyRtS/Wv+n3IHI993Sk76VCA7dD/+GzgGOmlJDITfPcJC1nIVIw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/types": "^4.3.2", "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", + "@smithy/util-middleware": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -5107,35 +5192,37 @@ } }, "node_modules/@smithy/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.6.0.tgz", - "integrity": "sha512-Pgvfb+TQ4wUNLyHzvgCP4aYZMh16y7GcfF59oirRHcgGgkH1e/s9C0nv/v3WP+Quymyr5je71HeFQCwh+44XLg==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.9.2.tgz", + "integrity": "sha512-H7H+dnfyHa/XXmZB3+IcqB1snIvbXaeGbV7//PMY69YKMOfGtuHPg6aukxsD0TyqmIU+bcX5nitR+nf/19nTlQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.0.8", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-stream": "^4.2.2", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-stream": "^4.2.4", "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", - "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.7.tgz", + "integrity": "sha512-dDzrMXA8d8riFNiPvytxn0mNwR4B3h8lgrQ5UjAGu6T9z/kRg/Xncf4tEQHE/+t25sY8IH3CowcmWi+1U5B1Gw==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/property-provider": "^4.0.5", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -5143,13 +5230,13 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz", - "integrity": "sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.5.tgz", + "integrity": "sha512-miEUN+nz2UTNoRYRhRqVTJCx7jMeILdAurStT2XoS+mhokkmz1xAPp95DFW9Gxt4iF2VBqpeF9HbTQ3kY1viOA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-hex-encoding": "^4.0.0", "tslib": "^2.6.2" }, @@ -5158,13 +5245,13 @@ } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.4.tgz", - "integrity": "sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.5.tgz", + "integrity": "sha512-LCUQUVTbM6HFKzImYlSB9w4xafZmpdmZsOh9rIl7riPC3osCgGFVP+wwvYVw6pXda9PPT9TcEZxaq3XE81EdJQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/eventstream-serde-universal": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5172,12 +5259,12 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.2.tgz", - "integrity": "sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.3.tgz", + "integrity": "sha512-yTTzw2jZjn/MbHu1pURbHdpjGbCuMHWncNBpJnQAPxOVnFUAbSIUSwafiphVDjNV93TdBJWmeVAds7yl5QCkcA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5185,13 +5272,13 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.4.tgz", - "integrity": "sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.5.tgz", + "integrity": "sha512-lGS10urI4CNzz6YlTe5EYG0YOpsSp3ra8MXyco4aqSkQDuyZPIw2hcaxDU82OUVtK7UY9hrSvgWtpsW5D4rb4g==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/eventstream-serde-universal": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5199,13 +5286,13 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.4.tgz", - "integrity": "sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.5.tgz", + "integrity": "sha512-JFnmu4SU36YYw3DIBVao3FsJh4Uw65vVDIqlWT4LzR6gXA0F3KP0IXFKKJrhaVzCBhAuMsrUUaT5I+/4ZhF7aw==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/eventstream-codec": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5213,14 +5300,14 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.4.tgz", - "integrity": "sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.1.tgz", + "integrity": "sha512-61WjM0PWmZJR+SnmzaKI7t7G0UkkNFboDpzIdzSoy7TByUzlxo18Qlh9s71qug4AY4hlH/CwXdubMtkcNEb/sQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/querystring-builder": "^4.0.5", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "tslib": "^2.6.2" }, @@ -5229,14 +5316,14 @@ } }, "node_modules/@smithy/hash-blob-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.4.tgz", - "integrity": "sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.5.tgz", + "integrity": "sha512-F7MmCd3FH/Q2edhcKd+qulWkwfChHbc9nhguBlVjSUE6hVHhec3q6uPQ+0u69S6ppvLtR3eStfCuEKMXBXhvvA==", "license": "Apache-2.0", "dependencies": { "@smithy/chunked-blob-reader": "^5.0.0", "@smithy/chunked-blob-reader-native": "^4.0.0", - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5244,12 +5331,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", - "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.5.tgz", + "integrity": "sha512-cv1HHkKhpyRb6ahD8Vcfb2Hgz67vNIXEp2vnhzfxLFGRukLCNEA5QdsorbUEzXma1Rco0u3rx5VTqbM06GcZqQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -5259,12 +5346,12 @@ } }, "node_modules/@smithy/hash-stream-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.4.tgz", - "integrity": "sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.5.tgz", + "integrity": "sha512-IJuDS3+VfWB67UC0GU0uYBG/TA30w+PlOaSo0GPm9UHS88A6rCP6uZxNjNYiyRtOcjv7TXn/60cW8ox1yuZsLg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -5273,12 +5360,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", - "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.5.tgz", + "integrity": "sha512-IVnb78Qtf7EJpoEVo7qJ8BEXQwgC4n3igeJNNKEj/MLYtapnx8A67Zt/J3RXAj2xSO1910zk0LdFiygSemuLow==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5298,12 +5385,12 @@ } }, "node_modules/@smithy/md5-js": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.4.tgz", - "integrity": "sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.5.tgz", + "integrity": "sha512-8n2XCwdUbGr8W/XhMTaxILkVlw2QebkVTn5tm3HOcbPbOpWg89zr6dPXsH8xbeTsbTXlJvlJNTQsKAIoqQGbdA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" }, @@ -5312,13 +5399,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", - "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.5.tgz", + "integrity": "sha512-l1jlNZoYzoCC7p0zCtBDE5OBXZ95yMKlRlftooE5jPWQn4YBPLgsp+oeHp7iMHaTGoUdFqmHOPa8c9G3gBsRpQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5326,18 +5413,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.13.tgz", - "integrity": "sha512-xg3EHV/Q5ZdAO5b0UiIMj3RIOCobuS40pBBODguUDVdko6YK6QIzCVRrHTogVuEKglBWqWenRnZ71iZnLL3ZAQ==", + "version": "4.1.21", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.21.tgz", + "integrity": "sha512-VCFE6LGSbnXs6uxLTdtar6dbkOHa9mrj692pZJx1mQVEzk0gvckAX9WB9BzlONUpv92QBWGezROz/+yEitQjAQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.6.0", - "@smithy/middleware-serde": "^4.0.8", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", - "@smithy/url-parser": "^4.0.4", - "@smithy/util-middleware": "^4.0.4", + "@smithy/core": "^3.9.2", + "@smithy/middleware-serde": "^4.0.9", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", + "@smithy/url-parser": "^4.0.5", + "@smithy/util-middleware": "^4.0.5", "tslib": "^2.6.2" }, "engines": { @@ -5345,18 +5432,19 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.14.tgz", - "integrity": "sha512-eoXaLlDGpKvdmvt+YBfRXE7HmIEtFF+DJCbTPwuLunP0YUnrydl+C4tS+vEM0+nyxXrX3PSUFqC+lP1+EHB1Tw==", + "version": "4.1.22", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.22.tgz", + "integrity": "sha512-mb6/wn4ixnSJCkKVLs51AKAyknbSTvwrHCM7cqgwGfYQ7/J6Qvv+49cBHe6Rl8Q0m3fROVYcSvM6bBiQtuhYWg==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/protocol-http": "^5.1.2", - "@smithy/service-error-classification": "^4.0.6", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", - "@smithy/util-middleware": "^4.0.4", - "@smithy/util-retry": "^4.0.6", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/protocol-http": "^5.1.3", + "@smithy/service-error-classification": "^4.0.7", + "@smithy/smithy-client": "^4.5.2", + "@smithy/types": "^4.3.2", + "@smithy/util-middleware": "^4.0.5", + "@smithy/util-retry": "^4.0.7", + "@types/uuid": "^9.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" }, @@ -5365,13 +5453,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", - "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.9.tgz", + "integrity": "sha512-uAFFR4dpeoJPGz8x9mhxp+RPjo5wW0QEEIPPPbLXiRRWeCATf/Km3gKIVR5vaP8bN1kgsPhcEeh+IZvUlBv6Xg==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5379,12 +5467,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", - "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.5.tgz", + "integrity": "sha512-/yoHDXZPh3ocRVyeWQFvC44u8seu3eYzZRveCMfgMOBcNKnAmOvjbL9+Cp5XKSIi9iYA9PECUuW2teDAk8T+OQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5392,14 +5480,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", - "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.4.tgz", + "integrity": "sha512-+UDQV/k42jLEPPHSn39l0Bmc4sB1xtdI9Gd47fzo/0PbXzJ7ylgaOByVjF5EeQIumkepnrJyfx86dPa9p47Y+w==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/shared-ini-file-loader": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/shared-ini-file-loader": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5407,15 +5495,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.6.tgz", - "integrity": "sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.1.tgz", + "integrity": "sha512-RHnlHqFpoVdjSPPiYy/t40Zovf3BBHc2oemgD7VsVTFFZrU5erFFe0n52OANZZ/5sbshgD93sOh5r6I35Xmpaw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/querystring-builder": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/abort-controller": "^4.0.5", + "@smithy/protocol-http": "^5.1.3", + "@smithy/querystring-builder": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5423,12 +5511,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", - "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.5.tgz", + "integrity": "sha512-R/bswf59T/n9ZgfgUICAZoWYKBHcsVDurAGX88zsiUtOTA/xUAPyiT+qkNCPwFn43pZqN84M4MiUsbSGQmgFIQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5436,12 +5524,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", - "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.3.tgz", + "integrity": "sha512-fCJd2ZR7D22XhDY0l+92pUag/7je2BztPRQ01gU5bMChcyI0rlly7QFibnYHzcxDvccMjlpM/Q1ev8ceRIb48w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5449,12 +5537,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", - "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.5.tgz", + "integrity": "sha512-NJeSCU57piZ56c+/wY+AbAw6rxCCAOZLCIniRE7wqvndqxcKKDOXzwWjrY7wGKEISfhL9gBbAaWWgHsUGedk+A==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" }, @@ -5463,12 +5551,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", - "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.5.tgz", + "integrity": "sha512-6SV7md2CzNG/WUeTjVe6Dj8noH32r4MnUeFKZrnVYsQxpGSIcphAanQMayi8jJLZAWm6pdM9ZXvKCpWOsIGg0w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5476,24 +5564,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz", - "integrity": "sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.7.tgz", + "integrity": "sha512-XvRHOipqpwNhEjDf2L5gJowZEm5nsxC16pAZOeEcsygdjv9A2jdOh3YoDQvOXBGTsaJk6mNWtzWalOB9976Wlg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1" + "@smithy/types": "^4.3.2" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", - "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.5.tgz", + "integrity": "sha512-YVVwehRDuehgoXdEL4r1tAAzdaDgaC9EQvhK0lEbfnbrd0bd5+CTQumbdPryX3J2shT7ZqQE+jPW4lmNBAB8JQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5501,16 +5589,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", - "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.3.tgz", + "integrity": "sha512-mARDSXSEgllNzMw6N+mC+r1AQlEBO3meEAkR/UlfAgnMzJUB3goRBWgip1EAMG99wh36MDqzo86SfIX5Y+VEaw==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.4", + "@smithy/util-middleware": "^4.0.5", "@smithy/util-uri-escape": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" @@ -5520,17 +5608,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.5.tgz", - "integrity": "sha512-+lynZjGuUFJaMdDYSTMnP/uPBBXXukVfrJlP+1U/Dp5SFTEI++w6NMga8DjOENxecOF71V9Z2DllaVDYRnGlkg==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.5.2.tgz", + "integrity": "sha512-WRdTJ7aNSJY0WuGpxrvVgRaFKGiuvtXX1Txhnu2BdynraSlH2bcP75riQ4SiQfawU1HNEKaPI5gf/ePm+Ro/Cw==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.6.0", - "@smithy/middleware-endpoint": "^4.1.13", - "@smithy/middleware-stack": "^4.0.4", - "@smithy/protocol-http": "^5.1.2", - "@smithy/types": "^4.3.1", - "@smithy/util-stream": "^4.2.2", + "@smithy/core": "^3.9.2", + "@smithy/middleware-endpoint": "^4.1.21", + "@smithy/middleware-stack": "^4.0.5", + "@smithy/protocol-http": "^5.1.3", + "@smithy/types": "^4.3.2", + "@smithy/util-stream": "^4.2.4", "tslib": "^2.6.2" }, "engines": { @@ -5538,9 +5626,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", - "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.2.tgz", + "integrity": "sha512-QO4zghLxiQ5W9UZmX2Lo0nta2PuE1sSrXUYDoaB6HMR762C0P7v/HEPHf6ZdglTVssJG1bsrSBxdc3quvDSihw==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -5550,13 +5638,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", - "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.5.tgz", + "integrity": "sha512-j+733Um7f1/DXjYhCbvNXABV53NyCRRA54C7bNEIxNPs0YjfRxeMKjjgm2jvTYrciZyCjsicHwQ6Q0ylo+NAUw==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/querystring-parser": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5627,14 +5715,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.21.tgz", - "integrity": "sha512-wM0jhTytgXu3wzJoIqpbBAG5U6BwiubZ6QKzSbP7/VbmF1v96xlAbX2Am/mz0Zep0NLvLh84JT0tuZnk3wmYQA==", + "version": "4.0.29", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.29.tgz", + "integrity": "sha512-awrIb21sWml3OMRhqf8e5GPLuZAcH3PRAHXVOPof/rBOKLxc6N01ZRs25154Ww6Ygm9oNP6G0tVvhcy8ktYXtw==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", + "@smithy/property-provider": "^4.0.5", + "@smithy/smithy-client": "^4.5.2", + "@smithy/types": "^4.3.2", "bowser": "^2.11.0", "tslib": "^2.6.2" }, @@ -5643,17 +5731,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.21.tgz", - "integrity": "sha512-/F34zkoU0GzpUgLJydHY8Rxu9lBn8xQC/s/0M0U9lLBkYbA1htaAFjWYJzpzsbXPuri5D1H8gjp2jBum05qBrA==", + "version": "4.0.29", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.29.tgz", + "integrity": "sha512-DxBWCC059GwOQXc5nxVudhdGQLZHTDhU4rkK4rvaBQn8IWBw8G+3H2hWk897LaNv6zwwhh7kpfqF0rJ77DvlSg==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.1.4", - "@smithy/credential-provider-imds": "^4.0.6", - "@smithy/node-config-provider": "^4.1.3", - "@smithy/property-provider": "^4.0.4", - "@smithy/smithy-client": "^4.4.5", - "@smithy/types": "^4.3.1", + "@smithy/config-resolver": "^4.1.5", + "@smithy/credential-provider-imds": "^4.0.7", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/property-provider": "^4.0.5", + "@smithy/smithy-client": "^4.5.2", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5661,13 +5749,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", - "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.7.tgz", + "integrity": "sha512-klGBP+RpBp6V5JbrY2C/VKnHXn3d5V2YrifZbmMY8os7M6m8wdYFoO6w/fe5VkP+YVwrEktW3IWYaSQVNZJ8oQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.1.3", - "@smithy/types": "^4.3.1", + "@smithy/node-config-provider": "^4.1.4", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5687,12 +5775,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", - "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.5.tgz", + "integrity": "sha512-N40PfqsZHRSsByGB81HhSo+uvMxEHT+9e255S53pfBw/wI6WKDI7Jw9oyu5tJTLwZzV5DsMha3ji8jk9dsHmQQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.3.1", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5700,13 +5788,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz", - "integrity": "sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.7.tgz", + "integrity": "sha512-TTO6rt0ppK70alZpkjwy+3nQlTiqNfoXja+qwuAchIEAIoSZW8Qyd76dvBv3I5bCpE38APafG23Y/u270NspiQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.0.6", - "@smithy/types": "^4.3.1", + "@smithy/service-error-classification": "^4.0.7", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5714,14 +5802,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.2.tgz", - "integrity": "sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.4.tgz", + "integrity": "sha512-vSKnvNZX2BXzl0U2RgCLOwWaAP9x/ddd/XobPK02pCbzRm5s55M53uwb1rl/Ts7RXZvdJZerPkA+en2FDghLuQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.0.4", - "@smithy/node-http-handler": "^4.0.6", - "@smithy/types": "^4.3.1", + "@smithy/fetch-http-handler": "^5.1.1", + "@smithy/node-http-handler": "^4.1.1", + "@smithy/types": "^4.3.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-hex-encoding": "^4.0.0", @@ -5758,13 +5846,13 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.6.tgz", - "integrity": "sha512-slcr1wdRbX7NFphXZOxtxRNA7hXAAtJAXJDE/wdoMAos27SIquVCKiSqfB6/28YzQ8FCsB5NKkhdM5gMADbqxg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.7.tgz", + "integrity": "sha512-mYqtQXPmrwvUljaHyGxYUIIRI3qjBTEb/f5QFi3A6VlxhpmZd5mWXn9W+qUkf2pVE1Hv3SqxefiZOPGdxmO64A==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.0.4", - "@smithy/types": "^4.3.1", + "@smithy/abort-controller": "^4.0.5", + "@smithy/types": "^4.3.2", "tslib": "^2.6.2" }, "engines": { @@ -5900,6 +5988,16 @@ "@types/node": "*" } }, + "node_modules/@types/amqplib": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.7.tgz", + "integrity": "sha512-IVj3avf9AQd2nXCx0PGk/OYq7VmHiyNxWFSb5HhU9ATh+i+gHWvVcljFTcTWQ/dyHJCTrzCixde+r/asL2ErDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -5936,13 +6034,13 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.20.7" + "@babel/types": "^7.28.2" } }, "node_modules/@types/body-parser": { @@ -6154,10 +6252,17 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-NYqRyg/hIQrYPT9lbOeYc3kIRabJDn/k4qQHIXUpx88CBDww2fD15Sg5kbXlW86zm2XEW4g0QxkTI3/Kfkc7xQ==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", "license": "MIT" }, "node_modules/@types/long": { @@ -6166,6 +6271,24 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT" }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/methods": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", @@ -6186,14 +6309,14 @@ "license": "MIT" }, "node_modules/@types/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "license": "MIT", "peer": true, "dependencies": { "@types/node": "*", - "form-data": "^4.0.0" + "form-data": "^4.0.4" } }, "node_modules/@types/qs": { @@ -6229,9 +6352,9 @@ } }, "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "dev": true, "license": "MIT" }, @@ -6316,9 +6439,9 @@ "license": "MIT" }, "node_modules/@types/validator": { - "version": "13.15.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", - "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", + "version": "13.15.3", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.3.tgz", + "integrity": "sha512-7bcUmDyS6PN3EuD9SlGGOxM77F8WLVsrwkxyWxKnxzmXoequ6c7741QBrANq6htVRGOITJ7z72mTP6Z4XyuG+Q==", "license": "MIT" }, "node_modules/@types/webidl-conversions": { @@ -6774,6 +6897,19 @@ "acorn": "^8" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -6874,9 +7010,9 @@ } }, "node_modules/amqplib": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.8.tgz", - "integrity": "sha512-Tfn1O9sFgAP8DqeMEpt2IacsVTENBpblB3SqLdn0jK2AeX8iyCvbptBc8lyATT9bQ31MsjVwUSQ1g8f4jHOUfw==", + "version": "0.10.9", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.9.tgz", + "integrity": "sha512-jwSftI4QjS3mizvnSnOrPGYiUnm1vI2OP1iXeOUz5pb74Ua0nbf6nPyyTzuiCLEE3fMpaJORXh2K/TQ08H5xGA==", "license": "MIT", "dependencies": { "buffer-more-ints": "~1.0.0", @@ -7553,13 +7689,13 @@ } }, "node_modules/axios": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", - "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -7646,9 +7782,9 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", "dev": true, "license": "MIT", "dependencies": { @@ -7669,7 +7805,7 @@ "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "node_modules/babel-preset-jest": { @@ -7737,9 +7873,9 @@ "license": "MIT" }, "node_modules/bignumber.js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", - "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "license": "MIT", "engines": { "node": "*" @@ -7911,9 +8047,9 @@ "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==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", "license": "MIT" }, "node_modules/brace-expansion": { @@ -7940,9 +8076,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", + "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", "dev": true, "funding": [ { @@ -7960,8 +8096,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", + "caniuse-lite": "^1.0.30001737", + "electron-to-chromium": "^1.5.211", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -8134,9 +8270,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "version": "1.0.30001739", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz", + "integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==", "dev": true, "funding": [ { @@ -8154,6 +8290,19 @@ ], "license": "CC-BY-4.0" }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8410,19 +8559,6 @@ "dev": true, "license": "MIT" }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8548,16 +8684,16 @@ } }, "node_modules/compression": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", - "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -8849,9 +8985,9 @@ "license": "MIT" }, "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "version": "1.11.18", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz", + "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==", "license": "MIT" }, "node_modules/dc-polyfill": { @@ -9041,9 +9177,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -9247,26 +9383,10 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/electron-to-chromium": { - "version": "1.5.178", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.178.tgz", - "integrity": "sha512-wObbz/ar3Bc6e4X5vf0iO8xTN8YAjN/tgiAOJLr7yjYFtP9wAjq8Mb5h0yn6kResir+VYx2DXBj9NNobs0ETSA==", + "version": "1.5.213", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.213.tgz", + "integrity": "sha512-xr9eRzSLNa4neDO0xVFrkXu3vyIzG4Ay08dApecw42Z1NbmCt+keEpXdvlYGVe0wtvY5dhW0Ay0lY0IOfsCg0Q==", "dev": true, "license": "ISC" }, @@ -9432,9 +9552,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, "license": "MIT", "dependencies": { @@ -9445,6 +9565,19 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -9587,37 +9720,125 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "esprima": "^4.0.1", + "estraverse": "^4.2.0", "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", @@ -9645,9 +9866,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", - "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz", + "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", "dev": true, "license": "MIT", "bin": { @@ -9658,9 +9879,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.5.tgz", + "integrity": "sha512-9Ni+xgemM2IWLq6aXEpP2+V/V30GeA/46Ar629vcMqVPodFFWC9skHu/D1phvuqtS8bJCFnNf01/qcmqYEwNfg==", "dev": true, "license": "MIT", "dependencies": { @@ -10140,22 +10361,18 @@ "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==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", "dependencies": { - "strnum": "^1.0.5" + "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" @@ -10258,39 +10475,6 @@ "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -10447,9 +10631,9 @@ "license": "MIT" }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -10527,9 +10711,9 @@ } }, "node_modules/form-data": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", - "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -10592,9 +10776,9 @@ } }, "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", + "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", "dev": true, "license": "Unlicense" }, @@ -10873,14 +11057,15 @@ } }, "node_modules/graphql-request/node_modules/form-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz", - "integrity": "sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.35" }, "engines": { @@ -10926,6 +11111,38 @@ "graphql": ">=0.11 <=16" } }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -11214,12 +11431,12 @@ } }, "node_modules/ioredis": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz", - "integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.7.0.tgz", + "integrity": "sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==", "license": "MIT", "dependencies": { - "@ioredis/commands": "^1.1.1", + "@ioredis/commands": "^1.3.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", @@ -11416,9 +11633,9 @@ } }, "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "license": "MIT" }, "node_modules/isexe": { @@ -11494,9 +11711,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -11537,32 +11754,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, "node_modules/jest": { "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", @@ -12221,6 +12412,69 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", + "integrity": "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -12309,9 +12563,9 @@ "license": "MIT" }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -12364,6 +12618,16 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keccak": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", @@ -12406,6 +12670,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -12456,9 +12730,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.12.13", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.13.tgz", - "integrity": "sha512-QZXnR/OGiDcBjF4hGk0wwVrPcZvbSSyzlvkjXv5LFfktj7O2VZDrt4Xs8SgR/vOFco+qk1i8J43ikMXZoTrtPw==", + "version": "1.12.15", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.15.tgz", + "integrity": "sha512-TMDCtIhWUDHh91wRC+wFuGlIzKdPzaTUHHVrIZ3vPUEoNaXFLrsIQ1ZpAeZeXApIF6rvDksMTvjrIQlLKaYxqQ==", "license": "MIT" }, "node_modules/limiter": { @@ -12473,6 +12747,16 @@ "dev": true, "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -12696,9 +12980,9 @@ } }, "node_modules/luxon": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.1.tgz", - "integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.1.tgz", + "integrity": "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==", "license": "MIT", "engines": { "node": ">=12" @@ -12750,6 +13034,48 @@ "tmpl": "1.0.5" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "license": "Unlicense", + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -12770,6 +13096,13 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -12997,9 +13330,9 @@ } }, "node_modules/mongodb": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz", - "integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.19.0.tgz", + "integrity": "sha512-H3GtYujOJdeKIMLKBT9PwlDhGrQfplABNF1G904w6r5ZXKWyv77aB0X9B+rhmaAwjtllHzaEkvi9mkGVZxs2Bw==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.1.9", @@ -13015,7 +13348,7 @@ "gcp-metadata": "^5.2.0", "kerberos": "^2.0.1", "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", + "snappy": "^7.3.2", "socks": "^2.7.1" }, "peerDependenciesMeta": { @@ -13052,6 +13385,99 @@ "whatwg-url": "^14.1.0 || ^13.0.0" } }, + "node_modules/mongoose": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.18.0.tgz", + "integrity": "sha512-3TixPihQKBdyaYDeJqRjzgb86KbilEH07JmzV8SoSjgoskNTpa6oTBmDxeoF9p8YnWQoz7shnCyPkSV/48y3yw==", + "license": "MIT", + "peer": true, + "dependencies": { + "bson": "^6.10.4", + "kareem": "2.6.3", + "mongodb": "~6.18.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz", + "integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.4", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -13093,15 +13519,15 @@ } }, "node_modules/mysql2": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz", - "integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==", + "version": "3.14.4", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.4.tgz", + "integrity": "sha512-Cs/jx3WZPNrYHVz+Iunp9ziahaG5uFMvD2R8Zlmc194AqXNxt9HBNu7ZsPYrUtmJsF0egETCWIdMIYAwOGjL1w==", "license": "MIT", "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "long": "^5.2.1", "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", @@ -13113,15 +13539,19 @@ } }, "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/mysql2/node_modules/long": { @@ -13366,9 +13796,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -13927,9 +14357,9 @@ } }, "node_modules/pprof-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pprof-format/-/pprof-format-2.1.0.tgz", - "integrity": "sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/pprof-format/-/pprof-format-2.2.1.tgz", + "integrity": "sha512-p4tVN7iK19ccDqQv8heyobzUmbHyds4N2FI6aBMcXz6y99MglTWDxIyhFkNaLeEXs6IFUEzT0zya0icbSLLY0g==", "license": "MIT" }, "node_modules/prelude-ls": { @@ -14038,9 +14468,9 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz", - "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -14061,6 +14491,99 @@ "node": ">=12.0.0" } }, + "node_modules/protobufjs-cli": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/protobufjs-cli/-/protobufjs-cli-1.1.3.tgz", + "integrity": "sha512-MqD10lqF+FMsOayFiNOdOGNlXc4iKDCf0ZQPkPR+gizYh9gqUeGTWulABUCdI+N67w5RfJ6xhgX4J8pa8qmMXQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "chalk": "^4.0.0", + "escodegen": "^1.13.0", + "espree": "^9.0.0", + "estraverse": "^5.1.0", + "glob": "^8.0.0", + "jsdoc": "^4.0.0", + "minimist": "^1.2.0", + "semver": "^7.1.2", + "tmp": "^0.2.1", + "uglify-js": "^3.7.7" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "protobufjs": "^7.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/protobufjs-cli/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/protobufjs-cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/protobufjs-cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protobufjs-cli/node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/protobufjs/node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -14095,6 +14618,16 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -14355,6 +14888,16 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "license": "MIT" }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -14757,27 +15300,34 @@ "license": "ISC" }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/sharp": { - "version": "0.34.2", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.2.tgz", - "integrity": "sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==", + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", + "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.4", + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.0", "semver": "^7.7.2" }, "engines": { @@ -14787,27 +15337,28 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.2", - "@img/sharp-darwin-x64": "0.34.2", - "@img/sharp-libvips-darwin-arm64": "1.1.0", - "@img/sharp-libvips-darwin-x64": "1.1.0", - "@img/sharp-libvips-linux-arm": "1.1.0", - "@img/sharp-libvips-linux-arm64": "1.1.0", - "@img/sharp-libvips-linux-ppc64": "1.1.0", - "@img/sharp-libvips-linux-s390x": "1.1.0", - "@img/sharp-libvips-linux-x64": "1.1.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", - "@img/sharp-libvips-linuxmusl-x64": "1.1.0", - "@img/sharp-linux-arm": "0.34.2", - "@img/sharp-linux-arm64": "0.34.2", - "@img/sharp-linux-s390x": "0.34.2", - "@img/sharp-linux-x64": "0.34.2", - "@img/sharp-linuxmusl-arm64": "0.34.2", - "@img/sharp-linuxmusl-x64": "0.34.2", - "@img/sharp-wasm32": "0.34.2", - "@img/sharp-win32-arm64": "0.34.2", - "@img/sharp-win32-ia32": "0.34.2", - "@img/sharp-win32-x64": "0.34.2" + "@img/sharp-darwin-arm64": "0.34.4", + "@img/sharp-darwin-x64": "0.34.4", + "@img/sharp-libvips-darwin-arm64": "1.2.3", + "@img/sharp-libvips-darwin-x64": "1.2.3", + "@img/sharp-libvips-linux-arm": "1.2.3", + "@img/sharp-libvips-linux-arm64": "1.2.3", + "@img/sharp-libvips-linux-ppc64": "1.2.3", + "@img/sharp-libvips-linux-s390x": "1.2.3", + "@img/sharp-libvips-linux-x64": "1.2.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", + "@img/sharp-libvips-linuxmusl-x64": "1.2.3", + "@img/sharp-linux-arm": "0.34.4", + "@img/sharp-linux-arm64": "0.34.4", + "@img/sharp-linux-ppc64": "0.34.4", + "@img/sharp-linux-s390x": "0.34.4", + "@img/sharp-linux-x64": "0.34.4", + "@img/sharp-linuxmusl-arm64": "0.34.4", + "@img/sharp-linuxmusl-x64": "0.34.4", + "@img/sharp-wasm32": "0.34.4", + "@img/sharp-win32-arm64": "0.34.4", + "@img/sharp-win32-ia32": "0.34.4", + "@img/sharp-win32-x64": "0.34.4" } }, "node_modules/shebang-command": { @@ -14915,6 +15466,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT", + "peer": true + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -15378,9 +15936,9 @@ } }, "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", "funding": [ { "type": "github", @@ -15390,9 +15948,9 @@ "license": "MIT" }, "node_modules/strtok3": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.1.tgz", - "integrity": "sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw==", + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", "license": "MIT", "dependencies": { "@tokenizer/token": "^0.3.0" @@ -15456,7 +16014,7 @@ "version": "8.1.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", - "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", + "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", "dev": true, "license": "MIT", "dependencies": { @@ -15492,6 +16050,7 @@ "version": "6.3.4", "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", + "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net", "dev": true, "license": "MIT", "dependencies": { @@ -15559,13 +16118,17 @@ } }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tdigest": { @@ -15578,14 +16141,14 @@ } }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", + "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -15838,12 +16401,6 @@ "node": ">= 0.4" } }, - "node_modules/to-buffer/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15866,11 +16423,12 @@ } }, "node_modules/token-types": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.3.tgz", - "integrity": "sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", + "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", "license": "MIT", "dependencies": { + "@borewit/text-codec": "^0.1.0", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" }, @@ -15920,15 +16478,15 @@ } }, "node_modules/ts-jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz", - "integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==", + "version": "29.4.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.1.tgz", + "integrity": "sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==", "dev": true, "license": "MIT", "dependencies": { "bs-logger": "^0.2.6", - "ejs": "^3.1.10", "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", @@ -16210,9 +16768,9 @@ "license": "MIT" }, "node_modules/typeorm": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.25.tgz", - "integrity": "sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg==", + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.26.tgz", + "integrity": "sha512-o2RrBNn3lczx1qv4j+JliVMmtkPSqEGpG0UuZkt9tCfWkoXKu8MZnjvp2GjWPll1SehwemQw6xrbVRhmOglj8Q==", "license": "MIT", "dependencies": { "@sqltools/formatter": "^1.2.5", @@ -16243,9 +16801,8 @@ }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", - "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", - "hdb-pool": "^0.1.6", + "@sap/hana-client": "^2.14.22", + "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", @@ -16254,7 +16811,7 @@ "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", - "redis": "^3.1.1 || ^4.0.0", + "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", @@ -16271,9 +16828,6 @@ "better-sqlite3": { "optional": true }, - "hdb-pool": { - "optional": true - }, "ioredis": { "optional": true }, @@ -16354,6 +16908,26 @@ "node": ">=4.2.0" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/uid": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", @@ -16367,9 +16941,9 @@ } }, "node_modules/uint8array-extras": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", - "integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", "license": "MIT", "engines": { "node": ">=18" @@ -16378,6 +16952,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true, + "license": "MIT" + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -16569,22 +17150,23 @@ } }, "node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.101.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", + "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.17.3", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -16598,7 +17180,7 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -16890,6 +17472,12 @@ } } }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "node_modules/xmlhttprequest-ssl": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", diff --git a/package.json b/package.json index dbd1c1ecd..3de61989f 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "@nestjs/event-emitter": "^2.0.3", "@nestjs/graphql": "^12.0.11", "@nestjs/microservices": "10.2.4", + "@nestjs/mongoose": "^11.0.3", "@nestjs/platform-express": "10.4.19", "@nestjs/platform-socket.io": "^10.2.4", "@nestjs/schedule": "3.0.3", @@ -140,12 +141,13 @@ "node-object-hash": "^2.3.10", "pg": "^8.7.3", "prom-client": "^14.0.1", + "protobufjs": "^7.5.4", "redis": "^3.1.2", "reflect-metadata": "^0.1.13", "request-ip": "^3.3.0", "rimraf": "^5.0.0", "rxjs": "^7.1.0", - "sharp": "^0.34.2", + "sharp": "^0.34.4", "simple-git": "^3.16.0", "socket.io": "^4.8.1", "socket.io-client": "^4.8.1", @@ -164,6 +166,7 @@ "@nestjs/schematics": "10.0.2", "@nestjs/testing": "10.2.4", "@testing-library/jest-dom": "6.1.4", + "@types/amqplib": "^0.10.7", "@types/compression": "^1.8.1", "@types/cron": "^1.7.3", "@types/crypto-js": "^4.0.2", @@ -186,6 +189,7 @@ "eslint-plugin-prettier": "^4.0.0", "jest": "29.5.0", "prettier": "^2.5.1", + "protobufjs-cli": "^1.1.3", "run-script-os": "^1.1.6", "supertest": "^6.2.2", "ts-jest": "^29.0.5", diff --git a/src/common/api-config/api.config.service.ts b/src/common/api-config/api.config.service.ts index 6496eafbd..8237e7414 100644 --- a/src/common/api-config/api.config.service.ts +++ b/src/common/api-config/api.config.service.ts @@ -484,6 +484,10 @@ export class ApiConfigService { return databaseUrl; } + isDatabaseTlsEnabled(): boolean { + return this.configService.get('database.tls') ?? false; + } + getDatabaseConnection(): any { return { host: this.getDatabaseHost(), @@ -1104,4 +1108,69 @@ export class ApiConfigService { return timestamp; } + + isStateChangesFeatureActive(): boolean { + return this.configService.get('features.stateChanges.enabled') ?? false; + } + + getStateChangesFeaturePort(): number { + const stateChangesPort = this.configService.get('features.stateChanges.port'); + if (stateChangesPort === undefined) { + throw new Error('No state changes port present'); + } + + return stateChangesPort; + } + + getStateChangesRabbitUrl(): string { + let url = this.configService.get('features.stateChanges.rabbitUrl'); + if (!url) { + url = this.configService.get('features.stateChanges.url'); + if (!url) { + throw new Error('No state changes rabbit url present'); + } + } + + return url; + } + + getStateChangesExchange(): string { + const exchange = this.configService.get('features.stateChanges.exchange'); + if (!exchange) { + throw new Error('No state changes exchange present'); + } + + return exchange; + } + + getStateChangesQueueName(): string { + const queueName = this.configService.get('features.stateChanges.queueName'); + if (!queueName) { + throw new Error('No state changes queue name present'); + } + + return queueName; + } + + isEsdtComputationEnabled(): boolean { + return this.configService.get('features.stateChanges.esdtEnabled') ?? false; + } + + getStateChangesDeadLetterExchange(): string { + const deadLetterExchange = this.configService.get('features.stateChanges.deadLetterExchange'); + if (!deadLetterExchange) { + throw new Error('No state changes dead letter exchange present'); + } + + return deadLetterExchange; + } + + isPubSubListenerEnabled(): boolean { + const isPubSubListenerEnabled = this.configService.get('pubSubListener.enabled'); + if (isPubSubListenerEnabled == null) { + return true; + } + + return isPubSubListenerEnabled; + } } diff --git a/src/common/indexer/db/index.ts b/src/common/indexer/db/index.ts new file mode 100644 index 000000000..37a3a8bd0 --- /dev/null +++ b/src/common/indexer/db/index.ts @@ -0,0 +1,4 @@ +export * from './mongodb.module'; +export * from './repositories'; +export * from './schemas'; +export * from './utils'; diff --git a/src/common/indexer/db/mongodb.module.ts b/src/common/indexer/db/mongodb.module.ts new file mode 100644 index 000000000..4524742fe --- /dev/null +++ b/src/common/indexer/db/mongodb.module.ts @@ -0,0 +1,67 @@ +import { Module, Provider } from "@nestjs/common"; +import { MongooseModule } from "@nestjs/mongoose"; +import { ApiConfigModule } from "src/common/api-config/api.config.module"; +import { ApiConfigService } from "src/common/api-config/api.config.service"; +import { AccountDetails, AccountDetailsSchema, EsdtDetails, EsdtDetailsSchema } from "./schemas"; +import { AccountDetailsRepository, EsdtDetailsRepository } from "./repositories"; +import { EventEmitterModule } from "@nestjs/event-emitter"; +import configuration from "config/configuration"; + +const isPassThrough = + process.env.PERSISTENCE === 'passthrough' || + configuration()?.database?.enabled === false; + +const mongoImports = []; + +if (!isPassThrough) { + mongoImports.push( + EventEmitterModule.forRoot({ maxListeners: 1 }), + MongooseModule.forRootAsync({ + imports: [ApiConfigModule], + inject: [ApiConfigService], + useFactory: (apiConfigService: ApiConfigService) => ({ + uri: apiConfigService.getDatabaseUrl().replace(":27017", ''), + tls: apiConfigService.isDatabaseTlsEnabled(), + tlsAllowInvalidCertificates: true, + }), + }), + MongooseModule.forFeature([ + { name: AccountDetails.name, schema: AccountDetailsSchema }, + { name: EsdtDetails.name, schema: EsdtDetailsSchema }, + ]) + ); +} + +const mongoProviders: Provider[] = []; + +if (isPassThrough) { + mongoProviders.push( + { + provide: AccountDetailsRepository, + useValue: { + getAccount: () => Promise.resolve(null), + updateAccount: () => Promise.resolve(null), + updateAccounts: () => Promise.resolve([]), + }, + }, + { + provide: EsdtDetailsRepository, + useValue: { + getEsdt: () => Promise.resolve(null), + updateEsdts: () => Promise.resolve([]), + }, + }, + ); +} else { + mongoProviders.push( + { provide: AccountDetailsRepository, useClass: AccountDetailsRepository }, + { provide: EsdtDetailsRepository, useClass: EsdtDetailsRepository }, + ); +} + +@Module({ + imports: mongoImports, + providers: mongoProviders, + exports: mongoProviders, +}) +export class MongoDbModule { } diff --git a/src/common/indexer/db/repositories/account.details.repository.ts b/src/common/indexer/db/repositories/account.details.repository.ts new file mode 100644 index 000000000..b36b5b90e --- /dev/null +++ b/src/common/indexer/db/repositories/account.details.repository.ts @@ -0,0 +1,122 @@ +import { Model } from 'mongoose'; +import { LogPerformanceAsync } from 'src/utils/log.performance.decorator'; +import { MetricsEvents } from 'src/utils/metrics-events.constants'; +import { AccountDetails } from '../schemas'; +import { InjectModel } from '@nestjs/mongoose'; +import { Injectable } from '@nestjs/common'; +import { AccountDetailed } from 'src/endpoints/accounts/entities/account.detailed'; +import { OriginLogger } from '@multiversx/sdk-nestjs-common'; + +@Injectable() +export class AccountDetailsRepository { + private readonly logger = new OriginLogger(AccountDetailsRepository.name); + constructor( + @InjectModel(AccountDetails.name) + private readonly accountDetailsModel: Model + ) { } + + @LogPerformanceAsync(MetricsEvents.SetPersistenceDuration, 'account-details') + async getAccount(address: string): Promise { + try { + const accountDb = await this.accountDetailsModel.findOne( + { address }, + { _id: 0, __v: 0, tokens: 0, nfts: 0, updatedAt: 0, createdAt: 0, code: 0 } + ).lean(); + if (!accountDb) { + return null; + } + return new AccountDetailed({ ...accountDb, nonce: accountDb.nonce }); + } catch (error) { + console.error('Error fetching account:', error); + return null; + } + } + + @LogPerformanceAsync(MetricsEvents.SetPersistenceDuration, 'account-details') + async updateAccount(accountDetailed: AccountDetails): Promise { + try { + // Create update object with all fields from accountDetailed + const updateFields: Partial = {}; + + // Helper function to check if a value is valid for update + const isValidValue = (value: any): boolean => { + return value !== undefined && value !== null; + }; + + // Build update object with all valid fields from accountDetailed + Object.entries(accountDetailed).forEach(([key, value]) => { + if (isValidValue(value)) { + updateFields[key as keyof AccountDetails] = value; + } + }); + // Use findOneAndUpdate with upsert option + const updatedAccount = await this.accountDetailsModel.findOneAndUpdate( + { address: accountDetailed.address }, + { $set: updateFields }, + { + new: true, // Return the updated document + upsert: true, // Create if doesn't exist + lean: true, // Return plain JavaScript object + projection: { __v: 0, __id: 0, updatedAt: 0 }, // Exclude __v field + } + ); + return updatedAccount; + } catch (error: any) { + // Handle potential duplicate key errors + if (error.code !== 11000) { + throw error; + } + return null; + } + } + + @LogPerformanceAsync(MetricsEvents.SetPersistenceDuration, 'account-details') + async updateAccounts(accounts: AccountDetails[]): Promise { + try { + if (!accounts.length) return []; + let totalOperations = 0; + + const operations: any[] = []; + + for (const accountDetailed of accounts) { + const updatePipeline: any[] = []; + + // --- helper --- + const isValidValue = (value: any): boolean => + value != null; + + // --- simple fields --- + const updateFields: any = {}; + Object.entries(accountDetailed).forEach(([key, value]) => { + if (isValidValue(value)) { + updateFields[key as keyof AccountDetails] = value; + } + + }); + if (Object.keys(updateFields).length > 0) { + updatePipeline.push({ $set: updateFields }); + } + if (updatePipeline.length > 0) { + operations.push({ + updateOne: { + filter: { address: accountDetailed.address }, + update: updatePipeline, // <<--- pipeline array + upsert: true, + }, + }); + totalOperations++; + } + } + + this.logger.log(`number of accounts write operations: ${totalOperations}`); + const result = await this.accountDetailsModel.bulkWrite(operations, { + ordered: true, + }); + + return result; + } catch (error: any) { + console.error('Error updating accounts:', error); + throw error; + } + } +} diff --git a/src/common/indexer/db/repositories/esdt.details.repository.ts b/src/common/indexer/db/repositories/esdt.details.repository.ts new file mode 100644 index 000000000..248c4c934 --- /dev/null +++ b/src/common/indexer/db/repositories/esdt.details.repository.ts @@ -0,0 +1,102 @@ +import { Model } from 'mongoose'; +import { LogPerformanceAsync } from 'src/utils/log.performance.decorator'; +import { MetricsEvents } from 'src/utils/metrics-events.constants'; +import { InjectModel } from '@nestjs/mongoose'; +import { Injectable } from '@nestjs/common'; +import { OriginLogger } from '@multiversx/sdk-nestjs-common'; +import { EsdtDetails } from '../schemas/esdt.details.schema'; + +@Injectable() +export class EsdtDetailsRepository { + private readonly logger = new OriginLogger(EsdtDetailsRepository.name); + constructor( + @InjectModel(EsdtDetails.name) + private readonly esdtDetailsModel: Model + ) { } + + @LogPerformanceAsync(MetricsEvents.SetPersistenceDuration, 'esdt-details') + async getEsdt(address: string, identifier: string): Promise { + try { + const esdtDb = await this.esdtDetailsModel.findOne( + { address, identifier }, + { _id: 0, __v: 0, tokens: 0, nfts: 0, updatedAt: 0, createdAt: 0, code: 0 } + ).lean(); + if (!esdtDb) { + return null; + } + return new EsdtDetails({ ...esdtDb }); + } catch (error) { + console.error('Error fetching esdt:', error); + return null; + } + } + + + @LogPerformanceAsync(MetricsEvents.SetPersistenceDuration, 'esdt-details') + async updateEsdts(esdts: EsdtDetails[]): Promise { + try { + if (!esdts.length) return []; + let totalOperations = 0; + + const operations: any[] = []; + + for (const esdtDetailed of esdts) { + if (esdtDetailed.balance === '0') { + operations.push({ + deleteOne: { + filter: { + address: esdtDetailed.address, + identifier: esdtDetailed.identifier, + }, + }, + }); + + totalOperations++; + continue; + } + + const updatePipeline: any[] = []; + + const isValidValue = (value: any): boolean => + value != null; + + const updateFields: any = {}; + Object.entries(esdtDetailed).forEach(([key, value]) => { + if (isValidValue(value)) { + updateFields[key as keyof EsdtDetails] = value; + } + }); + + if (Object.keys(updateFields).length > 0) { + updatePipeline.push({ $set: updateFields }); + } + + if (updatePipeline.length > 0) { + operations.push({ + updateOne: { + filter: { + address: esdtDetailed.address, + identifier: esdtDetailed.identifier, + }, + update: updatePipeline, + upsert: true, + }, + }); + totalOperations++; + } + } + + this.logger.log(`number of esdts write operations: ${totalOperations}`); + + const result = await this.esdtDetailsModel.bulkWrite(operations, { + ordered: true, + }); + + return result; + } catch (error: any) { + console.error('Error updating esdts:', error); + throw error; + } + } + +} diff --git a/src/common/indexer/db/repositories/index.ts b/src/common/indexer/db/repositories/index.ts new file mode 100644 index 000000000..6740a9e4e --- /dev/null +++ b/src/common/indexer/db/repositories/index.ts @@ -0,0 +1,2 @@ +export * from './account.details.repository'; +export * from './esdt.details.repository'; diff --git a/src/common/indexer/db/schemas/account.details.schema.ts b/src/common/indexer/db/schemas/account.details.schema.ts new file mode 100644 index 000000000..4b5bf43ae --- /dev/null +++ b/src/common/indexer/db/schemas/account.details.schema.ts @@ -0,0 +1,121 @@ +import { Prop, SchemaFactory, Schema } from '@nestjs/mongoose'; +import mongoose, { HydratedDocument } from 'mongoose'; +import { AccountAssets } from 'src/common/assets/entities/account.assets'; +import { ScamInfo } from 'src/common/entities/scam-info.dto'; +import { NftCollectionAccount } from 'src/endpoints/collections/entities/nft.collection.account'; + +export type AccountDetailsDocument = HydratedDocument; + +@Schema({ collection: 'account-details', timestamps: true }) +export class AccountDetails { + @Prop({ type: mongoose.Schema.Types.ObjectId, auto: true }) + _id!: string; + + @Prop({ required: true, type: String }) + address: string = ''; + + @Prop({ required: true, type: String }) + balance: string = ''; + + @Prop({ required: true, type: Number }) + nonce: number = 0; + + @Prop({ required: false, type: Number }) + timestampMs: number = 0; + + @Prop({ required: true, type: Number }) + timestamp: number = 0; + + @Prop({ required: true, type: Number }) + shard: number = 0; + + @Prop({ required: false, type: String }) + ownerAddress?: string; + + @Prop({ type: Object, required: false }) + assets?: AccountAssets; + + @Prop({ required: false, type: Number }) + deployedAt?: number | null; + + @Prop({ required: false, type: String }) + deployTxHash?: string | null; + + @Prop({ type: Object, required: false }) + ownerAssets?: AccountAssets; + + @Prop({ required: false, type: Boolean }) + isVerified?: boolean; + + @Prop({ required: false, type: Number }) + txCount?: number; + + @Prop({ required: false, type: Number }) + scrCount?: number; + + @Prop({ required: false, type: Number }) + transfersLast24h?: number; + + @Prop({ required: false, type: String }) + code?: string; + + @Prop({ required: false, type: String }) + codeHash?: string; + + @Prop({ required: false, type: String }) + rootHash?: string; + + @Prop({ required: false, type: String }) + username?: string; + + @Prop({ required: true, type: String }) + developerReward: string = '0'; + + @Prop({ required: false, type: Boolean }) + isUpgradeable?: boolean; + + @Prop({ required: false, type: Boolean }) + isReadable?: boolean; + + @Prop({ required: false, type: Boolean }) + isPayable?: boolean; + + @Prop({ required: false, type: Boolean }) + isPayableBySmartContract?: boolean; + + @Prop({ type: Object, required: false }) + scamInfo?: ScamInfo; + + @Prop({ type: Array, required: false }) + nftCollections?: NftCollectionAccount[]; + + @Prop({ required: false, type: Number }) + activeGuardianActivationEpoch?: number; + + @Prop({ required: false, type: String }) + activeGuardianAddress?: string; + + @Prop({ required: false, type: String }) + activeGuardianServiceUid?: string; + + @Prop({ required: false, type: Number }) + pendingGuardianActivationEpoch?: number; + + @Prop({ required: false, type: String }) + pendingGuardianAddress?: string; + + @Prop({ required: false, type: String }) + pendingGuardianServiceUid?: string; + + @Prop({ required: false, type: Boolean }) + isGuarded?: boolean; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} + +export const AccountDetailsSchema = SchemaFactory.createForClass(AccountDetails); + +AccountDetailsSchema.index({ address: 1 }, { unique: true }); +AccountDetailsSchema.index({ "esdts.identifier": 1 }); diff --git a/src/common/indexer/db/schemas/esdt.details.schema.ts b/src/common/indexer/db/schemas/esdt.details.schema.ts new file mode 100644 index 000000000..7a5fa6e8c --- /dev/null +++ b/src/common/indexer/db/schemas/esdt.details.schema.ts @@ -0,0 +1,30 @@ +import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose"; +import mongoose, { HydratedDocument } from 'mongoose'; + +export type EsdtDetailsDocument = HydratedDocument; + + +@Schema({ collection: 'esdt-details', timestamps: true }) +export class EsdtDetails { + @Prop({ type: mongoose.Schema.Types.ObjectId, auto: true }) + _id!: string; + + @Prop({ required: true, type: String }) + address: string = ''; + + @Prop({ required: true, type: String }) + identifier: string = ''; + + @Prop({ required: true, type: String }) + balance: string = ''; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} + +export const EsdtDetailsSchema = SchemaFactory.createForClass(EsdtDetails); + +EsdtDetailsSchema.index({ address: 1 }); +EsdtDetailsSchema.index({ identifier: 1 }); +EsdtDetailsSchema.index({ address: 1, identifier: 1 }, { unique: true }); diff --git a/src/common/indexer/db/schemas/index.ts b/src/common/indexer/db/schemas/index.ts new file mode 100644 index 000000000..ddb5d941f --- /dev/null +++ b/src/common/indexer/db/schemas/index.ts @@ -0,0 +1,2 @@ +export * from './account.details.schema'; +export * from './esdt.details.schema'; diff --git a/src/common/indexer/db/utils/errors.ts b/src/common/indexer/db/utils/errors.ts new file mode 100644 index 000000000..942e05c1d --- /dev/null +++ b/src/common/indexer/db/utils/errors.ts @@ -0,0 +1,3 @@ +export enum MongoDbErrorCode { + DUPLICATE_KEY_ERROR = 11000, +} diff --git a/src/common/indexer/db/utils/index.ts b/src/common/indexer/db/utils/index.ts new file mode 100644 index 000000000..f72bc43e2 --- /dev/null +++ b/src/common/indexer/db/utils/index.ts @@ -0,0 +1 @@ +export * from './errors'; diff --git a/src/endpoints/accounts-v2/account.controller.v2.ts b/src/endpoints/accounts-v2/account.controller.v2.ts new file mode 100644 index 000000000..453cd578c --- /dev/null +++ b/src/endpoints/accounts-v2/account.controller.v2.ts @@ -0,0 +1,65 @@ +import { Controller, Get, HttpException, HttpStatus, NotFoundException, Param, Query, UseInterceptors } from '@nestjs/common'; +import { ApiOkResponse, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger'; +import { AccountServiceV2 } from './account.service.v2'; +import { ParseAddressPipe, ParseBoolPipe, ParseTokenOrNftPipe } from '@multiversx/sdk-nestjs-common'; +import { DeepHistoryInterceptor } from 'src/interceptors/deep-history.interceptor'; +import { NoCache } from '@multiversx/sdk-nestjs-cache'; +import { AccountDetailed } from '../accounts/entities/account.detailed'; +import { AccountFetchOptions } from '../accounts/entities/account.fetch.options'; +import { TokenDetailedWithBalance } from '../tokens/entities/token.detailed.with.balance'; + +@Controller('') +@ApiTags('accounts') +export class AccountControllerV2 { + + constructor( + private readonly accountServiceV2: AccountServiceV2, + ) { } + + @Get("/accounts/v2/:address") + @UseInterceptors(DeepHistoryInterceptor) + @ApiOperation({ summary: 'Account details', description: 'Returns account details for a given address' }) + @ApiQuery({ name: 'withGuardianInfo', description: 'Returns guardian data for a given address', required: false }) + @ApiQuery({ name: 'withTxCount', description: 'Returns the count of the transactions for a given address', required: false }) + @ApiQuery({ name: 'withScrCount', description: 'Returns the sc results count for a given address', required: false }) + @ApiQuery({ name: 'withTimestamp', description: 'Returns the timestamp of the last activity for a given address', required: false }) + @ApiQuery({ name: 'withAssets', description: 'Returns the assets for a given address', required: false }) + @ApiQuery({ name: 'timestamp', description: 'Retrieve entry from timestamp', required: false, type: Number }) + @ApiOkResponse({ type: AccountDetailed }) + @NoCache() + async getAccountDetails( + @Param('address', ParseAddressPipe) address: string, + @Query('withGuardianInfo', ParseBoolPipe) withGuardianInfo?: boolean, + @Query('withTxCount', ParseBoolPipe) withTxCount?: boolean, + @Query('withScrCount', ParseBoolPipe) withScrCount?: boolean, + @Query('withTimestamp', ParseBoolPipe) withTimestamp?: boolean, + @Query('withAssets', ParseBoolPipe) withAssets?: boolean, + ): Promise { + const account = await this.accountServiceV2.getAccount( + address, + new AccountFetchOptions({ withGuardianInfo, withTxCount, withScrCount, withTimestamp, withAssets }), + ); + if (!account) { + throw new NotFoundException('Account not found'); + } + + return account; + } + + @Get("/accounts/v2/:address/tokens/:token") + @UseInterceptors(DeepHistoryInterceptor) + @ApiOkResponse({ type: TokenDetailedWithBalance }) + @ApiOperation({ summary: 'Account token details', description: 'Returns details about a specific fungible token from a given address' }) + @NoCache() + async getAccountToken( + @Param('address', ParseAddressPipe) address: string, + @Param('token', ParseTokenOrNftPipe) token: string, + ): Promise { + const result = await this.accountServiceV2.getTokenForAddress(address, token); + if (!result) { + throw new HttpException('Token for given account not found', HttpStatus.NOT_FOUND); + } + + return result; + } +} diff --git a/src/endpoints/accounts-v2/account.module.v2.ts b/src/endpoints/accounts-v2/account.module.v2.ts new file mode 100644 index 000000000..63d56af21 --- /dev/null +++ b/src/endpoints/accounts-v2/account.module.v2.ts @@ -0,0 +1,49 @@ +import { forwardRef, Module } from "@nestjs/common"; +import { AssetsModule } from "src/common/assets/assets.module"; +import { PluginModule } from "src/plugins/plugin.module"; +import { CollectionModule } from "../collections/collection.module"; +import { DelegationLegacyModule } from "../delegation.legacy/delegation.legacy.module"; +import { NftModule } from "../nfts/nft.module"; +import { SmartContractResultModule } from "../sc-results/scresult.module"; +import { StakeModule } from "../stake/stake.module"; +import { TokenModule } from "../tokens/token.module"; +import { TransactionModule } from "../transactions/transaction.module"; +import { TransferModule } from "../transfers/transfer.module"; +import { UsernameModule } from "../usernames/username.module"; +import { VmQueryModule } from "../vm.query/vm.query.module"; +import { WaitingListModule } from "../waiting-list/waiting.list.module"; +import { AccountServiceV2 } from "./account.service.v2"; +import { ProviderModule } from "../providers/provider.module"; +import { KeysModule } from "../keys/keys.module"; +import { MongoDbModule } from "src/common/indexer/db"; +import { AccountService } from "../accounts/account.service"; + +@Module({ + imports: [ + VmQueryModule, + forwardRef(() => NftModule), + DelegationLegacyModule, + WaitingListModule, + forwardRef(() => StakeModule), + forwardRef(() => TransactionModule), + forwardRef(() => SmartContractResultModule), + forwardRef(() => CollectionModule), + forwardRef(() => PluginModule), + forwardRef(() => TransferModule), + forwardRef(() => TokenModule), + forwardRef(() => AssetsModule), + forwardRef(() => ProviderModule), + UsernameModule, + forwardRef(() => KeysModule), + MongoDbModule, + ], + providers: [ + AccountService, + AccountServiceV2, + ], + exports: [ + AccountService, + AccountServiceV2, + ], +}) +export class AccountModuleV2 { } diff --git a/src/endpoints/accounts-v2/account.service.v2.ts b/src/endpoints/accounts-v2/account.service.v2.ts new file mode 100644 index 000000000..b7c4b5da0 --- /dev/null +++ b/src/endpoints/accounts-v2/account.service.v2.ts @@ -0,0 +1,191 @@ +import { forwardRef, Inject, Injectable } from '@nestjs/common'; +import { PluginService } from 'src/common/plugins/plugin.service'; +import { AssetsService } from 'src/common/assets/assets.service'; +import { CacheService } from "@multiversx/sdk-nestjs-cache"; +import { AddressUtils, OriginLogger, TokenUtils } from '@multiversx/sdk-nestjs-common'; +import { IndexerService } from "src/common/indexer/indexer.service"; +import { CacheInfo } from 'src/utils/cache.info'; +import { UsernameService } from '../usernames/username.service'; +import { ProviderService } from '../providers/provider.service'; +import { Provider } from '../providers/entities/provider'; +import { AccountDetailsRepository } from 'src/common/indexer/db'; +import { StateChangesConsumerService } from 'src/state-changes/state.changes.consumer.service'; +import { AccountService } from '../accounts/account.service'; +import { AccountDetailed } from '../accounts/entities/account.detailed'; +import { AccountFetchOptions } from '../accounts/entities/account.fetch.options'; +import { TokenService } from '../tokens/token.service'; +import { TokenDetailedWithBalance } from '../tokens/entities/token.detailed.with.balance'; +import { GatewayService } from 'src/common/gateway/gateway.service'; +import { EsdtDetailsRepository } from 'src/common/indexer/db/repositories/esdt.details.repository'; +import { EsdtDetails } from 'src/common/indexer/db/schemas/esdt.details.schema'; + +@Injectable() +export class AccountServiceV2 { + private readonly logger = new OriginLogger(AccountServiceV2.name); + + constructor( + private readonly indexerService: IndexerService, + private readonly cachingService: CacheService, + @Inject(forwardRef(() => PluginService)) + private readonly pluginService: PluginService, + private readonly assetsService: AssetsService, + private readonly usernameService: UsernameService, + @Inject(forwardRef(() => ProviderService)) + private readonly providerService: ProviderService, + private readonly accountDetailsDepository: AccountDetailsRepository, + private readonly esdtDetailsRepository: EsdtDetailsRepository, + private readonly accountServiceV1: AccountService, + private readonly tokenService: TokenService, + private readonly gatewayService: GatewayService, + ) { } + + private async getAccountWithFallBack(address: string, options?: AccountFetchOptions): Promise { + // First try to get account from MongoDB if it is wallet address + let accountFromDb = null; + if (!AddressUtils.isSmartContractAddress(address)) { + accountFromDb = await this.accountDetailsDepository.getAccount(address); + } + if (!accountFromDb) { + // Second use the legacy method + return await this.accountServiceV1.getAccountRaw(address, options?.withAssets); + } + if (options && options.withAssets === true) { + const assets = await this.assetsService.getAllAccountAssets(); + accountFromDb.assets = assets[address]; + if (accountFromDb.ownerAddress && accountFromDb.ownerAddress !== '') { + accountFromDb.ownerAssets = assets[accountFromDb.ownerAddress]; + } + } + + accountFromDb.username = await this.usernameService.getUsernameForAddress(address) ?? undefined; + await this.pluginService.processAccount(accountFromDb); + return accountFromDb; + } + + async getAccount(address: string, options?: AccountFetchOptions): Promise { + if (!AddressUtils.isAddressValid(address)) { + return null; + } + let account = null; + try { + const isStateChangesConsumerHealthy: boolean = await StateChangesConsumerService.isStateChangesConsumerHealthy(this.cachingService, 6000); + if (isStateChangesConsumerHealthy === true && !StateChangesConsumerService.isSystemContractAddress(address)) { + account = await this.cachingService.getOrSet( + CacheInfo.AccountState(address).key, + async () => await this.getAccountWithFallBack(address, options), + CacheInfo.AccountState(address).ttl, + ); + if (account?.username) { + account.username = await this.usernameService.getUsernameForAddress(address) ?? undefined; + } + } else { + account = await this.accountServiceV1.getAccountRaw(address, options?.withAssets); + } + + if (!account) { + return null; + } + + if (options?.withTxCount === true) { + account.txCount = await this.accountServiceV1.getAccountTxCount(address); + } + + if (options?.withScrCount === true) { + account.scrCount = await this.accountServiceV1.getAccountScResults(address); + } + + if (options?.withGuardianInfo === true) { + await this.accountServiceV1.applyGuardianInfo(account); + } + + if (options?.withTimestamp) { + if (!account.timestamp || !account.timestampMs) { + const elasticSearchAccount = await this.indexerService.getAccount(address); + if (!account.timestamp) { + account.timestamp = elasticSearchAccount.timestamp; + } + if (!account.timestampMs && elasticSearchAccount.timestampMs) { + account.timestampMs = elasticSearchAccount.timestampMs; + } + } + } + + if (AddressUtils.isSmartContractAddress(address) && !account.ownerAddress) { + const provider: Provider | undefined = await this.providerService.getProvider(address); + if (provider && provider.owner) { + account.ownerAddress = provider.owner; + } + } + } catch (error) { + this.logger.error(`Error when getting account for address '${address}'`); + this.logger.error(error); + return null; + } + + return account; + } + + async getTokenForAddress(address: string, identifier: string): Promise { + if (!TokenUtils.isToken(identifier) && !TokenUtils.isNft(identifier)) { + return undefined; + } + try { + let tokenDetailedWithBalance: TokenDetailedWithBalance | undefined; + const isStateChangesConsumerHealthy: boolean = await StateChangesConsumerService.isStateChangesConsumerHealthy(this.cachingService, 6000); + if (isStateChangesConsumerHealthy === true && !StateChangesConsumerService.isSystemContractAddress(address)) { + tokenDetailedWithBalance = await this.getTokenForAddressWithFallback(address, identifier); + } else { + tokenDetailedWithBalance = await this.tokenService.getTokenForAddress(address, identifier); + } + return tokenDetailedWithBalance; + } catch (err) { + return undefined; + } + } + + async getTokenForAddressWithFallback(address: string, identifier: string): Promise { + const tokenRaw = await this.cachingService.getOrSet( + CacheInfo.AccountEsdt(address, identifier).key, + async () => { + const token = await this.esdtDetailsRepository.getEsdt(address, identifier); + if (token) { + return new EsdtDetails({ + identifier, + balance: token.balance, + }); + } + + const tokenFromGateway = await this.gatewayService.getAddressEsdt(address, identifier); + if (tokenFromGateway) { + return new EsdtDetails({ + identifier, + balance: tokenFromGateway.balance, + }); + } + return undefined; + }, + CacheInfo.AccountEsdt(address, identifier).ttl, + ); + + if (!tokenRaw) { + return await this.getTokenForAddress(address, identifier); + } + const { balance } = tokenRaw; + const esdtIdentifier = identifier.split('-').slice(0, 2).join('-'); + const tokens = await this.tokenService.getFilteredTokens({ identifier: esdtIdentifier, includeMetaESDT: true }); + if (!tokens.length) { + this.logger.log(`Error when fetching token ${identifier} details for address ${address}`); + return undefined; + } + + const tokenData = tokens[0]; + + const tokenDetailedWithBalance = new TokenDetailedWithBalance({ ...tokenData, balance }); + + this.tokenService.applyValueUsd(tokenDetailedWithBalance); + this.tokenService.applyTickerFromAssets(tokenDetailedWithBalance); + await this.tokenService.applySupply(tokenDetailedWithBalance); + + return tokenDetailedWithBalance; + } +} diff --git a/src/endpoints/endpoints.controllers.module.ts b/src/endpoints/endpoints.controllers.module.ts index 318e527f0..787599feb 100644 --- a/src/endpoints/endpoints.controllers.module.ts +++ b/src/endpoints/endpoints.controllers.module.ts @@ -39,12 +39,13 @@ import { PoolController } from "./pool/pool.controller"; import { TpsController } from "./tps/tps.controller"; import { ApplicationController } from "./applications/application.controller"; import { EventsController } from "./events/events.controller"; +import { AccountControllerV2 } from "./accounts-v2/account.controller.v2"; @Module({}) export class EndpointsControllersModule { static forRoot(): DynamicModule { const controllers: Type[] = [ - AccountController, BlockController, CollectionController, DelegationController, DelegationLegacyController, IdentitiesController, + AccountController, AccountControllerV2, BlockController, CollectionController, DelegationController, DelegationLegacyController, IdentitiesController, KeysController, MiniBlockController, NetworkController, NftController, TagController, NodeController, ProviderController, GatewayProxyController, RoundController, SmartContractResultController, ShardController, StakeController, StakeController, TokenController, TransactionController, UsernameController, VmQueryController, WaitingListController, diff --git a/src/endpoints/endpoints.services.module.ts b/src/endpoints/endpoints.services.module.ts index fc8531828..5b1d095cd 100644 --- a/src/endpoints/endpoints.services.module.ts +++ b/src/endpoints/endpoints.services.module.ts @@ -36,10 +36,12 @@ import { PoolModule } from "./pool/pool.module"; import { TpsModule } from "./tps/tps.module"; import { ApplicationModule } from "./applications/application.module"; import { EventsModule } from "./events/events.module"; +import { AccountModuleV2 } from "./accounts-v2/account.module.v2"; @Module({ imports: [ AccountModule, + AccountModuleV2, BlockModule, CollectionModule, DelegationModule, @@ -79,7 +81,7 @@ import { EventsModule } from "./events/events.module"; EventsModule, ], exports: [ - AccountModule, CollectionModule, BlockModule, DelegationModule, DelegationLegacyModule, IdentitiesModule, KeysModule, + AccountModule, AccountModuleV2, CollectionModule, BlockModule, DelegationModule, DelegationLegacyModule, IdentitiesModule, KeysModule, MiniBlockModule, NetworkModule, NftModule, NftMediaModule, TagModule, NodeModule, ProviderModule, RoundModule, SmartContractResultModule, ShardModule, StakeModule, TokenModule, RoundModule, TransactionModule, UsernameModule, VmQueryModule, WaitingListModule, EsdtModule, BlsModule, DappConfigModule, TransferModule, PoolModule, TransactionActionModule, WebsocketModule, MexModule, diff --git a/src/endpoints/network/network.controller.ts b/src/endpoints/network/network.controller.ts index f1fb81f55..719f83aff 100644 --- a/src/endpoints/network/network.controller.ts +++ b/src/endpoints/network/network.controller.ts @@ -41,7 +41,6 @@ export class NetworkController { } } - @Get("/about") @ApiOperation({ summary: 'About', description: 'Returns general information about API deployment' }) @ApiOkResponse({ type: About }) diff --git a/src/main.ts b/src/main.ts index aca22383e..a4d03f1c3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -38,6 +38,7 @@ import * as requestIp from 'request-ip'; import compression from 'compression'; import { IoAdapter } from '@nestjs/platform-socket.io'; import { WebsocketSubscriptionModule } from './crons/websocket/websocket.subscription.module'; +import { StateChangesModule } from './state-changes/state.changes.module'; async function bootstrap() { const logger = new Logger('Bootstrapper'); @@ -147,23 +148,30 @@ async function bootstrap() { await eventsNotifierApp.listen(apiConfigService.getEventsNotifierFeaturePort()); } - const pubSubApp = await NestFactory.createMicroservice( - PubSubListenerModule, - { - transport: Transport.REDIS, - options: { - host: apiConfigService.getRedisUrl(), - port: 6379, - retryAttempts: 100, - retryDelay: 1000, - retryStrategy: () => 1000, + if (apiConfigService.isStateChangesFeatureActive()) { + const stateChangesApp = await NestFactory.create(StateChangesModule.register()); + await stateChangesApp.listen(apiConfigService.getStateChangesFeaturePort()); + } + + if (apiConfigService.isPubSubListenerEnabled()) { + const pubSubApp = await NestFactory.createMicroservice( + PubSubListenerModule, + { + transport: Transport.REDIS, + options: { + host: apiConfigService.getRedisUrl(), + port: 6379, + retryAttempts: 100, + retryDelay: 1000, + retryStrategy: () => 1000, + }, }, - }, - ); - pubSubApp.useLogger(pubSubApp.get(WINSTON_MODULE_NEST_PROVIDER)); - pubSubApp.useWebSocketAdapter(new SocketAdapter(pubSubApp)); - // eslint-disable-next-line @typescript-eslint/no-floating-promises - pubSubApp.listen(); + ); + pubSubApp.useLogger(pubSubApp.get(WINSTON_MODULE_NEST_PROVIDER)); + pubSubApp.useWebSocketAdapter(new SocketAdapter(pubSubApp)); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + pubSubApp.listen(); + } logger.log(`Public API active: ${apiConfigService.getIsPublicApiActive()}`); logger.log(`Private API active: ${apiConfigService.getIsPrivateApiActive()}`); diff --git a/src/state-changes/entities/account-changes-raw.ts b/src/state-changes/entities/account-changes-raw.ts new file mode 100644 index 000000000..98c887a3a --- /dev/null +++ b/src/state-changes/entities/account-changes-raw.ts @@ -0,0 +1,11 @@ +export enum AccountChangesRaw { + NoChange = 0, + NonceChanged = 1 << 0, // 1 + BalanceChanged = 1 << 1, // 2 + CodeHashChanged = 1 << 2, // 4 + RootHashChanged = 1 << 3, // 8 + DeveloperRewardChanged = 1 << 4, // 16 + OwnerAddressChanged = 1 << 5, // 32 + UserNameChanged = 1 << 6, // 64 + CodeMetadataChanged = 1 << 7 // 128 +} diff --git a/src/state-changes/entities/account-changes.ts b/src/state-changes/entities/account-changes.ts new file mode 100644 index 000000000..ced774c91 --- /dev/null +++ b/src/state-changes/entities/account-changes.ts @@ -0,0 +1,14 @@ +export class AccountChanges { + nonceChanged!: boolean; + balanceChanged!: boolean; + codeHashChanged!: boolean; + rootHashChanged!: boolean; + developerRewardChanged!: boolean; + ownerAddressChanged!: boolean; + userNameChanged!: boolean; + codeMetadataChanged!: boolean; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/state-changes/entities/account-state.ts b/src/state-changes/entities/account-state.ts new file mode 100644 index 000000000..7f0bbabdc --- /dev/null +++ b/src/state-changes/entities/account-state.ts @@ -0,0 +1,15 @@ +export class AccountState { + nonce!: number; + balance!: string; + developerReward!: string; + address!: string; + codeHash?: string; + rootHash!: string; + ownerAddress?: string; + username?: string; + codeMetadata?: string; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/state-changes/entities/block-with-state-changes-raw.ts b/src/state-changes/entities/block-with-state-changes-raw.ts new file mode 100644 index 000000000..a4c5002f6 --- /dev/null +++ b/src/state-changes/entities/block-with-state-changes-raw.ts @@ -0,0 +1,13 @@ +import { StateAccessPerAccountRaw } from "./state-access-per-account-raw"; + +export class BlockWithStateChangesRaw { + hash!: string; + shardID!: number; + nonce!: number; + timestampMs!: number; + stateAccessesPerAccounts!: Record; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/state-changes/entities/data-trie-change-operation.ts b/src/state-changes/entities/data-trie-change-operation.ts new file mode 100644 index 000000000..d448b7ebc --- /dev/null +++ b/src/state-changes/entities/data-trie-change-operation.ts @@ -0,0 +1,4 @@ +export enum DataTrieChangeOperation { + NotDelete = 0, + Delete = 1, +} diff --git a/src/state-changes/entities/data-trie-change.ts b/src/state-changes/entities/data-trie-change.ts new file mode 100644 index 000000000..722fc6608 --- /dev/null +++ b/src/state-changes/entities/data-trie-change.ts @@ -0,0 +1,9 @@ +import { DataTrieChangeOperation } from "./data-trie-change-operation"; + +export class DataTrieChange { + type!: number; + key!: string; + val!: any; + version!: number; + operation!: DataTrieChangeOperation; +} diff --git a/src/state-changes/entities/esdt-state.ts b/src/state-changes/entities/esdt-state.ts new file mode 100644 index 000000000..614c3fc0e --- /dev/null +++ b/src/state-changes/entities/esdt-state.ts @@ -0,0 +1,15 @@ +import { ESDTType } from "./esdt-type"; + +export class EsdtState { + identifier!: string; + nonce!: string; + type!: ESDTType; + value!: string; + propertiesHex!: string; + reservedHex!: string; + tokenMetaData!: any; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/state-changes/entities/esdt-type.ts b/src/state-changes/entities/esdt-type.ts new file mode 100644 index 000000000..6dd0f4eb7 --- /dev/null +++ b/src/state-changes/entities/esdt-type.ts @@ -0,0 +1,10 @@ +export enum ESDTType { + Fungible = 0, + NonFungible = 1, + NonFungibleV2 = 2, + SemiFungible = 3, + MetaFungible = 4, + DynamicNFT = 5, + DynamicSFT = 6, + DynamicMeta = 7, +} diff --git a/src/state-changes/entities/index.ts b/src/state-changes/entities/index.ts new file mode 100644 index 000000000..79b691e9a --- /dev/null +++ b/src/state-changes/entities/index.ts @@ -0,0 +1,14 @@ +// Entities +export * from "./account-changes"; +export * from "./state-access-per-account-raw"; +export * from "./data-trie-change"; +export * from "./block-with-state-changes-raw"; +export * from "./account-state"; +export * from "./esdt-state"; +export * from "./state-changes"; + +// Enums +export * from "./esdt-type"; +export * from "./account-changes-raw"; +export * from "./state-access-operation"; +export * from "./data-trie-change-operation"; diff --git a/src/state-changes/entities/state-access-operation.ts b/src/state-changes/entities/state-access-operation.ts new file mode 100644 index 000000000..97aaa749e --- /dev/null +++ b/src/state-changes/entities/state-access-operation.ts @@ -0,0 +1,9 @@ +export enum StateAccessOperation { + NotSet = 0, + GetCode = 1 << 0, + SaveAccount = 1 << 1, + GetAccount = 1 << 2, + WriteCode = 1 << 3, + RemoveDataTrie = 1 << 4, + GetDataTrieValue = 1 << 5, +} diff --git a/src/state-changes/entities/state-access-per-account-raw.ts b/src/state-changes/entities/state-access-per-account-raw.ts new file mode 100644 index 000000000..a65d829df --- /dev/null +++ b/src/state-changes/entities/state-access-per-account-raw.ts @@ -0,0 +1,16 @@ +import { DataTrieChange } from "./data-trie-change"; + +export class StateAccessPerAccountRaw { + type!: number; + index!: number; + txHash!: string; + mainTrieKey!: string; + mainTrieVal!: string; + operation!: number; + dataTrieChanges?: DataTrieChange[]; + accountChanges?: number; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/state-changes/entities/state-changes.ts b/src/state-changes/entities/state-changes.ts new file mode 100644 index 000000000..e0c712d28 --- /dev/null +++ b/src/state-changes/entities/state-changes.ts @@ -0,0 +1,23 @@ +import { AccountState } from "./account-state"; +import { EsdtState } from "./esdt-state"; +import { AccountChanges } from "./account-changes"; + +export class StateChanges { + accountState!: AccountState | undefined; + esdtState!: { + 'Fungible': EsdtState[], + 'NonFungible': EsdtState[], + 'NonFungibleV2': EsdtState[], + 'SemiFungible': EsdtState[], + 'MetaFungible': EsdtState[], + 'DynamicNFT': EsdtState[], + 'DynamicSFT': EsdtState[], + 'DynamicMeta': EsdtState[], + }; + accountChanges!: AccountChanges; + isNewAccount!: boolean; + + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/state-changes/state.changes.consumer.service.ts b/src/state-changes/state.changes.consumer.service.ts new file mode 100644 index 000000000..669fea4bd --- /dev/null +++ b/src/state-changes/state.changes.consumer.service.ts @@ -0,0 +1,347 @@ +import { CompetingRabbitConsumer } from "src/common/rabbitmq/rabbitmq.consumers"; +import { BlockWithStateChangesRaw, ESDTType, StateChanges } from "./entities"; +import { AccountDetails, AccountDetailsRepository, EsdtDetails, EsdtDetailsRepository } from "src/common/indexer/db"; +import { Inject, Injectable } from "@nestjs/common"; +import { CacheService } from "@multiversx/sdk-nestjs-cache"; +import { CacheInfo } from "src/utils/cache.info"; +import { TokenType } from "src/common/indexer/entities"; +import { NftType } from "src/endpoints/nfts/entities/nft.type"; +import { NftSubType } from "src/endpoints/nfts/entities/nft.sub.type"; +import { ClientProxy } from "@nestjs/microservices"; +import { StateChangesDecoder } from "./utils/state-changes.decoder"; +import { AddressUtils, OriginLogger, TokenUtils } from "@multiversx/sdk-nestjs-common"; +import { PerformanceProfiler } from "@multiversx/sdk-nestjs-monitoring"; +import configuration from "config/configuration"; +import { ApiConfigService } from "src/common/api-config/api.config.service"; +import { NftAccount } from "src/endpoints/nfts/entities/nft.account"; +import { TokenWithBalance } from "src/endpoints/tokens/entities/token.with.balance"; + +@Injectable() +export class StateChangesConsumerService { + private readonly logger = new OriginLogger(StateChangesConsumerService.name); + + constructor( + private readonly cacheService: CacheService, + private readonly accountDetailsRepository: AccountDetailsRepository, + private readonly esdtDetailsRepository: EsdtDetailsRepository, + private readonly apiConfigService: ApiConfigService, + @Inject('PUBSUB_SERVICE') private clientProxy: ClientProxy, + ) { } + + @CompetingRabbitConsumer({ + exchange: configuration().features.stateChanges.exchange ?? 'state_accesses', + queueName: configuration().features.stateChanges.queueName ?? 'api_state_accesses_queue', + deadLetterExchange: configuration().features.stateChanges.deadLetterExchange ?? 'api_state_accesses_queue_dlx', + }) + async consumeEvents(blockWithStateChanges: BlockWithStateChangesRaw) { + try { + if (blockWithStateChanges.shardID === this.apiConfigService.getMetaChainShardId()) { + return; // skip meta shard + } + + const profiler = new PerformanceProfiler('BlockStateChangesProcessing'); + const decodingProfiler = new PerformanceProfiler('StateChangesDecoding'); + + const finalStates = this.decodeStateChangesFinal(blockWithStateChanges); + const { transformedAccounts, transformedEsdts } = this.transformFinalStatesToDbFormat(finalStates, blockWithStateChanges.shardID, blockWithStateChanges.timestampMs); + decodingProfiler.stop('StateChangesDecoding'); + this.logger.log(`Decoded state changes for block ${blockWithStateChanges.hash} on shard ${blockWithStateChanges.shardID} in ${decodingProfiler.duration} ms`); + + await this.updateAccounts(transformedAccounts, transformedEsdts); + + await this.cacheService.setRemote( + CacheInfo.StateChangesConsumerLatestProcessedBlockTimestamp(blockWithStateChanges.shardID).key, + blockWithStateChanges.timestampMs, + CacheInfo.StateChangesConsumerLatestProcessedBlockTimestamp(blockWithStateChanges.shardID).ttl, + ); + + profiler.stop('BlockStateChangesProcessing'); + this.logger.log(`Processed state changes for block ${blockWithStateChanges.hash} on shard ${blockWithStateChanges.shardID} in ${profiler.duration} ms`); + } catch (error) { + this.logger.error(`Error consuming state changes from shard ${blockWithStateChanges.shardID}:`, error); + throw error; + } + } + + private async updateAccounts(transformedAccounts: AccountDetails[], transformedEsdts: EsdtDetails[]) { + const promisesToWaitFor = [ + this.accountDetailsRepository.updateAccounts(transformedAccounts.filter(account => !AddressUtils.isSmartContractAddress(account.address))), + this.esdtDetailsRepository.updateEsdts(transformedEsdts.filter(esdt => !AddressUtils.isSmartContractAddress(esdt.address) && TokenUtils.isToken(esdt.identifier))), + ]; + + const esdtsUpdateCacheKeys = []; + const esdtsDeleteCacheKeys = []; + const walletAccountCacheKeys = []; + const contractCacheKeys = []; + const walletAccountValues = []; + const esdtsUpdateValues = []; + for (const account of transformedAccounts) { + + if (!AddressUtils.isSmartContractAddress(account.address)) { + walletAccountCacheKeys.push(CacheInfo.AccountState(account.address).key); + walletAccountValues.push(account); + } else { + contractCacheKeys.push(CacheInfo.AccountState(account.address).key); + } + } + + for (const esdt of transformedEsdts) { + if (esdt.balance === '0') { + esdtsDeleteCacheKeys.push(CacheInfo.AccountEsdt(esdt.address, esdt.identifier).key); + } else { + esdtsUpdateCacheKeys.push(CacheInfo.AccountEsdt(esdt.address, esdt.identifier).key); + esdtsUpdateValues.push(esdt); + } + } + + if (walletAccountCacheKeys.length > 0 || esdtsUpdateCacheKeys.length > 0) { + promisesToWaitFor.push( + this.cacheService.setManyRemote( + [...walletAccountCacheKeys, ...esdtsUpdateCacheKeys], + [...walletAccountValues, ...esdtsUpdateValues], + CacheInfo.AccountEsdt('any', 'any').ttl, + ), + ); + } + + if (contractCacheKeys.length > 0 || esdtsDeleteCacheKeys.length > 0) { + promisesToWaitFor.push( + this.cacheService.deleteManyRemote( + [...contractCacheKeys, ...esdtsDeleteCacheKeys], + ) + ); + } + + this.deleteLocalCache([...walletAccountCacheKeys, ...contractCacheKeys, ...esdtsUpdateCacheKeys, ...esdtsDeleteCacheKeys]); + + await Promise.all(promisesToWaitFor); + } + private decodeStateChangesFinal(blockWithStateChanges: BlockWithStateChangesRaw) { + const isEsdtComputationEnabled = this.apiConfigService.isEsdtComputationEnabled(); + return StateChangesDecoder.decodeStateChangesFinal(blockWithStateChanges, isEsdtComputationEnabled); + } + + private transformFinalStatesToDbFormat( + finalStates: Record, + shardID: number, + blockTimestampMs: number, + ) { + const isEsdtComputationEnabled = this.apiConfigService.isEsdtComputationEnabled(); + const transformedAccounts: AccountDetails[] = []; + const transformedEsdts: EsdtDetails[] = []; + for (const [_address, state] of Object.entries(finalStates)) { + const baseAccount = this.parseBaseAccount( + state, + shardID, + blockTimestampMs + ); + if (!baseAccount) continue; + + const parsedAccount = new AccountDetails({ + ...baseAccount, + }); + transformedAccounts.push(parsedAccount); + + if (isEsdtComputationEnabled) { + const esdts = this.transformEsdts(state); + transformedEsdts.push(...esdts); + } + } + + return { transformedAccounts, transformedEsdts }; + } + + private parseBaseAccount( + state: StateChanges, + shardID: number, + blockTimestampMs: number + ) { + if (!state.accountState) return undefined; + const { codeMetadata, ...filteredState } = state.accountState; + + return { + ...filteredState, + shard: shardID, + timestampMs: blockTimestampMs, + timestamp: Math.floor(blockTimestampMs / 1000), + ...this.parseCodeMetadata(filteredState.address, codeMetadata), + }; + } + + private transformEsdts(state: StateChanges) { + const allEsdts = [ + ...(state.esdtState.Fungible ?? []), + ...(state.esdtState.NonFungible ?? []), + ...(state.esdtState.NonFungibleV2 ?? []), + ...(state.esdtState.DynamicNFT ?? []), + ...(state.esdtState.SemiFungible ?? []), + ...(state.esdtState.DynamicSFT ?? []), + ...(state.esdtState.MetaFungible ?? []), + ...(state.esdtState.DynamicMeta ?? []), + ]; + return allEsdts.map(esdt => new EsdtDetails({ + address: state.accountState?.address, + identifier: esdt.identifier, + balance: esdt.value, + }) + ); + } + + //@ts-ignore + private transformTokens(state: StateChanges): TokenWithBalance[] { + const fungible = state.esdtState?.Fungible ?? []; + + return fungible.map(token => + new TokenWithBalance({ + identifier: token.identifier, + nonce: parseInt(token.nonce), + balance: token.value, + type: this.parseEsdtType(token.type) as TokenType, + subType: NftSubType.None, + }) + ); + } + + //@ts-ignore + private transformNfts(state: StateChanges): NftAccount[] { + const { + NonFungible, + NonFungibleV2, + DynamicNFT, + SemiFungible, + DynamicSFT, + MetaFungible, + DynamicMeta, + } = state.esdtState ?? {}; + + const allNfts = [ + ...(NonFungible ?? []), + ...(NonFungibleV2 ?? []), + ...(DynamicNFT ?? []), + ...(SemiFungible ?? []), + ...(DynamicSFT ?? []), + ...(MetaFungible ?? []), + ...(DynamicMeta ?? []), + ]; + + return allNfts.map(nft => + new NftAccount({ + identifier: nft.identifier, + nonce: parseInt(nft.nonce), + type: this.parseEsdtType(nft.type) as NftType, + subType: this.parseEsdtSubtype(nft.type), + collection: nft.identifier.replace(/-[^-]*$/, ''), + balance: nft.value, + }) + ); + } + + + private deleteLocalCache(cacheKeys: string[]) { + this.clientProxy.emit('deleteCacheKeys', cacheKeys); + } + + private parseCodeMetadata(address: string, hexStr?: string) { + if (!hexStr || hexStr === '') { + return {}; + } + + if (!AddressUtils.isSmartContractAddress(address)) { + const GUARDED = 0x08_00; + const value = parseInt(hexStr, 16); + return { + isGuarded: (value & GUARDED) !== 0, + }; + } + + const UPGRADEABLE = 0x01_00; // 256 + const READABLE = 0x04_00; // 1024 + const PAYABLE = 0x00_02; // 2 + const PAYABLE_BY_SC = 0x00_04; // 4 + const value = parseInt(hexStr, 16); + + return { + isUpgradeable: (value & UPGRADEABLE) !== 0, + isReadable: (value & READABLE) !== 0, + isPayable: (value & PAYABLE) !== 0, + isPayableBySmartContract: (value & PAYABLE_BY_SC) !== 0, + }; + } + + //@ts-ignore + private parseEsdtType(type: ESDTType): TokenType | NftType { + switch (type) { + case ESDTType.Fungible: + return TokenType.FungibleESDT; + + case ESDTType.NonFungible: + case ESDTType.DynamicNFT: + case ESDTType.NonFungibleV2: + return NftType.NonFungibleESDT; + + case ESDTType.SemiFungible: + case ESDTType.DynamicSFT: + return NftType.SemiFungibleESDT; + case ESDTType.MetaFungible: + case ESDTType.DynamicMeta: + return NftType.MetaESDT; + } + } + + //@ts-ignore + private parseEsdtSubtype(type: ESDTType): NftSubType { + switch (type) { + case ESDTType.Fungible: + return NftSubType.None; + + case ESDTType.NonFungible: + return NftSubType.NonFungibleESDT; + case ESDTType.DynamicNFT: + return NftSubType.DynamicNonFungibleESDT; + case ESDTType.NonFungibleV2: + return NftSubType.NonFungibleESDTv2; + + case ESDTType.SemiFungible: + return NftSubType.SemiFungibleESDT; + case ESDTType.DynamicSFT: + return NftSubType.DynamicSemiFungibleESDT; + case ESDTType.MetaFungible: + return NftSubType.MetaESDT; + case ESDTType.DynamicMeta: + return NftSubType.DynamicMetaESDT; + } + } + + static async isStateChangesConsumerHealthy(cacheService: CacheService, maxLastActivityDiffMs: number): Promise { + const keys = [ + CacheInfo.StateChangesConsumerLatestProcessedBlockTimestamp(0).key, + CacheInfo.StateChangesConsumerLatestProcessedBlockTimestamp(1).key, + CacheInfo.StateChangesConsumerLatestProcessedBlockTimestamp(2).key, + ]; + + let timestampsMs: (number | undefined | null)[] | undefined = cacheService.getManyLocal(keys); + + // check local + if (timestampsMs == null || timestampsMs.some(t => t == null)) { + timestampsMs = await cacheService.getManyRemote(keys); + + // check remote + if (timestampsMs == null || timestampsMs.some(t => t == null)) { + return false; + } + + // set only if it's valid + cacheService.setManyLocal(keys, timestampsMs, 0.6); + } + + const minTimestamp = Math.min(...(timestampsMs as number[])); + + const diff = Date.now() - minTimestamp; + + return diff <= maxLastActivityDiffMs; + } + + static isSystemContractAddress(address: string) { + return StateChangesDecoder.isSystemContractAddress(address); + } +} diff --git a/src/state-changes/state.changes.module.ts b/src/state-changes/state.changes.module.ts new file mode 100644 index 000000000..8427048b7 --- /dev/null +++ b/src/state-changes/state.changes.module.ts @@ -0,0 +1,41 @@ +import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq'; +import { DynamicModule, Module } from '@nestjs/common'; +import { DynamicModuleUtils } from 'src/utils/dynamic.module.utils'; +import { ApiConfigModule } from 'src/common/api-config/api.config.module'; +import { ApiConfigService } from 'src/common/api-config/api.config.service'; +import { StateChangesConsumerService } from './state.changes.consumer.service'; +import { MongoDbModule } from 'src/common/indexer/db'; + +@Module({ + imports: [ + ApiConfigModule, + MongoDbModule, + DynamicModuleUtils.getCacheModule(), + ], + providers: [ + StateChangesConsumerService, + DynamicModuleUtils.getPubSubService(), + ], +}) +export class StateChangesModule { + static register(): DynamicModule { + return { + module: StateChangesModule, + imports: [ + RabbitMQModule.forRootAsync(RabbitMQModule, { + imports: [ApiConfigModule], + inject: [ApiConfigService], + useFactory: (apiConfigService: ApiConfigService) => { + return { + name: apiConfigService.getStateChangesExchange(), + type: 'fanout', + options: {}, + uri: apiConfigService.getStateChangesRabbitUrl(), + prefetchCount: 1, + }; + }, + }), + ], + }; + } +} diff --git a/src/state-changes/utils/esdt.d.ts b/src/state-changes/utils/esdt.d.ts new file mode 100644 index 000000000..410eed3c8 --- /dev/null +++ b/src/state-changes/utils/esdt.d.ts @@ -0,0 +1,214 @@ +import * as $protobuf from "protobufjs"; +import Long = require("long"); +/** Properties of a MetaData. */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IMetaData { +} + +/** Represents a MetaData. */ +export class MetaData implements IMetaData { + + /** + * Constructs a new MetaData. + * @param [properties] Properties to set + */ + constructor(properties?: IMetaData); + + /** + * Creates a new MetaData instance using the specified properties. + * @param [properties] Properties to set + * @returns MetaData instance + */ + public static create(properties?: IMetaData): MetaData; + + /** + * Encodes the specified MetaData message. Does not implicitly {@link MetaData.verify|verify} messages. + * @param message MetaData message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: IMetaData, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified MetaData message, length delimited. Does not implicitly {@link MetaData.verify|verify} messages. + * @param message MetaData message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: IMetaData, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a MetaData message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns MetaData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader | Uint8Array), length?: number): MetaData; + + /** + * Decodes a MetaData message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns MetaData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader | Uint8Array)): MetaData; + + /** + * Verifies a MetaData message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string | null); + + /** + * Creates a MetaData message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns MetaData + */ + public static fromObject(object: { [k: string]: any }): MetaData; + + /** + * Creates a plain object from a MetaData message. Also converts values to other types if specified. + * @param message MetaData + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: MetaData, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this MetaData to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for MetaData + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; +} + +/** Properties of a ESDigitalToken. */ +export interface IESDigitalToken { + + /** ESDigitalToken Type */ + Type?: (number | null); + + /** ESDigitalToken Value */ + Value?: (Uint8Array | null); + + /** ESDigitalToken Properties */ + Properties?: (Uint8Array | null); + + /** ESDigitalToken TokenMetaData */ + TokenMetaData?: (IMetaData | null); + + /** ESDigitalToken Reserved */ + Reserved?: (Uint8Array | null); +} + +/** Represents a ESDigitalToken. */ +export class ESDigitalToken implements IESDigitalToken { + + /** + * Constructs a new ESDigitalToken. + * @param [properties] Properties to set + */ + constructor(properties?: IESDigitalToken); + + /** ESDigitalToken Type. */ + public Type: number; + + /** ESDigitalToken Value. */ + public Value: Uint8Array; + + /** ESDigitalToken Properties. */ + public Properties: Uint8Array; + + /** ESDigitalToken TokenMetaData. */ + public TokenMetaData?: (IMetaData | null); + + /** ESDigitalToken Reserved. */ + public Reserved: Uint8Array; + + /** + * Creates a new ESDigitalToken instance using the specified properties. + * @param [properties] Properties to set + * @returns ESDigitalToken instance + */ + public static create(properties?: IESDigitalToken): ESDigitalToken; + + /** + * Encodes the specified ESDigitalToken message. Does not implicitly {@link ESDigitalToken.verify|verify} messages. + * @param message ESDigitalToken message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: IESDigitalToken, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified ESDigitalToken message, length delimited. Does not implicitly {@link ESDigitalToken.verify|verify} messages. + * @param message ESDigitalToken message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: IESDigitalToken, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a ESDigitalToken message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns ESDigitalToken + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader | Uint8Array), length?: number): ESDigitalToken; + + /** + * Decodes a ESDigitalToken message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns ESDigitalToken + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader | Uint8Array)): ESDigitalToken; + + /** + * Verifies a ESDigitalToken message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string | null); + + /** + * Creates a ESDigitalToken message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns ESDigitalToken + */ + public static fromObject(object: { [k: string]: any }): ESDigitalToken; + + /** + * Creates a plain object from a ESDigitalToken message. Also converts values to other types if specified. + * @param message ESDigitalToken + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: ESDigitalToken, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this ESDigitalToken to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for ESDigitalToken + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; +} diff --git a/src/state-changes/utils/esdt.js b/src/state-changes/utils/esdt.js new file mode 100644 index 000000000..8d6b67ce6 --- /dev/null +++ b/src/state-changes/utils/esdt.js @@ -0,0 +1,519 @@ +/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ +"use strict"; + +var $protobuf = require("protobufjs/minimal"); + +// Common aliases +var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + +$root.MetaData = (function () { + + /** + * Properties of a MetaData. + * @exports IMetaData + * @interface IMetaData + */ + + /** + * Constructs a new MetaData. + * @exports MetaData + * @classdesc Represents a MetaData. + * @implements IMetaData + * @constructor + * @param {IMetaData=} [properties] Properties to set + */ + function MetaData(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Creates a new MetaData instance using the specified properties. + * @function create + * @memberof MetaData + * @static + * @param {IMetaData=} [properties] Properties to set + * @returns {MetaData} MetaData instance + */ + MetaData.create = function create(properties) { + return new MetaData(properties); + }; + + /** + * Encodes the specified MetaData message. Does not implicitly {@link MetaData.verify|verify} messages. + * @function encode + * @memberof MetaData + * @static + * @param {IMetaData} message MetaData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MetaData.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + return writer; + }; + + /** + * Encodes the specified MetaData message, length delimited. Does not implicitly {@link MetaData.verify|verify} messages. + * @function encodeDelimited + * @memberof MetaData + * @static + * @param {IMetaData} message MetaData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + MetaData.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a MetaData message from the specified reader or buffer. + * @function decode + * @memberof MetaData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {MetaData} MetaData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MetaData.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.MetaData(); + while (reader.pos < end) { + var tag = reader.uint32(); + if (tag === error) + break; + switch (tag >>> 3) { + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a MetaData message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof MetaData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {MetaData} MetaData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + MetaData.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a MetaData message. + * @function verify + * @memberof MetaData + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + MetaData.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + return null; + }; + + /** + * Creates a MetaData message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof MetaData + * @static + * @param {Object.} object Plain object + * @returns {MetaData} MetaData + */ + MetaData.fromObject = function fromObject(object) { + if (object instanceof $root.MetaData) + return object; + return new $root.MetaData(); + }; + + /** + * Creates a plain object from a MetaData message. Also converts values to other types if specified. + * @function toObject + * @memberof MetaData + * @static + * @param {MetaData} message MetaData + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + MetaData.toObject = function toObject() { + return {}; + }; + + /** + * Converts this MetaData to JSON. + * @function toJSON + * @memberof MetaData + * @instance + * @returns {Object.} JSON object + */ + MetaData.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for MetaData + * @function getTypeUrl + * @memberof MetaData + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + MetaData.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/MetaData"; + }; + + return MetaData; +})(); + +$root.ESDigitalToken = (function () { + + /** + * Properties of a ESDigitalToken. + * @exports IESDigitalToken + * @interface IESDigitalToken + * @property {number|null} [Type] ESDigitalToken Type + * @property {Uint8Array|null} [Value] ESDigitalToken Value + * @property {Uint8Array|null} [Properties] ESDigitalToken Properties + * @property {IMetaData|null} [TokenMetaData] ESDigitalToken TokenMetaData + * @property {Uint8Array|null} [Reserved] ESDigitalToken Reserved + */ + + /** + * Constructs a new ESDigitalToken. + * @exports ESDigitalToken + * @classdesc Represents a ESDigitalToken. + * @implements IESDigitalToken + * @constructor + * @param {IESDigitalToken=} [properties] Properties to set + */ + function ESDigitalToken(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * ESDigitalToken Type. + * @member {number} Type + * @memberof ESDigitalToken + * @instance + */ + ESDigitalToken.prototype.Type = 0; + + /** + * ESDigitalToken Value. + * @member {Uint8Array} Value + * @memberof ESDigitalToken + * @instance + */ + ESDigitalToken.prototype.Value = $util.newBuffer([]); + + /** + * ESDigitalToken Properties. + * @member {Uint8Array} Properties + * @memberof ESDigitalToken + * @instance + */ + ESDigitalToken.prototype.Properties = $util.newBuffer([]); + + /** + * ESDigitalToken TokenMetaData. + * @member {IMetaData|null|undefined} TokenMetaData + * @memberof ESDigitalToken + * @instance + */ + ESDigitalToken.prototype.TokenMetaData = null; + + /** + * ESDigitalToken Reserved. + * @member {Uint8Array} Reserved + * @memberof ESDigitalToken + * @instance + */ + ESDigitalToken.prototype.Reserved = $util.newBuffer([]); + + /** + * Creates a new ESDigitalToken instance using the specified properties. + * @function create + * @memberof ESDigitalToken + * @static + * @param {IESDigitalToken=} [properties] Properties to set + * @returns {ESDigitalToken} ESDigitalToken instance + */ + ESDigitalToken.create = function create(properties) { + return new ESDigitalToken(properties); + }; + + /** + * Encodes the specified ESDigitalToken message. Does not implicitly {@link ESDigitalToken.verify|verify} messages. + * @function encode + * @memberof ESDigitalToken + * @static + * @param {IESDigitalToken} message ESDigitalToken message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ESDigitalToken.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.Type != null && Object.hasOwnProperty.call(message, "Type")) + writer.uint32(/* id 1, wireType 0 =*/8).uint32(message.Type); + if (message.Value != null && Object.hasOwnProperty.call(message, "Value")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.Value); + if (message.Properties != null && Object.hasOwnProperty.call(message, "Properties")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.Properties); + if (message.TokenMetaData != null && Object.hasOwnProperty.call(message, "TokenMetaData")) + $root.MetaData.encode(message.TokenMetaData, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); + if (message.Reserved != null && Object.hasOwnProperty.call(message, "Reserved")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.Reserved); + return writer; + }; + + /** + * Encodes the specified ESDigitalToken message, length delimited. Does not implicitly {@link ESDigitalToken.verify|verify} messages. + * @function encodeDelimited + * @memberof ESDigitalToken + * @static + * @param {IESDigitalToken} message ESDigitalToken message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ESDigitalToken.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ESDigitalToken message from the specified reader or buffer. + * @function decode + * @memberof ESDigitalToken + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {ESDigitalToken} ESDigitalToken + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ESDigitalToken.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.ESDigitalToken(); + while (reader.pos < end) { + var tag = reader.uint32(); + if (tag === error) + break; + switch (tag >>> 3) { + case 1: { + message.Type = reader.uint32(); + break; + } + case 2: { + message.Value = reader.bytes(); + break; + } + case 3: { + message.Properties = reader.bytes(); + break; + } + case 4: { + message.TokenMetaData = $root.MetaData.decode(reader, reader.uint32()); + break; + } + case 5: { + message.Reserved = reader.bytes(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ESDigitalToken message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof ESDigitalToken + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {ESDigitalToken} ESDigitalToken + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ESDigitalToken.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ESDigitalToken message. + * @function verify + * @memberof ESDigitalToken + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ESDigitalToken.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.Type != null && message.hasOwnProperty("Type")) + if (!$util.isInteger(message.Type)) + return "Type: integer expected"; + if (message.Value != null && message.hasOwnProperty("Value")) + if (!(message.Value && typeof message.Value.length === "number" || $util.isString(message.Value))) + return "Value: buffer expected"; + if (message.Properties != null && message.hasOwnProperty("Properties")) + if (!(message.Properties && typeof message.Properties.length === "number" || $util.isString(message.Properties))) + return "Properties: buffer expected"; + if (message.TokenMetaData != null && message.hasOwnProperty("TokenMetaData")) { + var error = $root.MetaData.verify(message.TokenMetaData); + if (error) + return "TokenMetaData." + error; + } + if (message.Reserved != null && message.hasOwnProperty("Reserved")) + if (!(message.Reserved && typeof message.Reserved.length === "number" || $util.isString(message.Reserved))) + return "Reserved: buffer expected"; + return null; + }; + + /** + * Creates a ESDigitalToken message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof ESDigitalToken + * @static + * @param {Object.} object Plain object + * @returns {ESDigitalToken} ESDigitalToken + */ + ESDigitalToken.fromObject = function fromObject(object) { + if (object instanceof $root.ESDigitalToken) + return object; + var message = new $root.ESDigitalToken(); + if (object.Type != null) + message.Type = object.Type >>> 0; + if (object.Value != null) + if (typeof object.Value === "string") + $util.base64.decode(object.Value, message.Value = $util.newBuffer($util.base64.length(object.Value)), 0); + else if (object.Value.length >= 0) + message.Value = object.Value; + if (object.Properties != null) + if (typeof object.Properties === "string") + $util.base64.decode(object.Properties, message.Properties = $util.newBuffer($util.base64.length(object.Properties)), 0); + else if (object.Properties.length >= 0) + message.Properties = object.Properties; + if (object.TokenMetaData != null) { + if (typeof object.TokenMetaData !== "object") + throw TypeError(".ESDigitalToken.TokenMetaData: object expected"); + message.TokenMetaData = $root.MetaData.fromObject(object.TokenMetaData); + } + if (object.Reserved != null) + if (typeof object.Reserved === "string") + $util.base64.decode(object.Reserved, message.Reserved = $util.newBuffer($util.base64.length(object.Reserved)), 0); + else if (object.Reserved.length >= 0) + message.Reserved = object.Reserved; + return message; + }; + + /** + * Creates a plain object from a ESDigitalToken message. Also converts values to other types if specified. + * @function toObject + * @memberof ESDigitalToken + * @static + * @param {ESDigitalToken} message ESDigitalToken + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ESDigitalToken.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.Type = 0; + if (options.bytes === String) + object.Value = ""; + else { + object.Value = []; + if (options.bytes !== Array) + object.Value = $util.newBuffer(object.Value); + } + if (options.bytes === String) + object.Properties = ""; + else { + object.Properties = []; + if (options.bytes !== Array) + object.Properties = $util.newBuffer(object.Properties); + } + object.TokenMetaData = null; + if (options.bytes === String) + object.Reserved = ""; + else { + object.Reserved = []; + if (options.bytes !== Array) + object.Reserved = $util.newBuffer(object.Reserved); + } + } + if (message.Type != null && message.hasOwnProperty("Type")) + object.Type = message.Type; + if (message.Value != null && message.hasOwnProperty("Value")) + object.Value = options.bytes === String ? $util.base64.encode(message.Value, 0, message.Value.length) : options.bytes === Array ? Array.prototype.slice.call(message.Value) : message.Value; + if (message.Properties != null && message.hasOwnProperty("Properties")) + object.Properties = options.bytes === String ? $util.base64.encode(message.Properties, 0, message.Properties.length) : options.bytes === Array ? Array.prototype.slice.call(message.Properties) : message.Properties; + if (message.TokenMetaData != null && message.hasOwnProperty("TokenMetaData")) + object.TokenMetaData = $root.MetaData.toObject(message.TokenMetaData, options); + if (message.Reserved != null && message.hasOwnProperty("Reserved")) + object.Reserved = options.bytes === String ? $util.base64.encode(message.Reserved, 0, message.Reserved.length) : options.bytes === Array ? Array.prototype.slice.call(message.Reserved) : message.Reserved; + return object; + }; + + /** + * Converts this ESDigitalToken to JSON. + * @function toJSON + * @memberof ESDigitalToken + * @instance + * @returns {Object.} JSON object + */ + ESDigitalToken.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ESDigitalToken + * @function getTypeUrl + * @memberof ESDigitalToken + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ESDigitalToken.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/ESDigitalToken"; + }; + + return ESDigitalToken; +})(); + +module.exports = $root; diff --git a/src/state-changes/utils/esdt.proto b/src/state-changes/utils/esdt.proto new file mode 100644 index 000000000..54eece29f --- /dev/null +++ b/src/state-changes/utils/esdt.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +message MetaData { + // ex: string name = 1; + // optional uint64 id = 2; +} + +message ESDigitalToken { + uint32 Type = 1; + + bytes Value = 2; + + bytes Properties = 3; + + MetaData TokenMetaData = 4; + + bytes Reserved = 5; +} diff --git a/src/state-changes/utils/state-changes.decoder.ts b/src/state-changes/utils/state-changes.decoder.ts new file mode 100644 index 000000000..a9593bd83 --- /dev/null +++ b/src/state-changes/utils/state-changes.decoder.ts @@ -0,0 +1,433 @@ +import { Address } from "@multiversx/sdk-core/out"; +import { UserAccountData } from "./user_account.pb"; +import { ESDigitalToken } from "./esdt"; +import { TokenParser } from "./token.parser"; +import { + AccountChanges, + AccountChangesRaw, + AccountState, + BlockWithStateChangesRaw, + DataTrieChange, + DataTrieChangeOperation, + EsdtState, + ESDTType, + StateAccessOperation, + StateAccessPerAccountRaw, + StateChanges, +} from "../entities"; + +export class StateChangesDecoder { + private static SYSTEM_ACCOUNTS = new Set([ + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqllls0lczs7", // stakingScAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqplllst77y4l", // validatorScAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", // esdtScAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrlllsrujgla", // governanceScAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqrlllllllllllllllllllllllllsn60f0k", // jailingAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqlllllllllllllllllllllllllllsr9gav8", // endOfEpochAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6", // delegationManagerScAddress + "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0llllsqkarq6", // firstDelegationScAddress + "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu", // contractDeployScAddress + "erd17rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rcqqkhty3", // genesisMintingAddress + "erd1lllllllllllllllllllllllllllllllllllllllllllllllllllsckry7t", // systemAccountAddress + "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", // esdtGlobalSettingsAddresses[0] + "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366", // esdtGlobalSettingsAddresses[1] + "erd1lllllllllllllllllllllllllllllllllllllllllllllllllupq9x7ny0", // esdtGlobalSettingsAddresses[2] + ]); + + static isSystemContractAddress(address: string) { + return this.SYSTEM_ACCOUNTS.has(address); + } + + private static bech32FromHex(hex: any) { + const clean = hex.startsWith("0x") ? hex.slice(2) : hex; + return Address.newFromHex(clean).toBech32(); + } + + private static bech32FromBytes(u8: any) { + return (u8 && u8.length ? Address.newFromHex(this.bytesToHex(u8)).toBech32() : ""); + } + + private static bytesToHex(u8: any) { + return (u8 && u8.length ? Buffer.from(u8).toString("hex") : ""); + } + + private static bytesToBase64(u8: any) { + return (u8 && u8.length ? Buffer.from(u8).toString("base64") : ""); + } + + private static longToString(v: any) { + return v == null ? "" : (typeof v === "object" && typeof v.toString === "function" ? v.toString() : String(v)); + } + + private static bigEndianBytesToBigInt(u8: any) { + let v = BigInt(0); + for (const b of u8) { + v = (v << BigInt(8)) + BigInt(b); + } + return v; + } + + /** + * MultiversX custom sign & magnitude BigInt for proto: + * - zero => [0x00, 0x00] + * - positive non-zero => 0x00 || magnitude (big-endian) + * - (if present) negative => 0x01 || magnitude + * Fallback: if first byte is not a sign marker, treat whole buffer as positive magnitude. + */ + private static decodeMxSignMagBigInt(u8: any) { + if (!u8 || u8.length === 0) return BigInt(0); + + // canonical zero used by the serializer + if (u8.length === 2 && u8[0] === 0x00 && u8[1] === 0x00) return BigInt(0); + + const sign = u8[0]; + if (sign === 0x00 || sign === 0x01) { + const mag = u8.slice(1); + const m = this.bigEndianBytesToBigInt(mag); + return sign === 0x01 ? -m : m; + } + + // fallback for legacy "magnitude only" encodings + return this.bigEndianBytesToBigInt(u8); + } + + private static getDecodedUserAccountData(base64Value: string | null): AccountState | null { + try { + if (base64Value == null || base64Value === '') { + return null; + } + const buf = Buffer.from(base64Value, "base64"); + const msg = UserAccountData.decode(buf as Uint8Array); + + const balance = this.decodeMxSignMagBigInt(msg.Balance); + const devReward = this.decodeMxSignMagBigInt(msg.DeveloperReward); + const address = this.bech32FromBytes(msg.Address); + const ownerAddress = this.bech32FromBytes(msg.OwnerAddress); + + const data: AccountState = { + nonce: parseInt(this.longToString(msg.Nonce)), + balance: balance.toString(), + developerReward: devReward.toString(), + address, + ownerAddress, + codeHash: this.bytesToBase64(msg.CodeHash), + rootHash: this.bytesToBase64(msg.RootHash), + username: Buffer.from(this.bytesToHex(msg.UserName), 'hex').toString(), + codeMetadata: this.bytesToHex(msg.CodeMetadata), + }; + + const filteredData = Object.fromEntries( + Object.entries(data).filter(([_, v]) => v !== undefined && v !== null && v !== '') + ) as AccountState; + + return filteredData; + } catch (e: any) { + console.warn(`Could not decode as UserAccountData: ${e.message}`); + return null; + } + } + + private static decodeAccountChanges(flags: number | undefined): AccountChanges { + if (!flags) { + return new AccountChanges({ + nonceChanged: false, + balanceChanged: false, + codeHashChanged: false, + rootHashChanged: false, + developerRewardChanged: false, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }); + } + return new AccountChanges({ + nonceChanged: (flags & AccountChangesRaw.NonceChanged) !== 0, + balanceChanged: (flags & AccountChangesRaw.BalanceChanged) !== 0, + codeHashChanged: (flags & AccountChangesRaw.CodeHashChanged) !== 0, + rootHashChanged: (flags & AccountChangesRaw.RootHashChanged) !== 0, + developerRewardChanged: (flags & AccountChangesRaw.DeveloperRewardChanged) !== 0, + ownerAddressChanged: (flags & AccountChangesRaw.OwnerAddressChanged) !== 0, + userNameChanged: (flags & AccountChangesRaw.UserNameChanged) !== 0, + codeMetadataChanged: (flags & AccountChangesRaw.CodeMetadataChanged) !== 0, + }); + } + + private static getDecodedEsdtData(address: string, dataTrieChange: DataTrieChange) { + const bufTrieLeafValue = Buffer.from(dataTrieChange.val, "base64"); + const esdtPrefix = 'ELRONDesdt'; + try { + const keyRawBuf = Buffer.from(dataTrieChange.key, "base64"); + const keyRaw = keyRawBuf.toString(); + if (keyRaw.startsWith(esdtPrefix)) { + const keyBuf = keyRawBuf.slice(esdtPrefix.length); + const msgEsdtData: ESDigitalToken = ESDigitalToken.decode(bufTrieLeafValue as Uint8Array); + + const valueBigInt: bigint = this.decodeMxSignMagBigInt(msgEsdtData.Value); + const [identifier, nonceHex] = TokenParser.extractTokenIDAndNonceHexFromTokenStorageKey(keyBuf); + + return { + identifier: nonceHex !== '00' ? `${identifier}-${nonceHex}` : identifier, + nonce: parseInt(nonceHex, 16).toString(), + type: msgEsdtData.Type, + value: valueBigInt.toString(), + propertiesHex: this.bytesToHex(msgEsdtData.Properties), + reservedHex: this.bytesToHex(msgEsdtData.Reserved), + tokenMetaData: msgEsdtData.TokenMetaData ?? null, + }; + } else { + //TODO: handle if needed + return null; + } + } catch (e: any) { + console.warn(`Could not decode as EsdtData: ${e.message}`); + console.log(address, ':'); + console.dir(dataTrieChange); + return null; + } + } + + static decodeStateChangesRaw(blockWithStateChanges: BlockWithStateChangesRaw) { + const allAccounts: Record = {}; + const accounts = blockWithStateChanges.stateAccessesPerAccounts || {}; + + for (const accountHex of Object.keys(accounts)) { + const address = this.bech32FromHex(accountHex); + + if (this.isSystemContractAddress(address)) { + continue; + } + + const { stateAccess = [] } = accounts[accountHex] || {}; + const allDecoded: Record = {}; + stateAccess.forEach((sa: StateAccessPerAccountRaw, i: number) => { + + const base64AccountData = sa.mainTrieVal; + const decodedAccountData = this.getDecodedUserAccountData(base64AccountData); + + const dataTrieChanges = sa.dataTrieChanges; + + + const allDecodedEsdtData: any[] = []; + if (dataTrieChanges) { + for (const dataTrieChange of dataTrieChanges) { + if (dataTrieChange.version === 0 && dataTrieChange.val) { + const decodedEsdtData = this.getDecodedEsdtData(address, dataTrieChange); + if (decodedEsdtData) { + if (dataTrieChange.operation === DataTrieChangeOperation.Delete) { + decodedEsdtData.value = '0'; + } + allDecodedEsdtData.push(decodedEsdtData); + } + } + } + } + + if (decodedAccountData || allDecodedEsdtData.length > 0) { + const groupedEsdtStates = allDecodedEsdtData.reduce>( + (acc, state) => { + const typeName = ESDTType[state.type]; // numeric -> string + if (typeName) { + acc[typeName].push(state); + } + + return acc; + }, + { + Fungible: [], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + } + ); + if (allDecoded[address] === undefined) allDecoded[address] = []; + const newAccount = this.isNewAccount(sa); + + allDecoded[address].push({ + entry: `Entry #${i}`, + accountState: decodedAccountData, + esdtStates: groupedEsdtStates, + accountChanges: this.decodeAccountChanges(sa.accountChanges), + newAccount, + }); + } + }); + if (Object.keys(allDecoded).length === 0) continue; + + allAccounts[address] = [...(allAccounts[address] || []), ...Object.values(allDecoded).flat()]; + } + + return allAccounts; + } + + static decodeStateChangesFinal(blockWithStateChanges: BlockWithStateChangesRaw, isEsdtComputationEnabled: boolean = false) { + const accounts = blockWithStateChanges.stateAccessesPerAccounts; + const finalStates: Record = {}; + + for (const accountHex of Object.keys(accounts)) { + const address = this.bech32FromHex(accountHex); + + if (this.isSystemContractAddress(address)) { + continue; + } + const { stateAccess: accountStateAccesses } = accounts[accountHex] || {}; + finalStates[address] = this.getAccountFinalState(address, accountStateAccesses, isEsdtComputationEnabled); + } + + return finalStates; + } + + + private static getAccountFinalState(address: string, accountStateAccesses: StateAccessPerAccountRaw[], isEsdtComputationEnabled: boolean = false) { + let finalAccountChangesRaw: AccountChangesRaw = AccountChangesRaw.NoChange; + const esdtOccured: Record = {}; + let finalNewAccount = false; + + let finalAccountState: AccountState | undefined = undefined; + const finalEsdtStates = { + Fungible: [] as EsdtState[], + NonFungible: [] as EsdtState[], + NonFungibleV2: [] as EsdtState[], + SemiFungible: [] as EsdtState[], + MetaFungible: [] as EsdtState[], + DynamicNFT: [] as EsdtState[], + DynamicSFT: [] as EsdtState[], + DynamicMeta: [] as EsdtState[], + }; + + for (let i = accountStateAccesses.length - 1; i >= 0; i--) { + const stateAccess = accountStateAccesses[i]; + const currentAccountChangesRaw = stateAccess.accountChanges; + if (currentAccountChangesRaw) { + finalAccountChangesRaw |= currentAccountChangesRaw; + } + + // if we already found it as new account, we skip the computation + if (!finalNewAccount) { + const currentNewAccount = this.isNewAccount(stateAccess); + finalNewAccount = currentNewAccount || finalNewAccount; + } + + // the final state is the first state we find when iterating backwards on state accesses array + if (!finalAccountState) { + const base64AccountData = stateAccess.mainTrieVal; + const decodedAccountData = this.getDecodedUserAccountData(base64AccountData); + + if (decodedAccountData) { + finalAccountState = decodedAccountData; + //TODO: remove when we want to use accountChanges + if (!isEsdtComputationEnabled) { + break; + } + } + } + + const dataTrieChanges = stateAccess.dataTrieChanges; + if (dataTrieChanges && isEsdtComputationEnabled) { + for (let i = dataTrieChanges.length - 1; i >= 0; i--) { + const dataTrieChange = dataTrieChanges[i]; + if (dataTrieChange.version !== 0 && dataTrieChange.val) { + const decodedEsdtData = this.getDecodedEsdtData(address, dataTrieChange); + + // last esdt state is the first appeareance in reverse order when iterating over account state accesses + if (decodedEsdtData && !esdtOccured[decodedEsdtData.identifier]) { + const typeName = ESDTType[decodedEsdtData.type] as keyof typeof finalEsdtStates; // numeric -> string + + // double check in case some unknown type passed through + if (typeName) { + if (dataTrieChange.operation === DataTrieChangeOperation.Delete) { + decodedEsdtData.value = '0'; + } + finalEsdtStates[typeName].push(decodedEsdtData); + esdtOccured[decodedEsdtData.identifier] = true; + } + } + } + } + } + } + return { + accountState: finalAccountState, + esdtState: finalEsdtStates, + accountChanges: this.decodeAccountChanges(finalAccountChangesRaw), + isNewAccount: finalNewAccount, + }; + } + + private static isNewAccount(stateAccess: StateAccessPerAccountRaw) { + return (stateAccess.accountChanges == null) && + (stateAccess.operation & StateAccessOperation.SaveAccount) ? true : false; + } + + static getFinalStatesFromStateChangesRaw(stateChanges: Record) { + const finalStates: Record = {}; + + for (const [address, entries] of Object.entries(stateChanges)) { + let finalAccountState: AccountState | undefined = undefined; + const finalEsdtStates = { + Fungible: [] as EsdtState[], + NonFungible: [] as EsdtState[], + NonFungibleV2: [] as EsdtState[], + SemiFungible: [] as EsdtState[], + MetaFungible: [] as EsdtState[], + DynamicNFT: [] as EsdtState[], + DynamicSFT: [] as EsdtState[], + DynamicMeta: [] as EsdtState[], + }; + const finalAccountChanges: AccountChanges = new AccountChanges({ + nonceChanged: false, + balanceChanged: false, + codeHashChanged: false, + rootHashChanged: false, + developerRewardChanged: false, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }); + + let finalNewAccount = false; + + for (const entry of entries) { + const currentAccountState: AccountState = entry.accountState; + const currentEsdtStates = entry.esdtStates; + const currentAccountChanges = entry.accountChanges; + const currentNewAccount = entry.newAccount as boolean; + + + finalNewAccount = finalNewAccount ? finalNewAccount : currentNewAccount; + + finalAccountState = currentAccountState; + + (Object.entries(finalAccountChanges) as [keyof typeof finalAccountChanges, boolean][]).forEach( + ([key, value]) => { + finalAccountChanges[key] = value || currentAccountChanges[key]; + } + ); + + + (Object.entries(currentEsdtStates) as [keyof typeof finalEsdtStates, any[]][]).forEach( + ([tokenType, tokenChanges]) => { + for (const tokenChange of tokenChanges) { + let index = finalEsdtStates[tokenType].findIndex((item: any) => item.key === tokenChange.key); + index = index !== -1 ? index : finalEsdtStates[tokenType].length; + finalEsdtStates[tokenType][index] = tokenChange; + } + + } + ); + } + + finalStates[address] = { + accountState: finalAccountState, + esdtState: finalEsdtStates, + accountChanges: finalAccountChanges, + isNewAccount: finalNewAccount, + }; + } + + return finalStates; + } +} diff --git a/src/state-changes/utils/token.parser.ts b/src/state-changes/utils/token.parser.ts new file mode 100644 index 000000000..4f11b768a --- /dev/null +++ b/src/state-changes/utils/token.parser.ts @@ -0,0 +1,58 @@ +export class TokenParser { + // Constants from Go + private static readonly esdtTickerNumRandChars: number = 6; + private static readonly separatorChar: string = "-"; + private static readonly minLengthForTickerName: number = 3; + private static readonly maxLengthForTickerName: number = 10; + + /** + * ExtractTokenIDAndNonceFromTokenStorageKey + * Parses the token's storage key and extracts the identifier and the nonce. + * + * Examples: + * "ALC-1q2w3e" -> ["ALC-1q2w3e", "0"] (fungible, no nonce) + * "ALC-2w3e4rX" -> ["ALC-2w3e4r", "X"] (non-fungible, nonce = "X") + */ + + //TODO: add support for sovereign keys prefix + public static extractTokenIDAndNonceHexFromTokenStorageKey( + tokenKeyRaw: Buffer + ): [string, string] { + const tokenKey = tokenKeyRaw.toString(); + const token = tokenKey; + + const indexOfFirstHyphen = token.indexOf(this.separatorChar); + if (indexOfFirstHyphen < 0) { + return [tokenKey, "00"]; + } + + const tokenTicker = token.slice(0, indexOfFirstHyphen); + const randomSequencePlusNonce = token.slice(indexOfFirstHyphen + 1); + + const tokenTickerLen = tokenTicker.length; + + const areTickerAndRandomSequenceInvalid = + tokenTickerLen === 0 || + tokenTickerLen < this.minLengthForTickerName || + tokenTickerLen > this.maxLengthForTickerName || + randomSequencePlusNonce.length === 0; + + if (areTickerAndRandomSequenceInvalid) { + return [tokenKey, "00"]; + } + + if (randomSequencePlusNonce.length < this.esdtTickerNumRandChars + 1) { + return [tokenKey, "00"]; + } + + // ALC-1q2w3eX -> X is the nonce + const nonceStr = randomSequencePlusNonce.slice(this.esdtTickerNumRandChars); + + const numCharsSinceNonce = token.length - nonceStr.length; + const tokenID = token.slice(0, numCharsSinceNonce); + if (nonceStr) { + return [tokenID, Array.from(tokenKeyRaw.slice(tokenID.length)).map(byte => byte.toString(16).padStart(2, '0')).join('')]; + } + return [tokenID, "00"]; + } +} diff --git a/src/state-changes/utils/trie_leaf_data.d.ts b/src/state-changes/utils/trie_leaf_data.d.ts new file mode 100644 index 000000000..219357d40 --- /dev/null +++ b/src/state-changes/utils/trie_leaf_data.d.ts @@ -0,0 +1,110 @@ +import * as $protobuf from "protobufjs"; +import Long = require("long"); +/** Properties of a TrieLeafData. */ +export interface ITrieLeafData { + + /** TrieLeafData value */ + value?: (Uint8Array | null); + + /** TrieLeafData key */ + key?: (Uint8Array | null); + + /** TrieLeafData address */ + address?: (Uint8Array | null); +} + +/** Represents a TrieLeafData. */ +export class TrieLeafData implements ITrieLeafData { + + /** + * Constructs a new TrieLeafData. + * @param [properties] Properties to set + */ + constructor(properties?: ITrieLeafData); + + /** TrieLeafData value. */ + public value: Uint8Array; + + /** TrieLeafData key. */ + public key: Uint8Array; + + /** TrieLeafData address. */ + public address: Uint8Array; + + /** + * Creates a new TrieLeafData instance using the specified properties. + * @param [properties] Properties to set + * @returns TrieLeafData instance + */ + public static create(properties?: ITrieLeafData): TrieLeafData; + + /** + * Encodes the specified TrieLeafData message. Does not implicitly {@link TrieLeafData.verify|verify} messages. + * @param message TrieLeafData message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: ITrieLeafData, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified TrieLeafData message, length delimited. Does not implicitly {@link TrieLeafData.verify|verify} messages. + * @param message TrieLeafData message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: ITrieLeafData, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a TrieLeafData message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns TrieLeafData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader | Uint8Array), length?: number): TrieLeafData; + + /** + * Decodes a TrieLeafData message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns TrieLeafData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader | Uint8Array)): TrieLeafData; + + /** + * Verifies a TrieLeafData message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string | null); + + /** + * Creates a TrieLeafData message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns TrieLeafData + */ + public static fromObject(object: { [k: string]: any }): TrieLeafData; + + /** + * Creates a plain object from a TrieLeafData message. Also converts values to other types if specified. + * @param message TrieLeafData + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: TrieLeafData, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this TrieLeafData to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for TrieLeafData + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; +} diff --git a/src/state-changes/utils/trie_leaf_data.js b/src/state-changes/utils/trie_leaf_data.js new file mode 100644 index 000000000..03adf9033 --- /dev/null +++ b/src/state-changes/utils/trie_leaf_data.js @@ -0,0 +1,291 @@ +/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ +"use strict"; + +var $protobuf = require("protobufjs/minimal"); + +// Common aliases +var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + +$root.TrieLeafData = (function () { + + /** + * Properties of a TrieLeafData. + * @exports ITrieLeafData + * @interface ITrieLeafData + * @property {Uint8Array|null} [value] TrieLeafData value + * @property {Uint8Array|null} [key] TrieLeafData key + * @property {Uint8Array|null} [address] TrieLeafData address + */ + + /** + * Constructs a new TrieLeafData. + * @exports TrieLeafData + * @classdesc Represents a TrieLeafData. + * @implements ITrieLeafData + * @constructor + * @param {ITrieLeafData=} [properties] Properties to set + */ + function TrieLeafData(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * TrieLeafData value. + * @member {Uint8Array} value + * @memberof TrieLeafData + * @instance + */ + TrieLeafData.prototype.value = $util.newBuffer([]); + + /** + * TrieLeafData key. + * @member {Uint8Array} key + * @memberof TrieLeafData + * @instance + */ + TrieLeafData.prototype.key = $util.newBuffer([]); + + /** + * TrieLeafData address. + * @member {Uint8Array} address + * @memberof TrieLeafData + * @instance + */ + TrieLeafData.prototype.address = $util.newBuffer([]); + + /** + * Creates a new TrieLeafData instance using the specified properties. + * @function create + * @memberof TrieLeafData + * @static + * @param {ITrieLeafData=} [properties] Properties to set + * @returns {TrieLeafData} TrieLeafData instance + */ + TrieLeafData.create = function create(properties) { + return new TrieLeafData(properties); + }; + + /** + * Encodes the specified TrieLeafData message. Does not implicitly {@link TrieLeafData.verify|verify} messages. + * @function encode + * @memberof TrieLeafData + * @static + * @param {ITrieLeafData} message TrieLeafData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrieLeafData.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.value != null && Object.hasOwnProperty.call(message, "value")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.value); + if (message.key != null && Object.hasOwnProperty.call(message, "key")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.key); + if (message.address != null && Object.hasOwnProperty.call(message, "address")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.address); + return writer; + }; + + /** + * Encodes the specified TrieLeafData message, length delimited. Does not implicitly {@link TrieLeafData.verify|verify} messages. + * @function encodeDelimited + * @memberof TrieLeafData + * @static + * @param {ITrieLeafData} message TrieLeafData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + TrieLeafData.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a TrieLeafData message from the specified reader or buffer. + * @function decode + * @memberof TrieLeafData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {TrieLeafData} TrieLeafData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrieLeafData.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.TrieLeafData(); + while (reader.pos < end) { + var tag = reader.uint32(); + if (tag === error) + break; + switch (tag >>> 3) { + case 1: { + message.value = reader.bytes(); + break; + } + case 2: { + message.key = reader.bytes(); + break; + } + case 3: { + message.address = reader.bytes(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a TrieLeafData message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof TrieLeafData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {TrieLeafData} TrieLeafData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + TrieLeafData.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a TrieLeafData message. + * @function verify + * @memberof TrieLeafData + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + TrieLeafData.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.value != null && message.hasOwnProperty("value")) + if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) + return "value: buffer expected"; + if (message.key != null && message.hasOwnProperty("key")) + if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key))) + return "key: buffer expected"; + if (message.address != null && message.hasOwnProperty("address")) + if (!(message.address && typeof message.address.length === "number" || $util.isString(message.address))) + return "address: buffer expected"; + return null; + }; + + /** + * Creates a TrieLeafData message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof TrieLeafData + * @static + * @param {Object.} object Plain object + * @returns {TrieLeafData} TrieLeafData + */ + TrieLeafData.fromObject = function fromObject(object) { + if (object instanceof $root.TrieLeafData) + return object; + var message = new $root.TrieLeafData(); + if (object.value != null) + if (typeof object.value === "string") + $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); + else if (object.value.length >= 0) + message.value = object.value; + if (object.key != null) + if (typeof object.key === "string") + $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0); + else if (object.key.length >= 0) + message.key = object.key; + if (object.address != null) + if (typeof object.address === "string") + $util.base64.decode(object.address, message.address = $util.newBuffer($util.base64.length(object.address)), 0); + else if (object.address.length >= 0) + message.address = object.address; + return message; + }; + + /** + * Creates a plain object from a TrieLeafData message. Also converts values to other types if specified. + * @function toObject + * @memberof TrieLeafData + * @static + * @param {TrieLeafData} message TrieLeafData + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + TrieLeafData.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if (options.bytes === String) + object.value = ""; + else { + object.value = []; + if (options.bytes !== Array) + object.value = $util.newBuffer(object.value); + } + if (options.bytes === String) + object.key = ""; + else { + object.key = []; + if (options.bytes !== Array) + object.key = $util.newBuffer(object.key); + } + if (options.bytes === String) + object.address = ""; + else { + object.address = []; + if (options.bytes !== Array) + object.address = $util.newBuffer(object.address); + } + } + if (message.value != null && message.hasOwnProperty("value")) + object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; + if (message.key != null && message.hasOwnProperty("key")) + object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; + if (message.address != null && message.hasOwnProperty("address")) + object.address = options.bytes === String ? $util.base64.encode(message.address, 0, message.address.length) : options.bytes === Array ? Array.prototype.slice.call(message.address) : message.address; + return object; + }; + + /** + * Converts this TrieLeafData to JSON. + * @function toJSON + * @memberof TrieLeafData + * @instance + * @returns {Object.} JSON object + */ + TrieLeafData.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for TrieLeafData + * @function getTypeUrl + * @memberof TrieLeafData + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + TrieLeafData.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/TrieLeafData"; + }; + + return TrieLeafData; +})(); + +module.exports = $root; diff --git a/src/state-changes/utils/trie_leaf_data.proto b/src/state-changes/utils/trie_leaf_data.proto new file mode 100644 index 000000000..8a17f74cb --- /dev/null +++ b/src/state-changes/utils/trie_leaf_data.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +message TrieLeafData { + bytes value = 1; + bytes key = 2; + bytes address = 3; +} diff --git a/src/state-changes/utils/user_account.pb.d.ts b/src/state-changes/utils/user_account.pb.d.ts new file mode 100644 index 000000000..7b0c21fc3 --- /dev/null +++ b/src/state-changes/utils/user_account.pb.d.ts @@ -0,0 +1,146 @@ +import * as $protobuf from "protobufjs"; +import Long = require("long"); +/** Properties of a UserAccountData. */ +export interface IUserAccountData { + + /** UserAccountData Nonce */ + Nonce?: (number | Long | null); + + /** UserAccountData Balance */ + Balance?: (Uint8Array | null); + + /** UserAccountData CodeHash */ + CodeHash?: (Uint8Array | null); + + /** UserAccountData RootHash */ + RootHash?: (Uint8Array | null); + + /** UserAccountData Address */ + Address?: (Uint8Array | null); + + /** UserAccountData DeveloperReward */ + DeveloperReward?: (Uint8Array | null); + + /** UserAccountData OwnerAddress */ + OwnerAddress?: (Uint8Array | null); + + /** UserAccountData UserName */ + UserName?: (Uint8Array | null); + + /** UserAccountData CodeMetadata */ + CodeMetadata?: (Uint8Array | null); +} + +/** Represents a UserAccountData. */ +export class UserAccountData implements IUserAccountData { + + /** + * Constructs a new UserAccountData. + * @param [properties] Properties to set + */ + constructor(properties?: IUserAccountData); + + /** UserAccountData Nonce. */ + public Nonce: (number | Long); + + /** UserAccountData Balance. */ + public Balance: Uint8Array; + + /** UserAccountData CodeHash. */ + public CodeHash: Uint8Array; + + /** UserAccountData RootHash. */ + public RootHash: Uint8Array; + + /** UserAccountData Address. */ + public Address: Uint8Array; + + /** UserAccountData DeveloperReward. */ + public DeveloperReward: Uint8Array; + + /** UserAccountData OwnerAddress. */ + public OwnerAddress: Uint8Array; + + /** UserAccountData UserName. */ + public UserName: Uint8Array; + + /** UserAccountData CodeMetadata. */ + public CodeMetadata: Uint8Array; + + /** + * Creates a new UserAccountData instance using the specified properties. + * @param [properties] Properties to set + * @returns UserAccountData instance + */ + public static create(properties?: IUserAccountData): UserAccountData; + + /** + * Encodes the specified UserAccountData message. Does not implicitly {@link UserAccountData.verify|verify} messages. + * @param message UserAccountData message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encode(message: IUserAccountData, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Encodes the specified UserAccountData message, length delimited. Does not implicitly {@link UserAccountData.verify|verify} messages. + * @param message UserAccountData message or plain object to encode + * @param [writer] Writer to encode to + * @returns Writer + */ + public static encodeDelimited(message: IUserAccountData, writer?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a UserAccountData message from the specified reader or buffer. + * @param reader Reader or buffer to decode from + * @param [length] Message length if known beforehand + * @returns UserAccountData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(reader: ($protobuf.Reader | Uint8Array), length?: number): UserAccountData; + + /** + * Decodes a UserAccountData message from the specified reader or buffer, length delimited. + * @param reader Reader or buffer to decode from + * @returns UserAccountData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decodeDelimited(reader: ($protobuf.Reader | Uint8Array)): UserAccountData; + + /** + * Verifies a UserAccountData message. + * @param message Plain object to verify + * @returns `null` if valid, otherwise the reason why it is not + */ + public static verify(message: { [k: string]: any }): (string | null); + + /** + * Creates a UserAccountData message from a plain object. Also converts values to their respective internal types. + * @param object Plain object + * @returns UserAccountData + */ + public static fromObject(object: { [k: string]: any }): UserAccountData; + + /** + * Creates a plain object from a UserAccountData message. Also converts values to other types if specified. + * @param message UserAccountData + * @param [options] Conversion options + * @returns Plain object + */ + public static toObject(message: UserAccountData, options?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this UserAccountData to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; + + /** + * Gets the default type url for UserAccountData + * @param [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns The default type url + */ + public static getTypeUrl(typeUrlPrefix?: string): string; +} diff --git a/src/state-changes/utils/user_account.pb.js b/src/state-changes/utils/user_account.pb.js new file mode 100644 index 000000000..cdb6731d2 --- /dev/null +++ b/src/state-changes/utils/user_account.pb.js @@ -0,0 +1,488 @@ +/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/ +"use strict"; + +var $protobuf = require("protobufjs/minimal"); + +// Common aliases +var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + +$root.UserAccountData = (function () { + + /** + * Properties of a UserAccountData. + * @exports IUserAccountData + * @interface IUserAccountData + * @property {number|Long|null} [Nonce] UserAccountData Nonce + * @property {Uint8Array|null} [Balance] UserAccountData Balance + * @property {Uint8Array|null} [CodeHash] UserAccountData CodeHash + * @property {Uint8Array|null} [RootHash] UserAccountData RootHash + * @property {Uint8Array|null} [Address] UserAccountData Address + * @property {Uint8Array|null} [DeveloperReward] UserAccountData DeveloperReward + * @property {Uint8Array|null} [OwnerAddress] UserAccountData OwnerAddress + * @property {Uint8Array|null} [UserName] UserAccountData UserName + * @property {Uint8Array|null} [CodeMetadata] UserAccountData CodeMetadata + */ + + /** + * Constructs a new UserAccountData. + * @exports UserAccountData + * @classdesc Represents a UserAccountData. + * @implements IUserAccountData + * @constructor + * @param {IUserAccountData=} [properties] Properties to set + */ + function UserAccountData(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * UserAccountData Nonce. + * @member {number|Long} Nonce + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.Nonce = $util.Long ? $util.Long.fromBits(0, 0, true) : 0; + + /** + * UserAccountData Balance. + * @member {Uint8Array} Balance + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.Balance = $util.newBuffer([]); + + /** + * UserAccountData CodeHash. + * @member {Uint8Array} CodeHash + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.CodeHash = $util.newBuffer([]); + + /** + * UserAccountData RootHash. + * @member {Uint8Array} RootHash + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.RootHash = $util.newBuffer([]); + + /** + * UserAccountData Address. + * @member {Uint8Array} Address + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.Address = $util.newBuffer([]); + + /** + * UserAccountData DeveloperReward. + * @member {Uint8Array} DeveloperReward + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.DeveloperReward = $util.newBuffer([]); + + /** + * UserAccountData OwnerAddress. + * @member {Uint8Array} OwnerAddress + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.OwnerAddress = $util.newBuffer([]); + + /** + * UserAccountData UserName. + * @member {Uint8Array} UserName + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.UserName = $util.newBuffer([]); + + /** + * UserAccountData CodeMetadata. + * @member {Uint8Array} CodeMetadata + * @memberof UserAccountData + * @instance + */ + UserAccountData.prototype.CodeMetadata = $util.newBuffer([]); + + /** + * Creates a new UserAccountData instance using the specified properties. + * @function create + * @memberof UserAccountData + * @static + * @param {IUserAccountData=} [properties] Properties to set + * @returns {UserAccountData} UserAccountData instance + */ + UserAccountData.create = function create(properties) { + return new UserAccountData(properties); + }; + + /** + * Encodes the specified UserAccountData message. Does not implicitly {@link UserAccountData.verify|verify} messages. + * @function encode + * @memberof UserAccountData + * @static + * @param {IUserAccountData} message UserAccountData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UserAccountData.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.Nonce != null && Object.hasOwnProperty.call(message, "Nonce")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.Nonce); + if (message.Balance != null && Object.hasOwnProperty.call(message, "Balance")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.Balance); + if (message.CodeHash != null && Object.hasOwnProperty.call(message, "CodeHash")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.CodeHash); + if (message.RootHash != null && Object.hasOwnProperty.call(message, "RootHash")) + writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.RootHash); + if (message.Address != null && Object.hasOwnProperty.call(message, "Address")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.Address); + if (message.DeveloperReward != null && Object.hasOwnProperty.call(message, "DeveloperReward")) + writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.DeveloperReward); + if (message.OwnerAddress != null && Object.hasOwnProperty.call(message, "OwnerAddress")) + writer.uint32(/* id 7, wireType 2 =*/58).bytes(message.OwnerAddress); + if (message.UserName != null && Object.hasOwnProperty.call(message, "UserName")) + writer.uint32(/* id 8, wireType 2 =*/66).bytes(message.UserName); + if (message.CodeMetadata != null && Object.hasOwnProperty.call(message, "CodeMetadata")) + writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.CodeMetadata); + return writer; + }; + + /** + * Encodes the specified UserAccountData message, length delimited. Does not implicitly {@link UserAccountData.verify|verify} messages. + * @function encodeDelimited + * @memberof UserAccountData + * @static + * @param {IUserAccountData} message UserAccountData message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UserAccountData.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a UserAccountData message from the specified reader or buffer. + * @function decode + * @memberof UserAccountData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {UserAccountData} UserAccountData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UserAccountData.decode = function decode(reader, length, error) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.UserAccountData(); + while (reader.pos < end) { + var tag = reader.uint32(); + if (tag === error) + break; + switch (tag >>> 3) { + case 1: { + message.Nonce = reader.uint64(); + break; + } + case 2: { + message.Balance = reader.bytes(); + break; + } + case 3: { + message.CodeHash = reader.bytes(); + break; + } + case 4: { + message.RootHash = reader.bytes(); + break; + } + case 5: { + message.Address = reader.bytes(); + break; + } + case 6: { + message.DeveloperReward = reader.bytes(); + break; + } + case 7: { + message.OwnerAddress = reader.bytes(); + break; + } + case 8: { + message.UserName = reader.bytes(); + break; + } + case 9: { + message.CodeMetadata = reader.bytes(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a UserAccountData message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof UserAccountData + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {UserAccountData} UserAccountData + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UserAccountData.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a UserAccountData message. + * @function verify + * @memberof UserAccountData + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + UserAccountData.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.Nonce != null && message.hasOwnProperty("Nonce")) + if (!$util.isInteger(message.Nonce) && !(message.Nonce && $util.isInteger(message.Nonce.low) && $util.isInteger(message.Nonce.high))) + return "Nonce: integer|Long expected"; + if (message.Balance != null && message.hasOwnProperty("Balance")) + if (!(message.Balance && typeof message.Balance.length === "number" || $util.isString(message.Balance))) + return "Balance: buffer expected"; + if (message.CodeHash != null && message.hasOwnProperty("CodeHash")) + if (!(message.CodeHash && typeof message.CodeHash.length === "number" || $util.isString(message.CodeHash))) + return "CodeHash: buffer expected"; + if (message.RootHash != null && message.hasOwnProperty("RootHash")) + if (!(message.RootHash && typeof message.RootHash.length === "number" || $util.isString(message.RootHash))) + return "RootHash: buffer expected"; + if (message.Address != null && message.hasOwnProperty("Address")) + if (!(message.Address && typeof message.Address.length === "number" || $util.isString(message.Address))) + return "Address: buffer expected"; + if (message.DeveloperReward != null && message.hasOwnProperty("DeveloperReward")) + if (!(message.DeveloperReward && typeof message.DeveloperReward.length === "number" || $util.isString(message.DeveloperReward))) + return "DeveloperReward: buffer expected"; + if (message.OwnerAddress != null && message.hasOwnProperty("OwnerAddress")) + if (!(message.OwnerAddress && typeof message.OwnerAddress.length === "number" || $util.isString(message.OwnerAddress))) + return "OwnerAddress: buffer expected"; + if (message.UserName != null && message.hasOwnProperty("UserName")) + if (!(message.UserName && typeof message.UserName.length === "number" || $util.isString(message.UserName))) + return "UserName: buffer expected"; + if (message.CodeMetadata != null && message.hasOwnProperty("CodeMetadata")) + if (!(message.CodeMetadata && typeof message.CodeMetadata.length === "number" || $util.isString(message.CodeMetadata))) + return "CodeMetadata: buffer expected"; + return null; + }; + + /** + * Creates a UserAccountData message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof UserAccountData + * @static + * @param {Object.} object Plain object + * @returns {UserAccountData} UserAccountData + */ + UserAccountData.fromObject = function fromObject(object) { + if (object instanceof $root.UserAccountData) + return object; + var message = new $root.UserAccountData(); + if (object.Nonce != null) + if ($util.Long) + (message.Nonce = $util.Long.fromValue(object.Nonce)).unsigned = true; + else if (typeof object.Nonce === "string") + message.Nonce = parseInt(object.Nonce, 10); + else if (typeof object.Nonce === "number") + message.Nonce = object.Nonce; + else if (typeof object.Nonce === "object") + message.Nonce = new $util.LongBits(object.Nonce.low >>> 0, object.Nonce.high >>> 0).toNumber(true); + if (object.Balance != null) + if (typeof object.Balance === "string") + $util.base64.decode(object.Balance, message.Balance = $util.newBuffer($util.base64.length(object.Balance)), 0); + else if (object.Balance.length >= 0) + message.Balance = object.Balance; + if (object.CodeHash != null) + if (typeof object.CodeHash === "string") + $util.base64.decode(object.CodeHash, message.CodeHash = $util.newBuffer($util.base64.length(object.CodeHash)), 0); + else if (object.CodeHash.length >= 0) + message.CodeHash = object.CodeHash; + if (object.RootHash != null) + if (typeof object.RootHash === "string") + $util.base64.decode(object.RootHash, message.RootHash = $util.newBuffer($util.base64.length(object.RootHash)), 0); + else if (object.RootHash.length >= 0) + message.RootHash = object.RootHash; + if (object.Address != null) + if (typeof object.Address === "string") + $util.base64.decode(object.Address, message.Address = $util.newBuffer($util.base64.length(object.Address)), 0); + else if (object.Address.length >= 0) + message.Address = object.Address; + if (object.DeveloperReward != null) + if (typeof object.DeveloperReward === "string") + $util.base64.decode(object.DeveloperReward, message.DeveloperReward = $util.newBuffer($util.base64.length(object.DeveloperReward)), 0); + else if (object.DeveloperReward.length >= 0) + message.DeveloperReward = object.DeveloperReward; + if (object.OwnerAddress != null) + if (typeof object.OwnerAddress === "string") + $util.base64.decode(object.OwnerAddress, message.OwnerAddress = $util.newBuffer($util.base64.length(object.OwnerAddress)), 0); + else if (object.OwnerAddress.length >= 0) + message.OwnerAddress = object.OwnerAddress; + if (object.UserName != null) + if (typeof object.UserName === "string") + $util.base64.decode(object.UserName, message.UserName = $util.newBuffer($util.base64.length(object.UserName)), 0); + else if (object.UserName.length >= 0) + message.UserName = object.UserName; + if (object.CodeMetadata != null) + if (typeof object.CodeMetadata === "string") + $util.base64.decode(object.CodeMetadata, message.CodeMetadata = $util.newBuffer($util.base64.length(object.CodeMetadata)), 0); + else if (object.CodeMetadata.length >= 0) + message.CodeMetadata = object.CodeMetadata; + return message; + }; + + /** + * Creates a plain object from a UserAccountData message. Also converts values to other types if specified. + * @function toObject + * @memberof UserAccountData + * @static + * @param {UserAccountData} message UserAccountData + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + UserAccountData.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.Nonce = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.Nonce = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.Balance = ""; + else { + object.Balance = []; + if (options.bytes !== Array) + object.Balance = $util.newBuffer(object.Balance); + } + if (options.bytes === String) + object.CodeHash = ""; + else { + object.CodeHash = []; + if (options.bytes !== Array) + object.CodeHash = $util.newBuffer(object.CodeHash); + } + if (options.bytes === String) + object.RootHash = ""; + else { + object.RootHash = []; + if (options.bytes !== Array) + object.RootHash = $util.newBuffer(object.RootHash); + } + if (options.bytes === String) + object.Address = ""; + else { + object.Address = []; + if (options.bytes !== Array) + object.Address = $util.newBuffer(object.Address); + } + if (options.bytes === String) + object.DeveloperReward = ""; + else { + object.DeveloperReward = []; + if (options.bytes !== Array) + object.DeveloperReward = $util.newBuffer(object.DeveloperReward); + } + if (options.bytes === String) + object.OwnerAddress = ""; + else { + object.OwnerAddress = []; + if (options.bytes !== Array) + object.OwnerAddress = $util.newBuffer(object.OwnerAddress); + } + if (options.bytes === String) + object.UserName = ""; + else { + object.UserName = []; + if (options.bytes !== Array) + object.UserName = $util.newBuffer(object.UserName); + } + if (options.bytes === String) + object.CodeMetadata = ""; + else { + object.CodeMetadata = []; + if (options.bytes !== Array) + object.CodeMetadata = $util.newBuffer(object.CodeMetadata); + } + } + if (message.Nonce != null && message.hasOwnProperty("Nonce")) + if (typeof message.Nonce === "number") + object.Nonce = options.longs === String ? String(message.Nonce) : message.Nonce; + else + object.Nonce = options.longs === String ? $util.Long.prototype.toString.call(message.Nonce) : options.longs === Number ? new $util.LongBits(message.Nonce.low >>> 0, message.Nonce.high >>> 0).toNumber(true) : message.Nonce; + if (message.Balance != null && message.hasOwnProperty("Balance")) + object.Balance = options.bytes === String ? $util.base64.encode(message.Balance, 0, message.Balance.length) : options.bytes === Array ? Array.prototype.slice.call(message.Balance) : message.Balance; + if (message.CodeHash != null && message.hasOwnProperty("CodeHash")) + object.CodeHash = options.bytes === String ? $util.base64.encode(message.CodeHash, 0, message.CodeHash.length) : options.bytes === Array ? Array.prototype.slice.call(message.CodeHash) : message.CodeHash; + if (message.RootHash != null && message.hasOwnProperty("RootHash")) + object.RootHash = options.bytes === String ? $util.base64.encode(message.RootHash, 0, message.RootHash.length) : options.bytes === Array ? Array.prototype.slice.call(message.RootHash) : message.RootHash; + if (message.Address != null && message.hasOwnProperty("Address")) + object.Address = options.bytes === String ? $util.base64.encode(message.Address, 0, message.Address.length) : options.bytes === Array ? Array.prototype.slice.call(message.Address) : message.Address; + if (message.DeveloperReward != null && message.hasOwnProperty("DeveloperReward")) + object.DeveloperReward = options.bytes === String ? $util.base64.encode(message.DeveloperReward, 0, message.DeveloperReward.length) : options.bytes === Array ? Array.prototype.slice.call(message.DeveloperReward) : message.DeveloperReward; + if (message.OwnerAddress != null && message.hasOwnProperty("OwnerAddress")) + object.OwnerAddress = options.bytes === String ? $util.base64.encode(message.OwnerAddress, 0, message.OwnerAddress.length) : options.bytes === Array ? Array.prototype.slice.call(message.OwnerAddress) : message.OwnerAddress; + if (message.UserName != null && message.hasOwnProperty("UserName")) + object.UserName = options.bytes === String ? $util.base64.encode(message.UserName, 0, message.UserName.length) : options.bytes === Array ? Array.prototype.slice.call(message.UserName) : message.UserName; + if (message.CodeMetadata != null && message.hasOwnProperty("CodeMetadata")) + object.CodeMetadata = options.bytes === String ? $util.base64.encode(message.CodeMetadata, 0, message.CodeMetadata.length) : options.bytes === Array ? Array.prototype.slice.call(message.CodeMetadata) : message.CodeMetadata; + return object; + }; + + /** + * Converts this UserAccountData to JSON. + * @function toJSON + * @memberof UserAccountData + * @instance + * @returns {Object.} JSON object + */ + UserAccountData.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for UserAccountData + * @function getTypeUrl + * @memberof UserAccountData + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + UserAccountData.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/UserAccountData"; + }; + + return UserAccountData; +})(); + +module.exports = $root; diff --git a/src/state-changes/utils/user_account.proto b/src/state-changes/utils/user_account.proto new file mode 100644 index 000000000..d0780866e --- /dev/null +++ b/src/state-changes/utils/user_account.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +message UserAccountData { + uint64 Nonce = 1; + bytes Balance = 2; // big.Int in Go -> bytes on the wire + bytes CodeHash = 3; + bytes RootHash = 4; + bytes Address = 5; + bytes DeveloperReward = 6; // big.Int in Go -> bytes on the wire + bytes OwnerAddress = 7; + bytes UserName = 8; + bytes CodeMetadata = 9; +} diff --git a/src/test/unit/controllers/accounts.controller.spec.ts b/src/test/unit/controllers/accounts.controller.spec.ts index ab99de595..b163541fc 100644 --- a/src/test/unit/controllers/accounts.controller.spec.ts +++ b/src/test/unit/controllers/accounts.controller.spec.ts @@ -602,5 +602,3 @@ describe('AccountController', () => { return address.substring(0, desiredLength + 'erd1'.length); } }); - - diff --git a/src/test/unit/controllers/services.mock/account.services.mock.ts b/src/test/unit/controllers/services.mock/account.services.mock.ts index df379edfd..b3345e94b 100644 --- a/src/test/unit/controllers/services.mock/account.services.mock.ts +++ b/src/test/unit/controllers/services.mock/account.services.mock.ts @@ -78,6 +78,7 @@ export const mockApiConfigService = () => ({ getMediaUrl: jest.fn().mockReturnValue(''), isElasticCircuitBreakerEnabled: jest.fn().mockReturnValue(false), getElasticCircuitBreakerConfig: jest.fn().mockReturnValue({}), + getDatabaseUrl: jest.fn().mockReturnValue(''), getConfig: jest.fn(), }); diff --git a/src/test/unit/services/state-changes.consumer.spec.ts b/src/test/unit/services/state-changes.consumer.spec.ts new file mode 100644 index 000000000..e67fdbbe0 --- /dev/null +++ b/src/test/unit/services/state-changes.consumer.spec.ts @@ -0,0 +1,581 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { StateChangesConsumerService } from 'src/state-changes/state.changes.consumer.service'; +import { CacheService } from '@multiversx/sdk-nestjs-cache'; +import { AccountDetailsRepository, EsdtDetailsRepository } from 'src/common/indexer/db'; +import { ApiConfigService } from 'src/common/api-config/api.config.service'; +import { ClientProxy } from '@nestjs/microservices'; +import { StateChangesDecoder } from 'src/state-changes/utils/state-changes.decoder'; +import { ESDTType } from 'src/state-changes/entities'; +import { TokenType } from 'src/common/indexer/entities'; +import { NftType } from 'src/endpoints/nfts/entities/nft.type'; +import { NftSubType } from 'src/endpoints/nfts/entities/nft.sub.type'; +import { AddressUtils } from '@multiversx/sdk-nestjs-common'; + +jest.mock('src/state-changes/utils/state-changes.decoder'); +jest.mock('@multiversx/sdk-nestjs-cache'); +jest.mock('src/common/indexer/db'); +jest.mock('@nestjs/microservices'); +jest.mock('@multiversx/sdk-nestjs-common', () => ({ + AddressUtils: { + isSmartContractAddress: jest.fn(), + }, + TokenUtils: { + isToken: jest.fn(), + }, + OriginLogger: jest.fn().mockImplementation(() => ({ + log: jest.fn(), + error: jest.fn(), + })), + ComplexityEstimation: jest.fn().mockImplementation(() => () => { }), + SwaggerUtils: { + amountPropertyOptions: jest.fn().mockReturnValue({}), + }, + Constants: { + oneSecond: jest.fn(() => 1000), + oneMinute: jest.fn(() => 60 * 1000), + oneHour: jest.fn(() => 60 * 60 * 1000), + oneDay: jest.fn(() => 24 * 60 * 60 * 1000), + oneWeek: jest.fn(() => 7 * 24 * 60 * 60 * 1000), + oneMonth: jest.fn(() => 30 * 24 * 60 * 60 * 1000), + }, +})); +jest.mock('src/common/indexer/db', () => ({ + AccountDetailsRepository: jest.fn(), + AccountDetails: jest.fn().mockImplementation((data) => data), + EsdtDetailsRepository: jest.fn(), + EsdtDetails: jest.fn().mockImplementation((data) => data), +})); + +describe('StateChangesConsumerService', () => { + let service: StateChangesConsumerService; + let cacheService: jest.Mocked; + let accountRepo: jest.Mocked; + let esdtRepo: jest.Mocked; + let clientProxy: jest.Mocked; + let apiConfig: jest.Mocked; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + //@ts-ignore + providers: [ + StateChangesConsumerService, + { + provide: CacheService, + useValue: { + setRemote: jest.fn(), + setManyRemote: jest.fn(), + deleteManyRemote: jest.fn(), + getManyLocal: jest.fn(), + getManyRemote: jest.fn(), + setManyLocal: jest.fn(), + }, + }, + { + provide: AccountDetailsRepository, + useValue: { + updateAccounts: jest.fn(), + }, + }, + { + provide: EsdtDetailsRepository, + useValue: { + updateEsdts: jest.fn(), + }, + }, + { + provide: ApiConfigService, + useValue: { + getMetaChainShardId: jest.fn().mockReturnValue(4294967295), + isEsdtComputationEnabled: jest.fn().mockReturnValue(false), + }, + }, + { + provide: 'PUBSUB_SERVICE', + useValue: { + emit: jest.fn(), + }, + }, + ], + }).compile(); + + service = module.get(StateChangesConsumerService); + cacheService = module.get(CacheService); + accountRepo = module.get(AccountDetailsRepository); + esdtRepo = module.get(EsdtDetailsRepository); + clientProxy = module.get('PUBSUB_SERVICE'); + apiConfig = module.get(ApiConfigService); + }); + + afterEach(() => jest.clearAllMocks()); + + describe('parseCodeMetadata', () => { + it('should return empty object if hexStr is missing', () => { + expect(service['parseCodeMetadata']('erd1...', undefined)).toEqual({}); + }); + + it('should parse non-smart contract guarded flag', () => { + (AddressUtils.isSmartContractAddress as jest.Mock).mockReturnValue(false); + const result = service['parseCodeMetadata']('erd1useraddress', '0800'); + expect(result).toEqual({ isGuarded: true }); + }); + + it('should parse smart contract flags', () => { + (AddressUtils.isSmartContractAddress as jest.Mock).mockReturnValue(true); + const result = service['parseCodeMetadata']('erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu', '0106'); + expect(result).toEqual({ + isUpgradeable: true, + isReadable: false, + isPayable: true, + isPayableBySmartContract: true, + }); + }); + }); + + describe('parseEsdtType', () => { + it('should map Fungible to TokenType.FungibleESDT', () => { + expect(service['parseEsdtType'](ESDTType.Fungible)).toBe(TokenType.FungibleESDT); + }); + + it('should map NonFungible to NftType.NonFungibleESDT', () => { + expect(service['parseEsdtType'](ESDTType.NonFungible)).toBe(NftType.NonFungibleESDT); + }); + + it('should map MetaFungible to NftType.MetaESDT', () => { + expect(service['parseEsdtType'](ESDTType.MetaFungible)).toBe(NftType.MetaESDT); + }); + }); + + describe('parseEsdtSubtype', () => { + it('should map NonFungibleV2 to NftSubType.NonFungibleESDTv2', () => { + expect(service['parseEsdtSubtype'](ESDTType.NonFungibleV2)).toBe(NftSubType.NonFungibleESDTv2); + }); + + it('should map DynamicSFT to NftSubType.DynamicSemiFungibleESDT', () => { + expect(service['parseEsdtSubtype'](ESDTType.DynamicSFT)).toBe(NftSubType.DynamicSemiFungibleESDT); + }); + }); + + describe('isStateChangesConsumerHealthy', () => { + it('should return false if any timestamp missing', async () => { + cacheService.getManyLocal.mockReturnValue([undefined, 1, 2]); + const result = await StateChangesConsumerService.isStateChangesConsumerHealthy(cacheService, 10000); + expect(result).toBe(false); + }); + + it('should return true if timestamps within threshold', async () => { + const now = Date.now(); + cacheService.getManyLocal.mockReturnValue([now - 5000, now - 3000, now - 4000]); + const result = await StateChangesConsumerService.isStateChangesConsumerHealthy(cacheService, 10000); + expect(result).toBe(true); + }); + + it('should return false if timestamps too old', async () => { + const now = Date.now(); + cacheService.getManyLocal.mockReturnValue([now - 60000, now - 70000, now - 80000]); + const result = await StateChangesConsumerService.isStateChangesConsumerHealthy(cacheService, 10000); + expect(result).toBe(false); + }); + + it('should fallback to remote cache if local missing and succeed', async () => { + const now = Date.now(); + cacheService.getManyLocal.mockReturnValue([null, null, null]); + cacheService.getManyRemote.mockResolvedValue([now - 2000, now - 3000, now - 4000]); + const result = await StateChangesConsumerService.isStateChangesConsumerHealthy(cacheService, 10000); + expect(result).toBe(true); + expect(cacheService.setManyLocal).toHaveBeenCalled(); + }); + }); + + describe('consumeEvents', () => { + it('should skip meta chain shard', async () => { + const mockBlock = { shardID: apiConfig.getMetaChainShardId(), hash: 'abc', timestampMs: Date.now() } as any; + await service.consumeEvents(mockBlock); + expect(StateChangesDecoder.decodeStateChangesFinal).not.toHaveBeenCalled(); + }); + + it('should decode and update accounts', async () => { + const mockBlock = { shardID: 1, hash: 'block1', timestampMs: Date.now(), stateAccessesPerAccounts: {} } as any; + (StateChangesDecoder.decodeStateChangesFinal as jest.Mock).mockReturnValue({ + erd1abc: { accountState: { address: 'erd1abc' }, esdtState: {}, accountChanges: {}, isNewAccount: false }, + }); + const spyTransform = jest.spyOn(service, 'transformFinalStatesToDbFormat'); + const spyUpdate = jest.spyOn(service, 'updateAccounts').mockResolvedValue(undefined); + await service.consumeEvents(mockBlock); + expect(StateChangesDecoder.decodeStateChangesFinal).toHaveBeenCalled(); + expect(spyTransform).toHaveBeenCalled(); + expect(spyUpdate).toHaveBeenCalled(); + expect(cacheService.setRemote).toHaveBeenCalled(); + }); + + it('should log and throw on error', async () => { + const mockBlock = { shardID: 1, hash: 'block1', timestampMs: Date.now() } as any; + jest.spyOn(service, 'decodeStateChangesFinal').mockImplementation(() => { throw new Error('test'); }); + await expect(service.consumeEvents(mockBlock)).rejects.toThrow('test'); + }); + }); + + describe('updateAccounts', () => { + it('should update non-contract accounts and set cache', async () => { + (AddressUtils.isSmartContractAddress as jest.Mock).mockReturnValue(false); + const mockAccounts = [{ address: 'erd1', balance: '10' }]; + const mockEsdts = [{ identifier: 'id-123456', balance: '10' }]; + await service['updateAccounts'](mockAccounts as any, mockEsdts as any); + expect(accountRepo.updateAccounts).toHaveBeenCalled(); + expect(esdtRepo.updateEsdts).toHaveBeenCalled(); + expect(cacheService.setManyRemote).toHaveBeenCalled(); + expect(clientProxy.emit).toHaveBeenCalled(); + }); + + it('should delete contract cache keys', async () => { + (AddressUtils.isSmartContractAddress as jest.Mock).mockReturnValue(true); + const mockAccounts = [{ address: 'erd1sc', balance: '0' }]; + const mockEsdts = [{ identifier: 'id-123456', balance: '10' }]; + await service['updateAccounts'](mockAccounts as any, mockEsdts as any); + expect(cacheService.deleteManyRemote).toHaveBeenCalled(); + expect(clientProxy.emit).toHaveBeenCalled(); + }); + }); + + describe('transformFinalStatesToDbFormat', () => { + it('should transform state changes into AccountDetails and ignore ESDTs', () => { + const mockInput = + { + erd1qqqqqqqqqqqqqpgqvg8r5yavkyhu6rmmkgqzgsduzheg2fk7v5ysrypdex: { + accountState: { + nonce: 0, + balance: '6213923288818146107158', + developerReward: '7695868166885300000', + address: 'erd1qqqqqqqqqqqqqpgqvg8r5yavkyhu6rmmkgqzgsduzheg2fk7v5ysrypdex', + ownerAddress: 'erd1rc5p5drg26vggn6jx9puv6xlgka5n6ajm6cer554tzguwfm6v5ys2pr3pc', + codeHash: 'hRkRk4eX3AxvdJgLHruGrel+Zb0uHudVXBHqWvfvz4Q=', + rootHash: 'CKhf02sZIbMYtII8VbKqiLgTDEr0treTXEqIgHb1l4g=', + codeMetadata: '0500', + }, + esdtState: { + Fungible: [], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: false, + balanceChanged: true, + codeHashChanged: false, + rootHashChanged: true, + developerRewardChanged: true, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }, + erd1qqqqqqqqqqqqqpgqjwls7l4jf9qwafnxual6nadaak66g5jjeyvs9dswkt: { + accountState: { + nonce: 0, + balance: '126502242682468246846', + developerReward: '2472015964236000000', + address: 'erd1qqqqqqqqqqqqqpgqjwls7l4jf9qwafnxual6nadaak66g5jjeyvs9dswkt', + ownerAddress: 'erd1mmjkmtlz4cwl3svqtu4u9yfp3m8wqpqdykmterrleltpt4eaeyvsa68xa7', + codeHash: 'hcDhkiRq8PB5C3g5B7OcMZ020WOj+AuOOndgSDMBZ48=', + rootHash: 'bjwTHfuhx0bs3OJFnvcb6pcTWspG9cb370yuqVbKbQo=', + codeMetadata: '0100', + }, + esdtState: { + Fungible: [], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: false, + balanceChanged: false, + codeHashChanged: false, + rootHashChanged: true, + developerRewardChanged: true, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }, + erd1vt2qedvltqvrar072ny88wh7vgxq9xvxmyqm4nf8qkzpwj6ncy5sjtgj90: { + accountState: { + nonce: 43766, + balance: '59732371650000000000', + developerReward: '0', + address: 'erd1vt2qedvltqvrar072ny88wh7vgxq9xvxmyqm4nf8qkzpwj6ncy5sjtgj90', + rootHash: 's9P9Do2C9v8r3MqG3I3MkotuYpEA1qt8jNiRCE5ULBo=', + }, + esdtState: { + Fungible: [], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: true, + balanceChanged: true, + codeHashChanged: false, + rootHashChanged: false, + developerRewardChanged: false, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }, + erd1mmjkmtlz4cwl3svqtu4u9yfp3m8wqpqdykmterrleltpt4eaeyvsa68xa7: { + accountState: { + nonce: 306369, + balance: '391457061919320000000', + developerReward: '0', + address: 'erd1mmjkmtlz4cwl3svqtu4u9yfp3m8wqpqdykmterrleltpt4eaeyvsa68xa7', + rootHash: 'fV3JuZDrwZ8TbnlawkHGYYp1bQX0fTgefUzU7xEYLh8=', + }, + esdtState: { + Fungible: [], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: true, + balanceChanged: true, + codeHashChanged: false, + rootHashChanged: false, + developerRewardChanged: false, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }, + }; + const mockShardId = 1; + const mockBlockTimestampMs = 1762356608000; + const expectedResult = [ + { + address: 'erd1qqqqqqqqqqqqqpgqvg8r5yavkyhu6rmmkgqzgsduzheg2fk7v5ysrypdex', + balance: '6213923288818146107158', + nonce: 0, + timestampMs: 1762356608000, + timestamp: 1762356608, + shard: 1, + developerReward: '7695868166885300000', + ownerAddress: 'erd1rc5p5drg26vggn6jx9puv6xlgka5n6ajm6cer554tzguwfm6v5ys2pr3pc', + codeHash: 'hRkRk4eX3AxvdJgLHruGrel+Zb0uHudVXBHqWvfvz4Q=', + rootHash: 'CKhf02sZIbMYtII8VbKqiLgTDEr0treTXEqIgHb1l4g=', + isUpgradeable: true, + isReadable: true, + isPayable: false, + isPayableBySmartContract: false, + }, + { + address: 'erd1qqqqqqqqqqqqqpgqjwls7l4jf9qwafnxual6nadaak66g5jjeyvs9dswkt', + balance: '126502242682468246846', + nonce: 0, + timestampMs: 1762356608000, + timestamp: 1762356608, + shard: 1, + developerReward: '2472015964236000000', + ownerAddress: 'erd1mmjkmtlz4cwl3svqtu4u9yfp3m8wqpqdykmterrleltpt4eaeyvsa68xa7', + codeHash: 'hcDhkiRq8PB5C3g5B7OcMZ020WOj+AuOOndgSDMBZ48=', + rootHash: 'bjwTHfuhx0bs3OJFnvcb6pcTWspG9cb370yuqVbKbQo=', + isUpgradeable: true, + isReadable: false, + isPayable: false, + isPayableBySmartContract: false, + }, + { + address: 'erd1vt2qedvltqvrar072ny88wh7vgxq9xvxmyqm4nf8qkzpwj6ncy5sjtgj90', + balance: '59732371650000000000', + nonce: 43766, + timestampMs: 1762356608000, + timestamp: 1762356608, + shard: 1, + developerReward: '0', + rootHash: 's9P9Do2C9v8r3MqG3I3MkotuYpEA1qt8jNiRCE5ULBo=', + }, + { + address: 'erd1mmjkmtlz4cwl3svqtu4u9yfp3m8wqpqdykmterrleltpt4eaeyvsa68xa7', + balance: '391457061919320000000', + nonce: 306369, + timestampMs: 1762356608000, + timestamp: 1762356608, + shard: 1, + developerReward: '0', + rootHash: 'fV3JuZDrwZ8TbnlawkHGYYp1bQX0fTgefUzU7xEYLh8=', + }, + ]; + const { transformedAccounts, transformedEsdts } = service['transformFinalStatesToDbFormat']( + mockInput, + mockShardId, + mockBlockTimestampMs, + ); + expect(transformedAccounts).toEqual(expectedResult); + expect(transformedEsdts.length).toBe(0); + }); + + it('should transform state changes into AccountDetails and ESDT details', () => { + (apiConfig.isEsdtComputationEnabled as jest.Mock).mockReturnValue(true); + const mockInput = + { + erd1vhfuv9qznn59vlasthdgsp7pzc99snzvchvcrjzhgn3cdequ7jxsvwtu50: { + accountState: { + nonce: 163, + balance: '1022184909233299999998', + developerReward: '0', + address: 'erd1vhfuv9qznn59vlasthdgsp7pzc99snzvchvcrjzhgn3cdequ7jxsvwtu50', + rootHash: 'i6mdSsTadb0E0H17P7rCPCTmQrtu8b4WDT20ncfVRz4=', + }, + esdtState: { + Fungible: [ + { + identifier: 'ACCEPTED-bc0f6e', + nonce: '0', + type: 0, + value: '9920000000', + propertiesHex: '', + reservedHex: '', + tokenMetaData: null, + }, + ], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: false, + balanceChanged: false, + codeHashChanged: false, + rootHashChanged: true, + developerRewardChanged: false, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }, + erd107uaynrvf80g4zuym4fqqh5pqzvaczdryj49zr2qew57wqe3mvusupj8xh: { + accountState: { + nonce: 137, + balance: '1050718027978784480311', + developerReward: '0', + address: 'erd107uaynrvf80g4zuym4fqqh5pqzvaczdryj49zr2qew57wqe3mvusupj8xh', + rootHash: 'U0Q3PEXqxQNGQZ07/NVNVfFlxRdyzzY04/mzEWc5czs=', + }, + esdtState: { + Fungible: [ + { + identifier: 'ACCEPTED-bc0f6e', + nonce: '0', + type: 0, + value: '49980000000', + propertiesHex: '', + reservedHex: '', + tokenMetaData: null, + }, + ], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: true, + balanceChanged: true, + codeHashChanged: false, + rootHashChanged: true, + developerRewardChanged: false, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }, + }; + + const mockShardId = 1; + const mockBlockTimestampMs = 1763379962000; + const accountsExpectedResults = [ + { + address: 'erd1vhfuv9qznn59vlasthdgsp7pzc99snzvchvcrjzhgn3cdequ7jxsvwtu50', + balance: '1022184909233299999998', + nonce: 163, + timestampMs: 1763379962000, + timestamp: 1763379962, + shard: 1, + developerReward: '0', + rootHash: 'i6mdSsTadb0E0H17P7rCPCTmQrtu8b4WDT20ncfVRz4=', + }, + { + address: 'erd107uaynrvf80g4zuym4fqqh5pqzvaczdryj49zr2qew57wqe3mvusupj8xh', + balance: '1050718027978784480311', + nonce: 137, + timestampMs: 1763379962000, + timestamp: 1763379962, + shard: 1, + developerReward: '0', + rootHash: 'U0Q3PEXqxQNGQZ07/NVNVfFlxRdyzzY04/mzEWc5czs=', + }, + ]; + + const esdtsExpectedResults = [ + { + address: 'erd1vhfuv9qznn59vlasthdgsp7pzc99snzvchvcrjzhgn3cdequ7jxsvwtu50', + identifier: 'ACCEPTED-bc0f6e', + balance: '9920000000', + }, + { + address: 'erd107uaynrvf80g4zuym4fqqh5pqzvaczdryj49zr2qew57wqe3mvusupj8xh', + identifier: 'ACCEPTED-bc0f6e', + balance: '49980000000', + }, + ]; + + const { transformedAccounts, transformedEsdts } = service['transformFinalStatesToDbFormat']( + mockInput, + mockShardId, + mockBlockTimestampMs, + ); + expect(transformedAccounts).toEqual(accountsExpectedResults); + expect(transformedEsdts).toEqual(esdtsExpectedResults); + }); + + it('should skip if no accountState', () => { + const { transformedAccounts, transformedEsdts } = service['transformFinalStatesToDbFormat']({ erd1: {} } as any, 0, Date.now()); + expect(transformedAccounts.length).toBe(0); + expect(transformedEsdts.length).toBe(0); + }); + }); + + describe('deleteLocalCache', () => { + it('should emit deleteCacheKeys event', () => { + service['deleteLocalCache'](['key1', 'key2']); + expect(clientProxy.emit).toHaveBeenCalledWith('deleteCacheKeys', ['key1', 'key2']); + }); + }); +}); diff --git a/src/test/unit/utils/state-changes.decoder.spec.ts b/src/test/unit/utils/state-changes.decoder.spec.ts new file mode 100644 index 000000000..997e6b3a8 --- /dev/null +++ b/src/test/unit/utils/state-changes.decoder.spec.ts @@ -0,0 +1,218 @@ +import { StateChangesDecoder } from 'src/state-changes/utils/state-changes.decoder'; +import { AccountChangesRaw, DataTrieChangeOperation, StateAccessOperation } from 'src/state-changes/entities'; + +describe('StateChangesDecoder', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('isSystemContractAddress', () => { + it('should detect system addresses correctly', () => { + const address = 'erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqllls0lczs7'; + expect(StateChangesDecoder.isSystemContractAddress(address)).toBe(true); + expect(StateChangesDecoder.isSystemContractAddress('erd1random')).toBe(false); + }); + }); + + describe('decodeMxSignMagBigInt', () => { + it('should decode zero buffer', () => { + expect(StateChangesDecoder['decodeMxSignMagBigInt'](new Uint8Array([0x00, 0x00]))).toBe(BigInt(0)); + }); + + it('should decode positive big int', () => { + const result = StateChangesDecoder['decodeMxSignMagBigInt'](new Uint8Array([0x00, 0x01, 0x02])); + expect(result).toBe(BigInt(258)); + }); + + it('should decode negative big int', () => { + const result = StateChangesDecoder['decodeMxSignMagBigInt'](new Uint8Array([0x01, 0x01])); + expect(result).toBe(BigInt(-1)); + }); + + it('should decode fallback magnitude', () => { + const result = StateChangesDecoder['decodeMxSignMagBigInt'](new Uint8Array([0x05])); + expect(result).toBe(BigInt(5)); + }); + }); + + describe('getDecodedUserAccountData', () => { + it('should return null for invalid base64', () => { + const result = StateChangesDecoder['getDecodedUserAccountData']('invalidbase64'); + expect(result).toBeNull(); + }); + + it('should decode valid UserAccountData', () => { + const base64Value = "EgoABtuSP3tqxyU+GiCFwOGSJGrw8HkLeDkHs5wxnTbRY6P4C446d2BIMwFnjyIgo7jh8DROSNY3jtZL6vVOdbo/PP+O+6q/7dB+r0GfmDwqIAAAAAAAAAAABQCTvw9+sklA7qZm53+p9b3ttaRSUskZMgkAIko5RBEBXgA6IN7lba/irh34wYBfK8KRIY7O4AQNJba8jH/P1hXXPckZSgIBAA=="; + const result = StateChangesDecoder['getDecodedUserAccountData'](base64Value); + + const expectedResult = { + nonce: 0, + balance: '126502242682468246846', + developerReward: '2470850310072000000', + address: 'erd1qqqqqqqqqqqqqpgqjwls7l4jf9qwafnxual6nadaak66g5jjeyvs9dswkt', + ownerAddress: 'erd1mmjkmtlz4cwl3svqtu4u9yfp3m8wqpqdykmterrleltpt4eaeyvsa68xa7', + codeHash: 'hcDhkiRq8PB5C3g5B7OcMZ020WOj+AuOOndgSDMBZ48=', + rootHash: 'o7jh8DROSNY3jtZL6vVOdbo/PP+O+6q/7dB+r0GfmDw=', + codeMetadata: '0100', + }; + expect(result).toHaveProperty('nonce', expectedResult.nonce); + expect(result).toHaveProperty('balance', expectedResult.balance); + expect(result).toHaveProperty('developerReward', expectedResult.developerReward); + expect(result).toHaveProperty('address', expectedResult.address); + expect(result).toHaveProperty('ownerAddress', expectedResult.ownerAddress); + expect(result).toHaveProperty('codeHash', expectedResult.codeHash); + expect(result).toHaveProperty('rootHash', expectedResult.rootHash); + expect(result).toHaveProperty('codeMetadata', expectedResult.codeMetadata); + }); + }); + + describe('decodeAccountChanges', () => { + it('should decode all flags correctly', () => { + const result = StateChangesDecoder['decodeAccountChanges']( + AccountChangesRaw.BalanceChanged | AccountChangesRaw.RootHashChanged + ); + expect(result.balanceChanged).toBe(true); + expect(result.rootHashChanged).toBe(true); + expect(result.nonceChanged).toBe(false); + }); + + it('should handle undefined flags', () => { + const result = StateChangesDecoder['decodeAccountChanges'](undefined); + expect(result.balanceChanged).toBe(false); + }); + }); + + describe('getDecodedEsdtData', () => { + it('should return null for invalid key prefix', () => { + const dataTrieChange = { key: Buffer.from('BADKEY').toString('base64'), val: 'AA==', version: 1 }; + const result = StateChangesDecoder['getDecodedEsdtData']('erd1test', dataTrieChange as any); + expect(result).toBeNull(); + }); + + it('should decode valid ESDT data', () => { + const expectedResult = { + identifier: 'MEX-a659d0', + nonce: '0', + type: 0, + value: '135399426293137262324524632', + propertiesHex: '', + reservedHex: '', + tokenMetaData: null, + }; + + const dataTrieChange = { + type: 1, + key: 'RUxST05EZXNkdE1FWC1hNjU5ZDA=', + val: 'EgwAb//xm2Vec+YQplg=', + version: 1, + operation: DataTrieChangeOperation.NotDelete, + }; + + const result = StateChangesDecoder['getDecodedEsdtData']('erd150sh7scpm4q7tdtntte975kt0cgg3r4exf8mtwurfradguzxzuqsahzma8', dataTrieChange as any); + expect(result).toEqual(expectedResult); + }); + }); + + describe('isNewAccount', () => { + it('should detect new account correctly', () => { + const result = StateChangesDecoder['isNewAccount']({ + accountChanges: undefined, + operation: StateAccessOperation.SaveAccount, + } as any); + expect(result).toBe(true); + }); + + it('should detect existing account correctly', () => { + const result = StateChangesDecoder['isNewAccount']({ + accountChanges: 1, + operation: 0, + } as any); + expect(result).toBe(false); + }); + }); + + describe('getAccountFinalState', () => { + it('should get final account state from block state accesses', () => { + const mockAccountStateAccesses = [ + { + type: 1, + index: 1, + txHash: 'zvAPJGf0O/fbqGo5eq9kqs2AguViaEYvyEZmiTQDDwE=', + mainTrieKey: 'AAAAAAAAAAAFAHStkhZzzH/1idZo4AjPvzAQydYdiBc=', + mainTrieVal: 'EgIAABog9S1Hs2tTj7zA+JLDTnD29ncfZtRsxevT36irfG9yrWIiIBEmI7nptDIBxcYWKgu6Jou5jHnvmOIOj1vjVDHFPMX3KiAAAAAAAAAAAAUAdK2SFnPMf/WJ1mjgCM+/MBDJ1h2IFzIIACD1dWNCKQA6IE+qi6TxMzNnwNuQ8fhDq6VBoT9FgTUSb6bVix2DrIgXSgIFAA==', + operation: 2, + dataTrieChanges: [ + { + type: 1, + key: 'RUxST05EZXNkdEZPWFNZLTg2ZWNmZQ==', + val: 'EgkADeC2s6dkAAA=', + version: 1, + operation: 0, + }, + { + type: 1, + key: 'RUxST05EZXNkdEZPWFNZLTg2ZWNmZQ==', + val: 'EgkADeC2s6dkAAA=', + version: 1, + operation: 1, + }, + { + type: 1, + key: 'dG91cm5hbWVudHMAAAACnPg=', + val: 'AAAAApz4AAAAAGkLbEgAAAAAaQtuoAAAAAgN4Lazp2QAAAAAAAgN4Lazp2QAAAAAAAgpoiQa9iwAAABuAVv6I33/nQnW+3wmlLfavrSvstjnldid65XTjQ3nqgAAAAXwE1AptY3LtZdlBeh6mcP3eiC1CGvqqv/3e6SOTNq3cgAAAALsE8pgwEzgJ+Nk3sKxnZ6OQQ6s/5JhxCXnioUMFmdfpcqTAAAAAuwUQUO2CdnII2pbbgiyzP4TjqaZ99MUJtkS4/wxY6YkOxQAAAAC7BW8zrxROav1ST0TIld62AKhGxMYVMoJVvzDxYCXrvzY7gAAAALsFru2lwb0jw3/9QMkG67zHFB792NjLXypEOW/9DcOhiUMAAAAAuwX', + version: 1, + operation: 0, + }, + ], + accountChanges: 24, + }, + ]; + + const expectedResult = { + accountState: { + nonce: 0, + balance: '0', + developerReward: '9277083780000000', + address: 'erd1qqqqqqqqqqqqqpgqwjkey9nne3lltzwkdrsq3nalxqgvn4sa3qtse7d6nx', + ownerAddress: 'erd1f74ghf83xvek0sxmjrclssat54q6z069sy63ymax6k93mqav3qtsp2rv0l', + codeHash: '9S1Hs2tTj7zA+JLDTnD29ncfZtRsxevT36irfG9yrWI=', + rootHash: 'ESYjuem0MgHFxhYqC7omi7mMee+Y4g6PW+NUMcU8xfc=', + codeMetadata: '0500', + }, + esdtState: { + Fungible: [ + { + identifier: 'FOXSY-86ecfe', + nonce: '0', + type: 0, + value: '0', + propertiesHex: '', + reservedHex: '', + tokenMetaData: null, + }, + ], + NonFungible: [], + NonFungibleV2: [], + SemiFungible: [], + MetaFungible: [], + DynamicNFT: [], + DynamicSFT: [], + DynamicMeta: [], + }, + accountChanges: { + nonceChanged: false, + balanceChanged: false, + codeHashChanged: false, + rootHashChanged: true, + developerRewardChanged: true, + ownerAddressChanged: false, + userNameChanged: false, + codeMetadataChanged: false, + }, + isNewAccount: false, + }; + const result = StateChangesDecoder['getAccountFinalState']('erd1dwkr89z4mmqxxgrv0ks62pccmqsheqq3zjwpa7r7fh6v5dgnrmjs8a9wng', mockAccountStateAccesses, true); + expect(result).toEqual(expectedResult); + }); + }); +}); diff --git a/src/utils/cache.info.ts b/src/utils/cache.info.ts index 967f20f4b..938f18fb4 100644 --- a/src/utils/cache.info.ts +++ b/src/utils/cache.info.ts @@ -807,4 +807,25 @@ export class CacheInfo { ttl: Constants.oneMinute(), }; } + + static StateChangesConsumerLatestProcessedBlockTimestamp(shardId: number): CacheInfo { + return { + key: `latestProcessedBlock:${shardId}`, + ttl: Constants.oneMinute(), + }; + } + + static AccountState(address: string): CacheInfo { + return { + key: `account-state:${address}`, + ttl: Constants.oneHour() * 12, + }; + } + + static AccountEsdt(address: string, identifier: string): CacheInfo { + return { + key: `account-esdt:${address}:${identifier}`, + ttl: Constants.oneHour() * 12, + }; + } }