diff --git a/.github/workflows/blockchain_watcher_build.yaml b/.github/workflows/blockchain_watcher_build.yaml index 3b423b0e..dfa9608e 100644 --- a/.github/workflows/blockchain_watcher_build.yaml +++ b/.github/workflows/blockchain_watcher_build.yaml @@ -30,5 +30,5 @@ jobs: run: npm run build working-directory: ./blockchain-watcher - name: Run tests - run: npm test + run: npm run test:coverage working-directory: ./blockchain-watcher diff --git a/blockchain-watcher/.dockerignore b/blockchain-watcher/.dockerignore new file mode 100644 index 00000000..b0f99d68 --- /dev/null +++ b/blockchain-watcher/.dockerignore @@ -0,0 +1,6 @@ +lib +node_modules +README.md +metadata-repo +coverage +docs \ No newline at end of file diff --git a/blockchain-watcher/.gitignore b/blockchain-watcher/.gitignore index f3bd2c65..cee22133 100644 --- a/blockchain-watcher/.gitignore +++ b/blockchain-watcher/.gitignore @@ -1,3 +1,6 @@ node_modules lib -coverage \ No newline at end of file +coverage + +metadata-repo +config/dev.json \ No newline at end of file diff --git a/blockchain-watcher/Dockerfile b/blockchain-watcher/Dockerfile index 80a68a09..caa6cb35 100644 --- a/blockchain-watcher/Dockerfile +++ b/blockchain-watcher/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker.io/docker/dockerfile:1.3@sha256:42399d4635eddd7a9b8a24be879d2f9a930d0ed040a61324cfdf59ef1357b3b2 -FROM node:19.6.1-slim@sha256:a1ba21bf0c92931d02a8416f0a54daad66cb36a85d2b73af9d73b044f5f57cfc +FROM node:19.6.1-slim@sha256:a1ba21bf0c92931d02a8416f0a54daad66cb36a85d2b73af9d73b044f5f57cfc as builder # npm wants to clone random Git repositories - lovely. # RUN apk add git python make build-base @@ -7,8 +7,6 @@ FROM node:19.6.1-slim@sha256:a1ba21bf0c92931d02a8416f0a54daad66cb36a85d2b73af9d7 RUN apt-get update && apt-get -y install \ git python make curl netcat -RUN npm i typescript -g - USER 1000 RUN mkdir -p /home/node/app @@ -30,10 +28,21 @@ RUN if [ -e /certs/cert.pem ]; then git config --global http.sslCAInfo /certs/ce COPY --chown=node:node . . RUN npm ci +RUN npm run build -run npm run build +FROM node:19.6.1-slim@sha256:a1ba21bf0c92931d02a8416f0a54daad66cb36a85d2b73af9d73b044f5f57cfc as runner -CMD ["npm", "start"] +COPY --from=builder /home/node/app/config /home/node/app/config +COPY --from=builder /home/node/app/lib /home/node/app/lib + +WORKDIR /home/node/app + +COPY package.json . +COPY package-lock.json . + +RUN npm install --omit=dev + +CMD [ "npm", "start" ] diff --git a/blockchain-watcher/config/custom-environment-variables.json b/blockchain-watcher/config/custom-environment-variables.json new file mode 100644 index 00000000..08afdad6 --- /dev/null +++ b/blockchain-watcher/config/custom-environment-variables.json @@ -0,0 +1,8 @@ +{ + "environment": "BLOCKCHAIN_ENV", + "dryRun": "DRY_RUN_ENABLED", + "sns": { + "topicArn": "SNS_TOPIC_ARN", + "region": "SNS_REGION" + } +} diff --git a/blockchain-watcher/config/default.json b/blockchain-watcher/config/default.json new file mode 100644 index 00000000..db4d2349 --- /dev/null +++ b/blockchain-watcher/config/default.json @@ -0,0 +1,23 @@ +{ + "environment": "testnet", + "dryRun": true, + "supportedChains": ["ethereum"], + "sns": { + "topicArn": "arn:aws:sns:us-east-1:000000000000:localstack-topic.fifo", + "region": "us-east-1", + "groupId": "blockchain-watcher", + "subject": "blockchain-watcher" + }, + "metadata": { + "dir": "metadata-repo" + }, + "platforms": { + "ethereum": { + "name": "ethereum", + "network": "goerli", + "chainId": 2, + "rpcs": ["https://rpc.ankr.com/eth_goerli"], + "timeout": 10000 + } + } +} diff --git a/blockchain-watcher/config/local.json b/blockchain-watcher/config/local.json deleted file mode 100644 index 8231a59d..00000000 --- a/blockchain-watcher/config/local.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "network": "TESTNET", - "supportedChains": [2], - "rpcs": [ - { - "chain": 2, - "rpcs": ["https://rpc.ankr.com/eth_goerli"] - } - ], - "handlers": [ - { - "name": "deliveryEventHandler", - "config": { - "contractAddress": "0xA3cF45939bD6260bcFe3D66bc73d60f19e49a8BB", - "fromBlock": 0, - "toBlock": "latest" - } - } - ] -} diff --git a/blockchain-watcher/config/staging.json b/blockchain-watcher/config/staging.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/blockchain-watcher/config/staging.json @@ -0,0 +1 @@ +{} diff --git a/blockchain-watcher/jest.config.js b/blockchain-watcher/jest.config.js index a3546914..0dc2dbaf 100644 --- a/blockchain-watcher/jest.config.js +++ b/blockchain-watcher/jest.config.js @@ -2,8 +2,11 @@ module.exports = { preset: "ts-jest", testEnvironment: "node", - testRegex: "^(?!.*integration.*)(?=.*test\\/).*\\.test\\.ts$", - collectCoverageFrom: ["./src/**"], + collectCoverageFrom: [ + "./src/domain", + "./src/infrastructure/mappers", + "./src/infrastructure/repositories", + ], coverageThreshold: { global: { lines: 85, diff --git a/blockchain-watcher/package-lock.json b/blockchain-watcher/package-lock.json index a73e9b65..7a7010b8 100644 --- a/blockchain-watcher/package-lock.json +++ b/blockchain-watcher/package-lock.json @@ -9,7 +9,12 @@ "version": "0.0.0", "license": "ISC", "dependencies": { + "@aws-sdk/client-sns": "^3.445.0", "@certusone/wormhole-sdk": "^0.9.21-beta.0", + "@types/config": "^3.3.3", + "axios": "^1.6.0", + "axios-rate-limit": "^1.3.0", + "config": "^3.3.9", "dotenv": "^16.3.1", "ethers": "^5", "uuid": "^9.0.1", @@ -21,12 +26,15 @@ "@types/uuid": "^9.0.6", "@types/yargs": "^17.0.23", "jest": "^29.7.0", + "nock": "^13.3.8", "prettier": "^2.8.7", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "tsx": "^3.12.7", - "typescript": "^4.8.4", - "winston": "^3.8.2" + "typescript": "^4.8.4" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@ampproject/remapping": { @@ -84,6 +92,582 @@ } } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-sdk/client-sns": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.445.0.tgz", + "integrity": "sha512-uZfhTDDBT741C8PTUu3N+ANJjmnRPM8IO+51kjz2Gpt4g7QrMWKdnc5YBOycNeq0Iy742FenmisBIEQfuYoaAQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.445.0", + "@aws-sdk/core": "3.445.0", + "@aws-sdk/credential-provider-node": "3.445.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.445.0.tgz", + "integrity": "sha512-me4LvqNnu6kxi+sW7t0AgMv1Yi64ikas0x2+5jv23o6Csg32w0S0xOjCTKQYahOA5CMFunWvlkFIfxbqs+Uo7w==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.445.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.445.0.tgz", + "integrity": "sha512-ogbdqrS8x9O5BTot826iLnTQ6i4/F5BSi/74gycneCxYmAnYnyUBNOWVnynv6XZiEWyDJQCU2UtMd52aNGW1GA==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.445.0", + "@aws-sdk/credential-provider-node": "3.445.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-sdk-sts": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.445.0.tgz", + "integrity": "sha512-6GYLElUG1QTOdmXG8zXa+Ull9IUeSeItKDYHKzHYfIkbsagMfYlf7wm9XIYlatjtgodNfZ3gPHAJfRyPmwKrsg==", + "dependencies": { + "@smithy/smithy-client": "^2.1.12", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.433.0.tgz", + "integrity": "sha512-Vl7Qz5qYyxBurMn6hfSiNJeUHSqfVUlMt0C1Bds3tCkl3IzecRWwyBOlxtxO3VCrgVeW3HqswLzCvhAFzPH6nQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.445.0.tgz", + "integrity": "sha512-R7IYSGjNZ5KKJwQJ2HNPemjpAMWvdce91i8w+/aHfqeGfTXrmYJu99PeGRyyBTKEumBaojyjTRvmO8HzS+/l7g==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.445.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.445.0.tgz", + "integrity": "sha512-zI4k4foSjQRKNEsouculRcz7IbLfuqdFxypDLYwn+qPNMqJwWJ7VxOOeBSPUpHFcd7CLSfbHN2JAhQ7M02gPTA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-ini": "3.445.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.445.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.433.0.tgz", + "integrity": "sha512-W7FcGlQjio9Y/PepcZGRyl5Bpwb0uWU7qIUCh+u4+q2mW4D5ZngXg8V/opL9/I/p4tUH9VXZLyLGwyBSkdhL+A==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.445.0.tgz", + "integrity": "sha512-gJz7kAiDecdhtApgXnxfZsXKsww8BnifDF9MAx9Dr4X6no47qYsCCS3XPuEyRiF9VebXvHOH0H260Zp3bVyniQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.445.0", + "@aws-sdk/token-providers": "3.438.0", + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.433.0.tgz", + "integrity": "sha512-RlwjP1I5wO+aPpwyCp23Mk8nmRbRL33hqRASy73c4JA2z2YiRua+ryt6MalIxehhwQU6xvXUKulJnPG9VaMFZg==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.433.0.tgz", + "integrity": "sha512-mBTq3UWv1UzeHG+OfUQ2MB/5GEkt5LTKFaUqzL7ESwzW8XtpBgXnjZvIwu3Vcd3sEetMwijwaGiJhY0ae/YyaA==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.433.0.tgz", + "integrity": "sha512-We346Fb5xGonTGVZC9Nvqtnqy74VJzYuTLLiuuftA5sbNzftBDy/22QCfvYSTOAl3bvif+dkDUzQY2ihc5PwOQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.433.0.tgz", + "integrity": "sha512-HEvYC9PQlWY/ccUYtLvAlwwf1iCif2TSAmLNr3YTBRVa98x6jKL0hlCrHWYklFeqOGSKy6XhE+NGJMUII0/HaQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.433.0.tgz", + "integrity": "sha512-ORYbJnBejUyonFl5FwIqhvI3Cq6sAp9j+JpkKZtFNma9tFPdrhmYgfCeNH32H/wGTQV/tUoQ3luh0gA4cuk6DA==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.433.0.tgz", + "integrity": "sha512-jxPvt59NZo/epMNLNTu47ikmP8v0q217I6bQFGJG7JVFnfl36zDktMwGw+0xZR80qiK47/2BWrNpta61Zd2FxQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.438.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.438.0.tgz", + "integrity": "sha512-a+xHT1wOxT6EA6YyLmrfaroKWOkwwyiktUfXKM0FsUutGzNi4fKhb5NZ2al58NsXzHgHFrasSDp+Lqbd/X2cEw==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.433.0.tgz", + "integrity": "sha512-xpjRjCZW+CDFdcMmmhIYg81ST5UAnJh61IHziQEk0FXONrg4kjyYPZAOjEdzXQ+HxJQuGQLKPhRdzxmQnbX7pg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.438.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.438.0.tgz", + "integrity": "sha512-G2fUfTtU6/1ayYRMu0Pd9Ln4qYSvwJOWCqJMdkDgvXSwdgcOSOLsnAIk1AHGJDAvgLikdCzuyOsdJiexr9Vnww==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.433.0.tgz", + "integrity": "sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.438.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.438.0.tgz", + "integrity": "sha512-6VyPTq1kN3GWxwFt5DdZfOsr6cJZPLjWh0troY/0uUv3hK74C9o3Y0Xf/z8UAUvQFkVqZse12O0/BgPVMImvfA==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/util-endpoints": "^1.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.433.0.tgz", + "integrity": "sha512-2Cf/Lwvxbt5RXvWFXrFr49vXv0IddiUwrZoAiwhDYxvsh+BMnh+NUFot+ZQaTrk/8IPZVDeLPWZRdVy00iaVXQ==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.437.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.437.0.tgz", + "integrity": "sha512-JVEcvWaniamtYVPem4UthtCNoTBCfFTwYj7Y3CrWZ2Qic4TqrwLkAfaBGtI2TGrhIClVr77uzLI6exqMTN7orA==", + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -652,6 +1236,14 @@ "@types/node": "^18.0.3" } }, + "node_modules/@certusone/wormhole-sdk/node_modules/axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, "node_modules/@classic-terra/terra.proto": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@classic-terra/terra.proto/-/terra.proto-1.1.0.tgz", @@ -703,7 +1295,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, "engines": { "node": ">=0.1.90" } @@ -953,7 +1544,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "dev": true, "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -3426,6 +4016,515 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", + "integrity": "sha512-YIJyefe1mi3GxKdZxEBEuzYOeQ9xpYfqnFmWzojCssRAuR7ycxwpoRQgp965vuW426xUAQhCV5rCaWElQ7XsaA==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.16.tgz", + "integrity": "sha512-1k+FWHQDt2pfpXhJsOmNMmlAZ3NUQ98X5tYsjQhVGq+0X6cOBMhfh6Igd0IX3Ut6lEO6DQAdPMI/blNr3JZfMQ==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.18.tgz", + "integrity": "sha512-QnPBi6D2zj6AHJdUTo5zXmk8vwHJ2bNevhcVned1y+TZz/OI5cizz5DsYNkqFUIDn8tBuEyKNgbmKVNhBbuY3g==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.12.tgz", + "integrity": "sha512-ZZQLzHBJkbiAAdj2C5K+lBlYp/XJ+eH2uy+jgJgYIFW/o5AM59Hlj7zyI44/ZTDIQWmBxb3EFv/c5t44V8/g8A==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.4.tgz", + "integrity": "sha512-gIPRFEGi+c6V52eauGKrjDzPWF2Cu7Z1r5F8A3j2wcwz25sPG/t8kjsbEhli/tS/2zJp/ybCZXe4j4ro3yv/HA==", + "dependencies": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.12.tgz", + "integrity": "sha512-fDZnTr5j9t5qcbeJ037aMZXxMka13Znqwrgy3PAqYj6Dm3XHXHftTH3q+NWgayUxl1992GFtQt1RuEzRMy3NnQ==", + "dependencies": { + "@smithy/types": "^2.4.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.12.tgz", + "integrity": "sha512-p5Y+iMHV3SoEpy3VSR7mifbreHQwVSvHSAz/m4GdoXfOzKzaYC8hYv10Ks7Deblkf7lhas8U+lAp9ThbBM+ZXA==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.14.tgz", + "integrity": "sha512-poUNgKTw9XwPXfX9nEHpVgrMNVpaSMZbshqvPxFVoalF4wp6kRzYKOfdesSVectlQ51VtigoLfbXcdyPwvxgTg==", + "dependencies": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.3.tgz", + "integrity": "sha512-ZrQ0/YX6hNVTxqMEHtEaDbDv6pNeEji/a5Vk3HuFC5R3ZY8lfoATyxmOGxBVYnF3NUvZLNC7umEv1WzWGWvCGQ==", + "dependencies": { + "@smithy/middleware-serde": "^2.0.12", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.18.tgz", + "integrity": "sha512-VyrHQRldGSb3v9oFOB5yPxmLT7U2sQic2ytylOnYlnsmVOLlFIaI6sW22c+w2675yq+XZ6HOuzV7x2OBYCWRNA==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-retry": "^2.0.5", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.12.tgz", + "integrity": "sha512-IBeco157lIScecq2Z+n0gq56i4MTnfKxS7rbfrAORveDJgnbBAaEQgYqMqp/cYqKrpvEXcyTjwKHrBjCCIZh2A==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.6.tgz", + "integrity": "sha512-YSvNZeOKWLJ0M/ycxwDIe2Ztkp6Qixmcml1ggsSv2fdHKGkBPhGrX5tMzPGMI1yyx55UEYBi2OB4s+RriXX48A==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.3.tgz", + "integrity": "sha512-J6lXvRHGVnSX3n1PYi+e1L5HN73DkkJpUviV3Ebf+8wSaIjAf+eVNbzyvh/S5EQz7nf4KVfwbD5vdoZMAthAEQ==", + "dependencies": { + "@smithy/property-provider": "^2.0.13", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.8.tgz", + "integrity": "sha512-KZylM7Wff/So5SmCiwg2kQNXJ+RXgz34wkxS7WNwIUXuZrZZpY/jKJCK+ZaGyuESDu3TxcaY+zeYGJmnFKbQsA==", + "dependencies": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.13.tgz", + "integrity": "sha512-VJqUf2CbsQX6uUiC5dUPuoEATuFjkbkW3lJHbRnpk9EDC9X+iKqhfTK+WP+lve5EQ9TcCI1Q6R7hrg41FyC54w==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.8.tgz", + "integrity": "sha512-SHJvYeWq8q0FK8xHk+xjV9dzDUDjFMT+G1pZbV+XB6OVoac/FSVshlMNPeUJ8AmSkcDKHRu5vASnRqZHgD3qhw==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.12.tgz", + "integrity": "sha512-cDbF07IuCjiN8CdGvPzfJjXIrmDSelScRfyJYrYBNBbKl2+k7QD/KqiHhtRyEKgID5mmEVrV6KE6L/iPJ98sFw==", + "dependencies": { + "@smithy/types": "^2.4.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.12.tgz", + "integrity": "sha512-fytyTcXaMzPBuNtPlhj5v6dbl4bJAnwKZFyyItAGt4Tgm9HFPZNo7a9r1SKPr/qdxUEBzvL9Rh+B9SkTX3kFxg==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.5.tgz", + "integrity": "sha512-M0SeJnEgD2ywJyV99Fb1yKFzmxDe9JfpJiYTVSRMyRLc467BPU0qsuuDPzMCdB1mU8M8u1rVOdkqdoyFN8UFTw==", + "dependencies": { + "@smithy/types": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.2.tgz", + "integrity": "sha512-noyQUPn7b1M8uB0GEXc/Zyxq+5K2b7aaqWnLp+hgJ7+xu/FCvtyWy5eWLDjQEsHnAet2IZhS5QF8872OR69uNg==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.12.tgz", + "integrity": "sha512-6Kc2lCZEVmb1nNYngyNbWpq0d82OZwITH11SW/Q0U6PX5fH7B2cIcFe7o6eGEFPkTZTP8itTzmYiGcECL0D0Lw==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.12", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.12.tgz", + "integrity": "sha512-XXqhridfkKnpj+lt8vM6HRlZbqUAqBjVC74JIi13F/AYQd/zTj9SOyGfxnbp4mjY9q28LityxIuV8CTinr9r5w==", + "dependencies": { + "@smithy/middleware-stack": "^2.0.6", + "@smithy/types": "^2.4.0", + "@smithy/util-stream": "^2.0.17", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz", + "integrity": "sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz", + "integrity": "sha512-qgkW2mZqRvlNUcBkxYB/gYacRaAdck77Dk3/g2iw0S9F0EYthIS3loGfly8AwoWpIvHKhkTsCXXQfzksgZ4zIA==", + "dependencies": { + "@smithy/querystring-parser": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.16.tgz", + "integrity": "sha512-Uv5Cu8nVkuvLn0puX+R9zWbSNpLIR3AxUlPoLJ7hC5lvir8B2WVqVEkJLwtixKAncVLasnTVjPDCidtAUTGEQw==", + "dependencies": { + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.21.tgz", + "integrity": "sha512-cUEsttVZ79B7Al2rWK2FW03HBpD9LyuqFtm+1qFty5u9sHSdesr215gS2Ln53fTopNiPgeXpdoM3IgjvIO0rJw==", + "dependencies": { + "@smithy/config-resolver": "^2.0.16", + "@smithy/credential-provider-imds": "^2.0.18", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.2.tgz", + "integrity": "sha512-QEdq+sP68IJHAMVB2ugKVVZEWeKQtZLuf+akHzc8eTVElsZ2ZdVLWC6Cp+uKjJ/t4yOj1qu6ZzyxJQEQ8jdEjg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.5.tgz", + "integrity": "sha512-1lyT3TcaMJQe+OFfVI+TlomDkPuVzb27NZYdYtmSTltVmLaUjdCyt4KE+OH1CnhZKsz4/cdCL420Lg9UH5Z2Mw==", + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.5.tgz", + "integrity": "sha512-x3t1+MQAJ6QONk3GTbJNcugCFDVJ+Bkro5YqQQK1EyVesajNDqxFtCx9WdOFNGm/Cbm7tUdwVEmfKQOJoU2Vtw==", + "dependencies": { + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.17.tgz", + "integrity": "sha512-fP/ZQ27rRvHsqItds8yB7jerwMpZFTL3QqbQbidUiG0+mttMoKdP0ZqnvM8UK5q0/dfc3/pN7g4XKPXOU7oRWw==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@solana/buffer-layout": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", @@ -3707,6 +4806,11 @@ "@types/node": "*" } }, + "node_modules/@types/config": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.3.tgz", + "integrity": "sha512-BB8DBAud88EgiAKlz8WQStzI771Kb6F3j4dioRJ4GD+tP4tzcZyMlz86aXuZT4s9hyesFORehMQE6eqtA5O+Vg==" + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -3931,8 +5035,7 @@ "node_modules/@types/triple-beam": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", - "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==", - "dev": true + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" }, "node_modules/@types/uuid": { "version": "9.0.6", @@ -4233,8 +5336,7 @@ "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "node_modules/asynckit": { "version": "0.4.0", @@ -4242,11 +5344,21 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dependencies": { - "follow-redirects": "^1.14.4" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios-rate-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/axios-rate-limit/-/axios-rate-limit-1.3.0.tgz", + "integrity": "sha512-cKR5wTbU/CeeyF1xVl5hl6FlYsmzDVqxlN4rGtfO5x7J83UxKDckudsW0yW21/ZJRcO0Qrfm3fUFbhEbWTLayw==", + "peerDependencies": { + "axios": "*" } }, "node_modules/babel-jest": { @@ -4550,6 +5662,11 @@ "text-encoding-utf-8": "^1.0.2" } }, + "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==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4845,7 +5962,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dev": true, "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" @@ -4855,7 +5971,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "devOptional": true, "dependencies": { "color-name": "1.1.3" } @@ -4863,14 +5978,12 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "devOptional": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/color-string": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dev": true, "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -4880,7 +5993,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dev": true, "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" @@ -4907,6 +6019,17 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/config": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.9.tgz", + "integrity": "sha512-G17nfe+cY7kR0wVpc49NCYvNtelm/pPy8czHoFkAgtV1lkmcp7DHtWCdDu+C9Z7gb2WVqa9Tm3uF9aKaPbCfhg==", + "dependencies": { + "json5": "^2.2.3" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -5391,8 +6514,7 @@ "node_modules/enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "dev": true + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "node_modules/error-ex": { "version": "1.3.2", @@ -5770,6 +6892,27 @@ "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -5782,8 +6925,7 @@ "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "dev": true + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "node_modules/file-uri-to-path": { "version": "1.0.0", @@ -5818,8 +6960,7 @@ "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "dev": true + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { "version": "1.15.2", @@ -6250,8 +7391,7 @@ "node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "node_modules/is-core-module": { "version": "2.12.1", @@ -6306,7 +7446,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -8223,7 +9362,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -8300,8 +9438,7 @@ "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "dev": true + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, "node_modules/leven": { "version": "3.1.0", @@ -8382,7 +9519,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", - "dev": true, "dependencies": { "@colors/colors": "1.5.0", "@types/triple-beam": "^1.3.2", @@ -8651,6 +9787,20 @@ "tslib": "^2.0.3" } }, + "node_modules/nock": { + "version": "13.3.8", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.8.tgz", + "integrity": "sha512-96yVFal0c/W1lG7mmfRe7eO+hovrhJYd2obzzOZ90f6fjpeU/XNvd9cYHZKZAQJumDfhXgoTpkpJ9pvMj+hqHw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -8784,7 +9934,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dev": true, "dependencies": { "fn.name": "1.x.x" } @@ -9048,6 +10197,15 @@ "react-is": "^16.13.1" } }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/protobufjs": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", @@ -9076,6 +10234,11 @@ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -9336,7 +10499,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "dev": true, "engines": { "node": ">=10" } @@ -9454,7 +10616,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dev": true, "dependencies": { "is-arrayish": "^0.3.1" } @@ -9526,7 +10687,6 @@ "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true, "engines": { "node": "*" } @@ -9656,6 +10816,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/superstruct": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.3.tgz", @@ -9719,8 +10884,7 @@ "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "dev": true + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, "node_modules/through": { "version": "2.3.8", @@ -9853,8 +11017,7 @@ "node_modules/triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", - "dev": true + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "node_modules/ts-invariant": { "version": "0.10.3", @@ -10238,7 +11401,6 @@ "version": "3.8.2", "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", - "dev": true, "dependencies": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", @@ -10260,7 +11422,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", - "dev": true, "dependencies": { "logform": "^2.3.2", "readable-stream": "^3.6.0", @@ -10497,6 +11658,520 @@ "zen-observable-ts": "^1.2.5" } }, + "@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "requires": { + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "requires": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "requires": { + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "requires": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@aws-sdk/client-sns": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.445.0.tgz", + "integrity": "sha512-uZfhTDDBT741C8PTUu3N+ANJjmnRPM8IO+51kjz2Gpt4g7QrMWKdnc5YBOycNeq0Iy742FenmisBIEQfuYoaAQ==", + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.445.0", + "@aws-sdk/core": "3.445.0", + "@aws-sdk/credential-provider-node": "3.445.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/client-sso": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.445.0.tgz", + "integrity": "sha512-me4LvqNnu6kxi+sW7t0AgMv1Yi64ikas0x2+5jv23o6Csg32w0S0xOjCTKQYahOA5CMFunWvlkFIfxbqs+Uo7w==", + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.445.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/client-sts": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.445.0.tgz", + "integrity": "sha512-ogbdqrS8x9O5BTot826iLnTQ6i4/F5BSi/74gycneCxYmAnYnyUBNOWVnynv6XZiEWyDJQCU2UtMd52aNGW1GA==", + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.445.0", + "@aws-sdk/credential-provider-node": "3.445.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-sdk-sts": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/core": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.445.0.tgz", + "integrity": "sha512-6GYLElUG1QTOdmXG8zXa+Ull9IUeSeItKDYHKzHYfIkbsagMfYlf7wm9XIYlatjtgodNfZ3gPHAJfRyPmwKrsg==", + "requires": { + "@smithy/smithy-client": "^2.1.12", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.433.0.tgz", + "integrity": "sha512-Vl7Qz5qYyxBurMn6hfSiNJeUHSqfVUlMt0C1Bds3tCkl3IzecRWwyBOlxtxO3VCrgVeW3HqswLzCvhAFzPH6nQ==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.445.0.tgz", + "integrity": "sha512-R7IYSGjNZ5KKJwQJ2HNPemjpAMWvdce91i8w+/aHfqeGfTXrmYJu99PeGRyyBTKEumBaojyjTRvmO8HzS+/l7g==", + "requires": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.445.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.445.0.tgz", + "integrity": "sha512-zI4k4foSjQRKNEsouculRcz7IbLfuqdFxypDLYwn+qPNMqJwWJ7VxOOeBSPUpHFcd7CLSfbHN2JAhQ7M02gPTA==", + "requires": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-ini": "3.445.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.445.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.433.0.tgz", + "integrity": "sha512-W7FcGlQjio9Y/PepcZGRyl5Bpwb0uWU7qIUCh+u4+q2mW4D5ZngXg8V/opL9/I/p4tUH9VXZLyLGwyBSkdhL+A==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.445.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.445.0.tgz", + "integrity": "sha512-gJz7kAiDecdhtApgXnxfZsXKsww8BnifDF9MAx9Dr4X6no47qYsCCS3XPuEyRiF9VebXvHOH0H260Zp3bVyniQ==", + "requires": { + "@aws-sdk/client-sso": "3.445.0", + "@aws-sdk/token-providers": "3.438.0", + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.433.0.tgz", + "integrity": "sha512-RlwjP1I5wO+aPpwyCp23Mk8nmRbRL33hqRASy73c4JA2z2YiRua+ryt6MalIxehhwQU6xvXUKulJnPG9VaMFZg==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.433.0.tgz", + "integrity": "sha512-mBTq3UWv1UzeHG+OfUQ2MB/5GEkt5LTKFaUqzL7ESwzW8XtpBgXnjZvIwu3Vcd3sEetMwijwaGiJhY0ae/YyaA==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.433.0.tgz", + "integrity": "sha512-We346Fb5xGonTGVZC9Nvqtnqy74VJzYuTLLiuuftA5sbNzftBDy/22QCfvYSTOAl3bvif+dkDUzQY2ihc5PwOQ==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.433.0.tgz", + "integrity": "sha512-HEvYC9PQlWY/ccUYtLvAlwwf1iCif2TSAmLNr3YTBRVa98x6jKL0hlCrHWYklFeqOGSKy6XhE+NGJMUII0/HaQ==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-sdk-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.433.0.tgz", + "integrity": "sha512-ORYbJnBejUyonFl5FwIqhvI3Cq6sAp9j+JpkKZtFNma9tFPdrhmYgfCeNH32H/wGTQV/tUoQ3luh0gA4cuk6DA==", + "requires": { + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-signing": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.433.0.tgz", + "integrity": "sha512-jxPvt59NZo/epMNLNTu47ikmP8v0q217I6bQFGJG7JVFnfl36zDktMwGw+0xZR80qiK47/2BWrNpta61Zd2FxQ==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.438.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.438.0.tgz", + "integrity": "sha512-a+xHT1wOxT6EA6YyLmrfaroKWOkwwyiktUfXKM0FsUutGzNi4fKhb5NZ2al58NsXzHgHFrasSDp+Lqbd/X2cEw==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/region-config-resolver": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.433.0.tgz", + "integrity": "sha512-xpjRjCZW+CDFdcMmmhIYg81ST5UAnJh61IHziQEk0FXONrg4kjyYPZAOjEdzXQ+HxJQuGQLKPhRdzxmQnbX7pg==", + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/token-providers": { + "version": "3.438.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.438.0.tgz", + "integrity": "sha512-G2fUfTtU6/1ayYRMu0Pd9Ln4qYSvwJOWCqJMdkDgvXSwdgcOSOLsnAIk1AHGJDAvgLikdCzuyOsdJiexr9Vnww==", + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.438.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.438.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.437.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-endpoints": "^1.0.2", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/types": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.433.0.tgz", + "integrity": "sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.438.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.438.0.tgz", + "integrity": "sha512-6VyPTq1kN3GWxwFt5DdZfOsr6cJZPLjWh0troY/0uUv3hK74C9o3Y0Xf/z8UAUvQFkVqZse12O0/BgPVMImvfA==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/util-endpoints": "^1.0.2", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.433.0.tgz", + "integrity": "sha512-2Cf/Lwvxbt5RXvWFXrFr49vXv0IddiUwrZoAiwhDYxvsh+BMnh+NUFot+ZQaTrk/8IPZVDeLPWZRdVy00iaVXQ==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.437.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.437.0.tgz", + "integrity": "sha512-JVEcvWaniamtYVPem4UthtCNoTBCfFTwYj7Y3CrWZ2Qic4TqrwLkAfaBGtI2TGrhIClVr77uzLI6exqMTN7orA==", + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "requires": { + "tslib": "^2.3.1" + } + }, "@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -10912,6 +12587,16 @@ "elliptic": "^6.5.4", "js-base64": "^3.6.1", "near-api-js": "^1.0.0" + }, + "dependencies": { + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "requires": { + "follow-redirects": "^1.14.4" + } + } } }, "@certusone/wormhole-sdk-proto-web": { @@ -10977,8 +12662,7 @@ "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" }, "@confio/ics23": { "version": "0.6.8", @@ -11214,7 +12898,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "dev": true, "requires": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -12943,6 +14626,412 @@ "@sinonjs/commons": "^3.0.0" } }, + "@smithy/abort-controller": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", + "integrity": "sha512-YIJyefe1mi3GxKdZxEBEuzYOeQ9xpYfqnFmWzojCssRAuR7ycxwpoRQgp965vuW426xUAQhCV5rCaWElQ7XsaA==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/config-resolver": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.16.tgz", + "integrity": "sha512-1k+FWHQDt2pfpXhJsOmNMmlAZ3NUQ98X5tYsjQhVGq+0X6cOBMhfh6Igd0IX3Ut6lEO6DQAdPMI/blNr3JZfMQ==", + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@smithy/credential-provider-imds": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.18.tgz", + "integrity": "sha512-QnPBi6D2zj6AHJdUTo5zXmk8vwHJ2bNevhcVned1y+TZz/OI5cizz5DsYNkqFUIDn8tBuEyKNgbmKVNhBbuY3g==", + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "tslib": "^2.5.0" + } + }, + "@smithy/eventstream-codec": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.12.tgz", + "integrity": "sha512-ZZQLzHBJkbiAAdj2C5K+lBlYp/XJ+eH2uy+jgJgYIFW/o5AM59Hlj7zyI44/ZTDIQWmBxb3EFv/c5t44V8/g8A==", + "requires": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/fetch-http-handler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.4.tgz", + "integrity": "sha512-gIPRFEGi+c6V52eauGKrjDzPWF2Cu7Z1r5F8A3j2wcwz25sPG/t8kjsbEhli/tS/2zJp/ybCZXe4j4ro3yv/HA==", + "requires": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/hash-node": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.12.tgz", + "integrity": "sha512-fDZnTr5j9t5qcbeJ037aMZXxMka13Znqwrgy3PAqYj6Dm3XHXHftTH3q+NWgayUxl1992GFtQt1RuEzRMy3NnQ==", + "requires": { + "@smithy/types": "^2.4.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/invalid-dependency": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.12.tgz", + "integrity": "sha512-p5Y+iMHV3SoEpy3VSR7mifbreHQwVSvHSAz/m4GdoXfOzKzaYC8hYv10Ks7Deblkf7lhas8U+lAp9ThbBM+ZXA==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-content-length": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.14.tgz", + "integrity": "sha512-poUNgKTw9XwPXfX9nEHpVgrMNVpaSMZbshqvPxFVoalF4wp6kRzYKOfdesSVectlQ51VtigoLfbXcdyPwvxgTg==", + "requires": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-endpoint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.3.tgz", + "integrity": "sha512-ZrQ0/YX6hNVTxqMEHtEaDbDv6pNeEji/a5Vk3HuFC5R3ZY8lfoATyxmOGxBVYnF3NUvZLNC7umEv1WzWGWvCGQ==", + "requires": { + "@smithy/middleware-serde": "^2.0.12", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-retry": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.18.tgz", + "integrity": "sha512-VyrHQRldGSb3v9oFOB5yPxmLT7U2sQic2ytylOnYlnsmVOLlFIaI6sW22c+w2675yq+XZ6HOuzV7x2OBYCWRNA==", + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-retry": "^2.0.5", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + } + } + }, + "@smithy/middleware-serde": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.12.tgz", + "integrity": "sha512-IBeco157lIScecq2Z+n0gq56i4MTnfKxS7rbfrAORveDJgnbBAaEQgYqMqp/cYqKrpvEXcyTjwKHrBjCCIZh2A==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-stack": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.6.tgz", + "integrity": "sha512-YSvNZeOKWLJ0M/ycxwDIe2Ztkp6Qixmcml1ggsSv2fdHKGkBPhGrX5tMzPGMI1yyx55UEYBi2OB4s+RriXX48A==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/node-config-provider": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.3.tgz", + "integrity": "sha512-J6lXvRHGVnSX3n1PYi+e1L5HN73DkkJpUviV3Ebf+8wSaIjAf+eVNbzyvh/S5EQz7nf4KVfwbD5vdoZMAthAEQ==", + "requires": { + "@smithy/property-provider": "^2.0.13", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/node-http-handler": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.8.tgz", + "integrity": "sha512-KZylM7Wff/So5SmCiwg2kQNXJ+RXgz34wkxS7WNwIUXuZrZZpY/jKJCK+ZaGyuESDu3TxcaY+zeYGJmnFKbQsA==", + "requires": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/property-provider": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.13.tgz", + "integrity": "sha512-VJqUf2CbsQX6uUiC5dUPuoEATuFjkbkW3lJHbRnpk9EDC9X+iKqhfTK+WP+lve5EQ9TcCI1Q6R7hrg41FyC54w==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/protocol-http": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.8.tgz", + "integrity": "sha512-SHJvYeWq8q0FK8xHk+xjV9dzDUDjFMT+G1pZbV+XB6OVoac/FSVshlMNPeUJ8AmSkcDKHRu5vASnRqZHgD3qhw==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/querystring-builder": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.12.tgz", + "integrity": "sha512-cDbF07IuCjiN8CdGvPzfJjXIrmDSelScRfyJYrYBNBbKl2+k7QD/KqiHhtRyEKgID5mmEVrV6KE6L/iPJ98sFw==", + "requires": { + "@smithy/types": "^2.4.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/querystring-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.12.tgz", + "integrity": "sha512-fytyTcXaMzPBuNtPlhj5v6dbl4bJAnwKZFyyItAGt4Tgm9HFPZNo7a9r1SKPr/qdxUEBzvL9Rh+B9SkTX3kFxg==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/service-error-classification": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.5.tgz", + "integrity": "sha512-M0SeJnEgD2ywJyV99Fb1yKFzmxDe9JfpJiYTVSRMyRLc467BPU0qsuuDPzMCdB1mU8M8u1rVOdkqdoyFN8UFTw==", + "requires": { + "@smithy/types": "^2.4.0" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.2.tgz", + "integrity": "sha512-noyQUPn7b1M8uB0GEXc/Zyxq+5K2b7aaqWnLp+hgJ7+xu/FCvtyWy5eWLDjQEsHnAet2IZhS5QF8872OR69uNg==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/signature-v4": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.12.tgz", + "integrity": "sha512-6Kc2lCZEVmb1nNYngyNbWpq0d82OZwITH11SW/Q0U6PX5fH7B2cIcFe7o6eGEFPkTZTP8itTzmYiGcECL0D0Lw==", + "requires": { + "@smithy/eventstream-codec": "^2.0.12", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/smithy-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.12.tgz", + "integrity": "sha512-XXqhridfkKnpj+lt8vM6HRlZbqUAqBjVC74JIi13F/AYQd/zTj9SOyGfxnbp4mjY9q28LityxIuV8CTinr9r5w==", + "requires": { + "@smithy/middleware-stack": "^2.0.6", + "@smithy/types": "^2.4.0", + "@smithy/util-stream": "^2.0.17", + "tslib": "^2.5.0" + } + }, + "@smithy/types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz", + "integrity": "sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/url-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz", + "integrity": "sha512-qgkW2mZqRvlNUcBkxYB/gYacRaAdck77Dk3/g2iw0S9F0EYthIS3loGfly8AwoWpIvHKhkTsCXXQfzksgZ4zIA==", + "requires": { + "@smithy/querystring-parser": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "requires": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-defaults-mode-browser": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.16.tgz", + "integrity": "sha512-Uv5Cu8nVkuvLn0puX+R9zWbSNpLIR3AxUlPoLJ7hC5lvir8B2WVqVEkJLwtixKAncVLasnTVjPDCidtAUTGEQw==", + "requires": { + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-defaults-mode-node": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.21.tgz", + "integrity": "sha512-cUEsttVZ79B7Al2rWK2FW03HBpD9LyuqFtm+1qFty5u9sHSdesr215gS2Ln53fTopNiPgeXpdoM3IgjvIO0rJw==", + "requires": { + "@smithy/config-resolver": "^2.0.16", + "@smithy/credential-provider-imds": "^2.0.18", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-endpoints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.2.tgz", + "integrity": "sha512-QEdq+sP68IJHAMVB2ugKVVZEWeKQtZLuf+akHzc8eTVElsZ2ZdVLWC6Cp+uKjJ/t4yOj1qu6ZzyxJQEQ8jdEjg==", + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-middleware": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.5.tgz", + "integrity": "sha512-1lyT3TcaMJQe+OFfVI+TlomDkPuVzb27NZYdYtmSTltVmLaUjdCyt4KE+OH1CnhZKsz4/cdCL420Lg9UH5Z2Mw==", + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.5.tgz", + "integrity": "sha512-x3t1+MQAJ6QONk3GTbJNcugCFDVJ+Bkro5YqQQK1EyVesajNDqxFtCx9WdOFNGm/Cbm7tUdwVEmfKQOJoU2Vtw==", + "requires": { + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-stream": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.17.tgz", + "integrity": "sha512-fP/ZQ27rRvHsqItds8yB7jerwMpZFTL3QqbQbidUiG0+mttMoKdP0ZqnvM8UK5q0/dfc3/pN7g4XKPXOU7oRWw==", + "requires": { + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + } + }, "@solana/buffer-layout": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", @@ -13203,6 +15292,11 @@ "@types/node": "*" } }, + "@types/config": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@types/config/-/config-3.3.3.tgz", + "integrity": "sha512-BB8DBAud88EgiAKlz8WQStzI771Kb6F3j4dioRJ4GD+tP4tzcZyMlz86aXuZT4s9hyesFORehMQE6eqtA5O+Vg==" + }, "@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -13427,8 +15521,7 @@ "@types/triple-beam": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", - "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==", - "dev": true + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" }, "@types/uuid": { "version": "9.0.6", @@ -13669,8 +15762,7 @@ "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "asynckit": { "version": "0.4.0", @@ -13678,13 +15770,21 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "requires": { - "follow-redirects": "^1.14.4" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, + "axios-rate-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/axios-rate-limit/-/axios-rate-limit-1.3.0.tgz", + "integrity": "sha512-cKR5wTbU/CeeyF1xVl5hl6FlYsmzDVqxlN4rGtfO5x7J83UxKDckudsW0yW21/ZJRcO0Qrfm3fUFbhEbWTLayw==", + "requires": {} + }, "babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -13918,6 +16018,11 @@ "text-encoding-utf-8": "^1.0.2" } }, + "bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -14127,7 +16232,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dev": true, "requires": { "color-convert": "^1.9.3", "color-string": "^1.6.0" @@ -14137,7 +16241,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "devOptional": true, "requires": { "color-name": "1.1.3" } @@ -14145,14 +16248,12 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "devOptional": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "color-string": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dev": true, "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -14162,7 +16263,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dev": true, "requires": { "color": "^3.1.3", "text-hex": "1.0.x" @@ -14186,6 +16286,14 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "config": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.9.tgz", + "integrity": "sha512-G17nfe+cY7kR0wVpc49NCYvNtelm/pPy8czHoFkAgtV1lkmcp7DHtWCdDu+C9Z7gb2WVqa9Tm3uF9aKaPbCfhg==", + "requires": { + "json5": "^2.2.3" + } + }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -14560,8 +16668,7 @@ "enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "dev": true + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "error-ex": { "version": "1.3.2", @@ -14883,6 +16990,14 @@ "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz", "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==" }, + "fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "requires": { + "strnum": "^1.0.5" + } + }, "fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -14895,8 +17010,7 @@ "fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "dev": true + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "file-uri-to-path": { "version": "1.0.0", @@ -14925,8 +17039,7 @@ "fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "dev": true + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { "version": "1.15.2", @@ -15228,8 +17341,7 @@ "is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "is-core-module": { "version": "2.12.1", @@ -15267,8 +17379,7 @@ "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, "isarray": { "version": "0.0.1", @@ -16703,8 +18814,7 @@ "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonparse": { "version": "1.3.1", @@ -16756,8 +18866,7 @@ "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "dev": true + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, "leven": { "version": "3.1.0", @@ -16826,7 +18935,6 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", - "dev": true, "requires": { "@colors/colors": "1.5.0", "@types/triple-beam": "^1.3.2", @@ -17046,6 +19154,17 @@ "tslib": "^2.0.3" } }, + "nock": { + "version": "13.3.8", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.8.tgz", + "integrity": "sha512-96yVFal0c/W1lG7mmfRe7eO+hovrhJYd2obzzOZ90f6fjpeU/XNvd9cYHZKZAQJumDfhXgoTpkpJ9pvMj+hqHw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + } + }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -17153,7 +19272,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dev": true, "requires": { "fn.name": "1.x.x" } @@ -17349,6 +19467,12 @@ "react-is": "^16.13.1" } }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, "protobufjs": { "version": "7.2.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", @@ -17375,6 +19499,11 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -17547,8 +19676,7 @@ "safe-stable-stringify": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "dev": true + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, "scrypt-js": { "version": "3.0.1", @@ -17638,7 +19766,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dev": true, "requires": { "is-arrayish": "^0.3.1" } @@ -17700,8 +19827,7 @@ "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" }, "stack-utils": { "version": "2.0.6", @@ -17796,6 +19922,11 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "superstruct": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-1.0.3.tgz", @@ -17841,8 +19972,7 @@ "text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "dev": true + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, "through": { "version": "2.3.8", @@ -17963,8 +20093,7 @@ "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", - "dev": true + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-invariant": { "version": "0.10.3", @@ -18220,7 +20349,6 @@ "version": "3.8.2", "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", - "dev": true, "requires": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", @@ -18239,7 +20367,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", - "dev": true, "requires": { "logform": "^2.3.2", "readable-stream": "^3.6.0", diff --git a/blockchain-watcher/package.json b/blockchain-watcher/package.json index 977e134a..a23b4b28 100644 --- a/blockchain-watcher/package.json +++ b/blockchain-watcher/package.json @@ -4,20 +4,25 @@ "description": "A process for watching blockchain events and moving them to persistent storage", "main": "index.js", "scripts": { - "start": "node lib/index.js", + "start": "node lib/start.js", "test": "jest", "test:coverage": "jest --collectCoverage=true", "build": "tsc", - "dev": "USE_ENV_FILE=true ts-node src/index.ts", + "dev": "USE_ENV_FILE=true ts-node src/start.ts", "prettier": "prettier --write ." }, "author": "chase-45", "license": "ISC", "dependencies": { + "@aws-sdk/client-sns": "^3.445.0", "@certusone/wormhole-sdk": "^0.9.21-beta.0", + "@types/config": "^3.3.3", + "axios": "^1.6.0", + "axios-rate-limit": "^1.3.0", + "config": "^3.3.9", "dotenv": "^16.3.1", - "uuid": "^9.0.1", "ethers": "^5", + "uuid": "^9.0.1", "winston": "3.8.2" }, "devDependencies": { @@ -26,11 +31,14 @@ "@types/uuid": "^9.0.6", "@types/yargs": "^17.0.23", "jest": "^29.7.0", + "nock": "^13.3.8", "prettier": "^2.8.7", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "tsx": "^3.12.7", - "typescript": "^4.8.4", - "winston": "^3.8.2" + "typescript": "^4.8.4" + }, + "engines": { + "node": ">=18.0.0" } } diff --git a/blockchain-watcher/src/domain/actions/HandleEvmLogs.ts b/blockchain-watcher/src/domain/actions/HandleEvmLogs.ts index aad2d798..24377336 100644 --- a/blockchain-watcher/src/domain/actions/HandleEvmLogs.ts +++ b/blockchain-watcher/src/domain/actions/HandleEvmLogs.ts @@ -15,7 +15,7 @@ export class HandleEvmLogs { mapper: (log: EvmLog, args: ReadonlyArray) => T, target: (parsed: T[]) => Promise ) { - this.cfg = cfg; + this.cfg = this.normalizeCfg(cfg); this.mapper = mapper; this.target = target; } @@ -24,8 +24,8 @@ export class HandleEvmLogs { const mappedItems = logs .filter( (log) => - this.cfg.filter.addresses.includes(log.address) && - this.cfg.filter.topics.includes(log.topics[0]) + this.cfg.filter.addresses.includes(log.address.toLowerCase()) && + this.cfg.filter.topics.includes(log.topics[0].toLowerCase()) ) .map((log) => { const iface = new ethers.utils.Interface([this.cfg.abi]); @@ -37,6 +37,16 @@ export class HandleEvmLogs { // TODO: return a result specifying failures if any return mappedItems; } + + private normalizeCfg(cfg: HandleEvmLogsConfig): HandleEvmLogsConfig { + return { + filter: { + addresses: cfg.filter.addresses.map((addr) => addr.toLowerCase()), + topics: cfg.filter.topics.map((topic) => topic.toLowerCase()), + }, + abi: cfg.abi, + }; + } } export type HandleEvmLogsConfig = { diff --git a/blockchain-watcher/src/domain/actions/PollEvmLogs.ts b/blockchain-watcher/src/domain/actions/PollEvmLogs.ts index b36b22a4..2e08a02c 100644 --- a/blockchain-watcher/src/domain/actions/PollEvmLogs.ts +++ b/blockchain-watcher/src/domain/actions/PollEvmLogs.ts @@ -3,6 +3,7 @@ import { EvmBlockRepository, MetadataRepository } from "../repositories"; import { setTimeout } from "timers/promises"; const ID = "watch-evm-logs"; +let ref: any; /** * PollEvmLogs is an action that watches for new blocks and extracts logs from them. @@ -10,8 +11,8 @@ const ID = "watch-evm-logs"; export class PollEvmLogs { private readonly blockRepo: EvmBlockRepository; private readonly metadataRepo: MetadataRepository; - private latestBlockHeight: bigint = 0n; - private blockHeightCursor: bigint = 0n; + private latestBlockHeight?: bigint; + private blockHeightCursor?: bigint; private cfg: PollEvmLogsConfig; private started: boolean = false; @@ -25,10 +26,10 @@ export class PollEvmLogs { this.cfg = cfg; } - public async start(handlers: ((logs: EvmLog[]) => Promise)[]): Promise { - const metadata = await this.metadataRepo.get(ID); + public async start(handlers: ((logs: EvmLog[]) => Promise)[]): Promise { + const metadata = await this.metadataRepo.get(this.cfg.id); if (metadata) { - this.blockHeightCursor = metadata.lastBlock; + this.blockHeightCursor = BigInt(metadata.lastBlock); } this.started = true; @@ -37,14 +38,17 @@ export class PollEvmLogs { private async watch(handlers: ((logs: EvmLog[]) => Promise)[]): Promise { while (this.started) { + if (this.cfg.hasFinished(this.blockHeightCursor)) { + console.log( + `PollEvmLogs: (${this.cfg.id}) Finished processing all blocks from ${this.cfg.fromBlock} to ${this.cfg.toBlock}` + ); + await this.stop(); + break; + } + this.latestBlockHeight = await this.blockRepo.getBlockHeight(this.cfg.getCommitment()); const range = this.getBlockRange(this.latestBlockHeight); - if (this.cfg.hasFinished(range.fromBlock)) { - // TODO: log - await this.stop(); - continue; - } const logs = await this.blockRepo.getFilteredLogs({ fromBlock: range.fromBlock, @@ -63,10 +67,10 @@ export class PollEvmLogs { // TODO: add error handling. await Promise.all(handlers.map((handler) => handler(logs))); - await this.metadataRepo.save(ID, { lastBlock: range.toBlock }); + await this.metadataRepo.save(this.cfg.id, { lastBlock: range.toBlock }); this.blockHeightCursor = range.toBlock; - await setTimeout(this.cfg.interval ?? 1_000, undefined, { ref: false }); + ref = await setTimeout(this.cfg.interval ?? 1_000, undefined); } } @@ -79,26 +83,37 @@ export class PollEvmLogs { fromBlock: bigint; toBlock: bigint; } { - let fromBlock = this.blockHeightCursor + 1n; + let fromBlock = this.blockHeightCursor + ? this.blockHeightCursor + 1n + : this.cfg.fromBlock ?? latestBlockHeight; // fromBlock is configured and is greater than current block height, then we allow to skip blocks. - if (this.cfg.fromBlock && this.cfg.fromBlock > this.blockHeightCursor) { + if ( + this.blockHeightCursor && + this.cfg.fromBlock && + this.cfg.fromBlock > this.blockHeightCursor + ) { fromBlock = this.cfg.fromBlock; } if (fromBlock > latestBlockHeight) { - return { fromBlock: latestBlockHeight, toBlock: latestBlockHeight }; + return { fromBlock, toBlock: fromBlock }; } - let toBlock = this.cfg.toBlock ?? this.blockHeightCursor + BigInt(this.cfg.getBlockBatchSize()); + let toBlock = fromBlock + BigInt(this.cfg.getBlockBatchSize()); // limit toBlock to obtained block height if (toBlock > fromBlock && toBlock > latestBlockHeight) { toBlock = latestBlockHeight; } + // limit toBlock to configured toBlock + if (this.cfg.toBlock && toBlock > this.cfg.toBlock) { + toBlock = this.cfg.toBlock; + } return { fromBlock, toBlock }; } public async stop(): Promise { + clearTimeout(ref); this.started = false; } @@ -110,30 +125,71 @@ export type PollEvmLogsMetadata = { lastBlock: bigint; }; -export class PollEvmLogsConfig { +export interface PollEvmLogsConfigProps { fromBlock?: bigint; toBlock?: bigint; blockBatchSize?: number; commitment?: string; interval?: number; - addresses: string[] = []; - topics: string[] = []; + addresses: string[]; + topics: string[]; + id?: string; +} + +export class PollEvmLogsConfig { + private props: PollEvmLogsConfigProps; + + constructor(props: PollEvmLogsConfigProps = { addresses: [], topics: [] }) { + if (props.fromBlock && props.toBlock && props.fromBlock > props.toBlock) { + throw new Error("fromBlock must be less than or equal to toBlock"); + } + + this.props = props; + } public getBlockBatchSize() { - return this.blockBatchSize ?? 100; + return this.props.blockBatchSize ?? 100; } public getCommitment() { - return this.commitment ?? "latest"; + return this.props.commitment ?? "latest"; } - public hasFinished(currentFromBlock: bigint) { - return this.toBlock && currentFromBlock > this.toBlock; + public hasFinished(currentFromBlock?: bigint) { + return currentFromBlock && this.props.toBlock && currentFromBlock >= this.props.toBlock; + } + + public get fromBlock() { + return this.props.fromBlock; + } + + public setFromBlock(fromBlock: bigint | undefined) { + this.props.fromBlock = fromBlock; + } + + public get toBlock() { + return this.props.toBlock; + } + + public get interval() { + return this.props.interval; + } + + public get addresses() { + return this.props.addresses; + } + + public get topics() { + return this.props.topics; + } + + public get id() { + return this.props.id ?? ID; } static fromBlock(fromBlock: bigint) { const cfg = new PollEvmLogsConfig(); - cfg.fromBlock = fromBlock; + cfg.props.fromBlock = fromBlock; return cfg; } } diff --git a/blockchain-watcher/src/domain/entities.ts b/blockchain-watcher/src/domain/entities.ts index c67267f1..2fd453ba 100644 --- a/blockchain-watcher/src/domain/entities.ts +++ b/blockchain-watcher/src/domain/entities.ts @@ -1,11 +1,11 @@ export type EvmBlock = { number: bigint; hash: string; - timestamp: bigint; // epoch millis + timestamp: number; // epoch seconds }; export type EvmLog = { - blockTime: bigint; + blockTime?: number; // epoch seconds blockNumber: bigint; blockHash: string; address: string; @@ -36,7 +36,7 @@ export type LogFoundEvent = { chainId: number; txHash: string; blockHeight: bigint; - blockTime: bigint; + blockTime: number; attributes: T; }; diff --git a/blockchain-watcher/src/infrastructure/RepositoriesBuilder.ts b/blockchain-watcher/src/infrastructure/RepositoriesBuilder.ts new file mode 100644 index 00000000..33566aa6 --- /dev/null +++ b/blockchain-watcher/src/infrastructure/RepositoriesBuilder.ts @@ -0,0 +1,89 @@ +import { SNSClient, SNSClientConfig } from "@aws-sdk/client-sns"; +import { Config } from "./config"; +import { + SnsEventRepository, + EvmJsonRPCBlockRepository, + EvmJsonRPCBlockRepositoryCfg, + FileMetadataRepo, +} from "./repositories"; +import axios, { AxiosInstance } from "axios"; +import axiosRateLimit from "axios-rate-limit"; + +export class RepositoriesBuilder { + private cfg: Config; + private snsClient?: SNSClient; + private axiosInstance?: AxiosInstance; + private repositories = new Map(); + + constructor(cfg: Config) { + this.cfg = cfg; + this.build(); + } + + private build() { + this.snsClient = this.createSnsClient(); + this.axiosInstance = this.createAxios(); + + this.repositories.set("sns", new SnsEventRepository(this.snsClient, this.cfg.sns)); + + this.cfg.metadata?.dir && + this.repositories.set("metadata", new FileMetadataRepo(this.cfg.metadata.dir)); + + this.cfg.supportedChains.forEach((chain) => { + const repoCfg: EvmJsonRPCBlockRepositoryCfg = { + chain, + rpc: this.cfg.platforms[chain].rpcs[0], + timeout: this.cfg.platforms[chain].timeout, + }; + this.repositories.set( + `${chain}-evmRepo`, + new EvmJsonRPCBlockRepository(repoCfg, this.axiosInstance!) + ); + }); + } + + public getEvmBlockRepository(chain: string): EvmJsonRPCBlockRepository { + const repo = this.repositories.get(`${chain}-evmRepo`); + if (!repo) throw new Error(`No EvmJsonRPCBlockRepository for chain ${chain}`); + + return repo; + } + + public getSnsEventRepository(): SnsEventRepository { + const repo = this.repositories.get("sns"); + if (!repo) throw new Error(`No SnsEventRepository`); + + return repo; + } + + public getMetadataRepository(): FileMetadataRepo { + const repo = this.repositories.get("metadata"); + if (!repo) throw new Error(`No FileMetadataRepo`); + + return repo; + } + + public close(): void { + this.snsClient?.destroy(); + } + + private createSnsClient(): SNSClient { + const snsCfg: SNSClientConfig = { region: this.cfg.sns.region }; + if (this.cfg.sns.credentials) { + snsCfg.credentials = { + accessKeyId: this.cfg.sns.credentials.accessKeyId, + secretAccessKey: this.cfg.sns.credentials.secretAccessKey, + }; + snsCfg.endpoint = this.cfg.sns.credentials.url; + } + + return new SNSClient(snsCfg); + } + + private createAxios() { + return axiosRateLimit(axios.create(), { + perMilliseconds: 1000, + maxRequests: 1_000, + }); // TODO: configurable per repo + } +} diff --git a/blockchain-watcher/src/infrastructure/config.ts b/blockchain-watcher/src/infrastructure/config.ts new file mode 100644 index 00000000..456084ef --- /dev/null +++ b/blockchain-watcher/src/infrastructure/config.ts @@ -0,0 +1,34 @@ +import config from "config"; +import { SnsConfig } from "./repositories/SnsEventRepository"; + +export type Config = { + environment: "testnet" | "mainnet"; + dryRun: boolean; + sns: SnsConfig; + metadata?: { + dir: string; + }; + platforms: Record; + supportedChains: string[]; +}; + +export type PlatformConfig = { + name: string; + network: string; + chainId: number; + rpcs: string[]; + timeout?: number; +}; + +// By setting NODE_CONFIG_ENV we can point to a different config directory. +// Default settings can be customized by definining NODE_ENV=staging|production. +export const configuration = { + environment: config.get("environment"), + dryRun: config.get("dryRun") === "true" ? true : false, + sns: config.get("sns"), + metadata: { + dir: config.get("metadata.dir"), + }, + platforms: config.get>("platforms"), + supportedChains: config.get("supportedChains"), +} as Config; diff --git a/blockchain-watcher/src/infrastructure/mappers/evmLogMessagePublishedMapper.ts b/blockchain-watcher/src/infrastructure/mappers/evmLogMessagePublishedMapper.ts index ab678646..3d9ed459 100644 --- a/blockchain-watcher/src/infrastructure/mappers/evmLogMessagePublishedMapper.ts +++ b/blockchain-watcher/src/infrastructure/mappers/evmLogMessagePublishedMapper.ts @@ -5,6 +5,10 @@ export const evmLogMessagePublishedMapper = ( log: EvmLog, parsedArgs: ReadonlyArray ): LogFoundEvent => { + if (!log.blockTime) { + throw new Error(`Block time is missing for log ${log.logIndex} in tx ${log.transactionHash}`); + } + return { name: "log-message-published", chainId: 2, // TODO: get from config diff --git a/blockchain-watcher/src/infrastructure/repositories/EvmJsonRPCBlockRepository.ts b/blockchain-watcher/src/infrastructure/repositories/EvmJsonRPCBlockRepository.ts new file mode 100644 index 00000000..ec3b9d09 --- /dev/null +++ b/blockchain-watcher/src/infrastructure/repositories/EvmJsonRPCBlockRepository.ts @@ -0,0 +1,197 @@ +import { EvmBlock, EvmLogFilter, EvmLog, EvmTag } from "../../domain/entities"; +import { EvmBlockRepository } from "../../domain/repositories"; +import { AxiosInstance } from "axios"; + +const headers = { + "Content-Type": "application/json", +}; + +/** + * EvmJsonRPCBlockRepository is a repository that uses a JSON RPC endpoint to fetch blocks. + * On the reliability side, only knows how to timeout. + */ +export class EvmJsonRPCBlockRepository implements EvmBlockRepository { + private axios: AxiosInstance; + private chain: string; + private rpc: URL; + private timeout: number; + + constructor(cfg: EvmJsonRPCBlockRepositoryCfg, axios: AxiosInstance) { + this.chain = cfg.chain; + this.axios = axios; + this.rpc = new URL(cfg.rpc); + this.timeout = cfg.timeout ?? 10_000; + } + + async getBlockHeight(finality: EvmTag): Promise { + const block: EvmBlock = await this.getBlock(finality); + return block.number; + } + + /** + * Get blocks by block number. + * @param blockNumbers + * @returns a record of block hash -> EvmBlock + */ + async getBlocks(blockNumbers: Set): Promise> { + if (!blockNumbers.size) return {}; + + const reqs: any[] = []; + for (let blockNumber of blockNumbers) { + const blockNumberStr = blockNumber.toString(); + reqs.push({ + jsonrpc: "2.0", + id: blockNumberStr, + method: "eth_getBlockByNumber", + params: [blockNumberStr, false], + }); + } + const results = (await this.axios.post(this.rpc.href, reqs, this.getRequestOptions()))?.data; + if (results && results.length) { + return results + .map( + ( + response: undefined | { id: string; result?: EvmBlock; error?: ErrorBlock }, + idx: number + ) => { + // Karura is getting 6969 errors for some blocks, so we'll just return empty blocks for those instead of throwing an error. + // We take the timestamp from the previous block, which is not ideal but should be fine. + if ( + (response && response.result === null) || + (response?.error && response.error?.code && response.error.code === 6969) + ) { + return { + hash: "", + number: BigInt(response.id), + timestamp: Date.now(), // TODO: we might just want to return the timestamp of the previous block or do something at a client level when not found + }; + } + if ( + response?.result && + response.result?.hash && + response.result.number && + response.result.timestamp + ) { + return { + hash: response.result.hash, + number: BigInt(response.result.number), + timestamp: Number(response.result.timestamp), + }; + } + console.error(reqs[idx], response, idx); // TODO: use an actual logger + throw new Error( + `Unable to parse result of eth_getBlockByNumber for ${ + response?.id ?? reqs[idx].id + } on ${this.rpc.hostname}` + ); + } + ) + .reduce((acc: Record, block: EvmBlock) => { + acc[block.hash] = block; + return acc; + }, {}); + } + throw new Error( + `Unable to parse result of eth_getBlockByNumber for numbers ${blockNumbers} on ${this.rpc.hostname}` + ); + } + + async getFilteredLogs(filter: EvmLogFilter): Promise { + const parsedFilters = { + topics: filter.topics, + address: filter.addresses, + fromBlock: filter.fromBlock.toString(), + toBlock: filter.toBlock.toString(), + }; + + let response = await this.axios.post<{ result: Log[]; error?: ErrorBlock }>( + this.rpc.href, + { + jsonrpc: "2.0", + method: "eth_getLogs", + params: [parsedFilters], + id: 1, + }, + this.getRequestOptions() + ); + + if (response?.data.error) { + throw new Error( + `Got error ${response?.data.error.message} for ${this.describeFilter(filter)} from ${ + this.rpc.hostname + }` + ); + } + const logs = response?.data?.result; + console.info( + `Got ${logs?.length} logs for ${this.describeFilter(filter)} from ${this.rpc.hostname}` + ); + + return logs.map((log) => ({ + ...log, + blockNumber: BigInt(log.blockNumber), + transactionIndex: log.transactionIndex.toString(), + })); + } + + private describeFilter(filter: EvmLogFilter): string { + return `[addresses:${filter.addresses}][topics:${filter.topics}][blocks:${filter.fromBlock} - ${filter.toBlock}]`; + } + + /** + * Loosely based on the wormhole-dashboard implementation (minus some specially crafted blocks when null result is obtained) + */ + private async getBlock(blockNumberOrTag: bigint | EvmTag): Promise { + let response = await this.axios.post( + this.rpc.href, + { + jsonrpc: "2.0", + method: "eth_getBlockByNumber", + params: [blockNumberOrTag.toString(), false], // this means we'll get a light block (no txs) + id: 1, + }, + this.getRequestOptions() + ); + + const result = response?.data?.result; + + if (result && result.hash && result.number && result.timestamp) { + // Convert to our domain compatible type + return { + number: BigInt(result.number), + timestamp: Number(result.timestamp), + hash: result.hash, + }; + } + throw new Error( + `Unable to parse result of eth_getBlockByNumber for ${blockNumberOrTag} on ${this.rpc}` + ); + } + + private getRequestOptions() { + return { headers, timeout: this.timeout, signal: AbortSignal.timeout(this.timeout) }; + } +} + +export type EvmJsonRPCBlockRepositoryCfg = { + rpc: string; + timeout?: number; + chain: string; +}; + +type ErrorBlock = { + code: number; //6969, + message: string; //'Error: No response received from RPC endpoint in 60s' +}; + +type Log = { + blockNumber: string; + blockHash: string; + transactionIndex: number; + removed: boolean; + address: string; + data: string; + topics: Array; + transactionHash: string; + logIndex: number; +}; diff --git a/blockchain-watcher/src/infrastructure/repositories/FileMetadataRepo.ts b/blockchain-watcher/src/infrastructure/repositories/FileMetadataRepo.ts new file mode 100644 index 00000000..929851b3 --- /dev/null +++ b/blockchain-watcher/src/infrastructure/repositories/FileMetadataRepo.ts @@ -0,0 +1,27 @@ +import fs from "fs"; +import { MetadataRepository } from "../../domain/repositories"; + +export class FileMetadataRepo implements MetadataRepository { + private readonly dirPath: string; + + constructor(dirPath: string) { + this.dirPath = dirPath; + } + + async get(id: string): Promise { + const filePath = `${this.dirPath}/${id}.json`; + if (!fs.existsSync(this.dirPath)) { + fs.mkdirSync(this.dirPath); + } + + return fs.promises + .readFile(filePath, "utf8") + .then(JSON.parse) + .catch((err) => null); + } + + async save(id: string, metadata: any): Promise { + const filePath = `${this.dirPath}/${id}.json`; + return fs.promises.writeFile(filePath, JSON.stringify(metadata), "utf8"); + } +} diff --git a/blockchain-watcher/src/infrastructure/repositories/SnsEventRepository.ts b/blockchain-watcher/src/infrastructure/repositories/SnsEventRepository.ts new file mode 100644 index 00000000..257d1c36 --- /dev/null +++ b/blockchain-watcher/src/infrastructure/repositories/SnsEventRepository.ts @@ -0,0 +1,172 @@ +import { LogFoundEvent } from "../../domain/entities"; +import crypto from "node:crypto"; +import { + SNSClient, + PublishBatchCommand, + PublishBatchCommandInput, + PublishBatchRequestEntry, +} from "@aws-sdk/client-sns"; +import winston from "winston"; + +const CHUNK_SIZE = 10; + +export class SnsEventRepository { + private client: SNSClient; + private cfg: SnsConfig; + private logger: typeof winston; + + constructor(snsClient: SNSClient, cfg: SnsConfig) { + console.log(`SNSRepo: Created for topic ${cfg.topicArn}`); + this.client = snsClient; + this.cfg = cfg; + this.logger = winston; + } + + async publish(events: LogFoundEvent[]): Promise { + if (!events.length) { + console.log("No events to publish"); + return { + status: "success", + }; + } + + const batches: PublishBatchCommandInput[] = []; + const inputs: PublishBatchRequestEntry[] = events.map((event) => ({ + Id: crypto.randomUUID(), + Subject: this.cfg.subject ?? "blockchain-watcher", + Message: JSON.stringify(event), + MessageGroupId: this.cfg.groupId ?? "blockchain-watcher", + MessageDeduplicationId: `${event.chainId}-${event.txHash}-${event.blockHeight}-${event.name}`, + })); + + // PublishBatchCommand: only supports max 10 items per batch + for (let i = 0; i < inputs.length; i += CHUNK_SIZE) { + const batch: PublishBatchCommandInput = { + TopicArn: this.cfg.topicArn, + PublishBatchRequestEntries: inputs.slice(i, i + CHUNK_SIZE), + }; + + batches.push(batch); + } + + try { + const promises = []; + const errors = []; + for (const batch of batches) { + const command = new PublishBatchCommand(batch); + promises.push(this.client.send(command)); + } + + const results = await Promise.allSettled(promises); + + for (const result of results) { + if (result.status !== "fulfilled") { + this.logger.error(result.reason); + errors.push(result.reason); + } + } + + if (errors.length > 0) { + return { + status: "error", + reasons: errors, + }; + } + } catch (error: unknown) { + this.logger.error(error); + + return { + status: "error", + }; + } + + return { + status: "success", + }; + } +} + +export class SnsEvent { + trackId: string; + source: string; + event: string; + timestamp: string; + version: string; + data: Record; + + constructor( + trackId: string, + source: string, + event: string, + timestamp: string, + version: string, + data: Record + ) { + this.trackId = trackId; + this.source = source; + this.event = event; + this.timestamp = timestamp; + this.version = version; + this.data = data; + } + + static fromLogFoundEvent(logFoundEvent: LogFoundEvent): SnsEvent { + return new SnsEvent( + `chain-event-${logFoundEvent.txHash}-${logFoundEvent.blockHeight}`, + "blockchain-watcher", + logFoundEvent.name, + new Date().toISOString(), + "1", + { + chainId: logFoundEvent.chainId, + emitterAddress: logFoundEvent.name, + txHash: logFoundEvent.txHash, + blockHeight: logFoundEvent.blockHeight.toString(), + blockTime: new Date(logFoundEvent.blockTime * 1000).toISOString(), + attributes: logFoundEvent.attributes, + } + ); + } +} + +export type SnsConfig = { + region: string; + topicArn: string; + subject?: string; + groupId: string; + credentials?: { + accessKeyId: string; + secretAccessKey: string; + url: string; + }; +}; + +export type SnsPublishResult = { + status: "success" | "error"; + reason?: string; + reasons?: string[]; +}; + +/* + { + "trackId": "chain-event-{txId}-{position}", + "source": "blockchain-watcher", + "event": "log-message-published", + "timestamp": string (timestamp in RFC3339 format) + "version": "1", + "data": { + "chainId": number, + "emitterAddress": string, + "txHash": string, + "blockHeight": string, + "blockTime": string (timestamp in RFC3339 format), + "attributes": { + "sender": string, + "sequence": number, + "nonce": number, + "payload": bytes, + "consistencyLevel": number + } + } + } + */ diff --git a/blockchain-watcher/src/infrastructure/repositories/index.ts b/blockchain-watcher/src/infrastructure/repositories/index.ts new file mode 100644 index 00000000..4deebebe --- /dev/null +++ b/blockchain-watcher/src/infrastructure/repositories/index.ts @@ -0,0 +1,12 @@ +// Monkey patching BigInt serialization +if (!("toJSON" in BigInt.prototype)) { + Object.defineProperty(BigInt.prototype, "toJSON", { + get() { + return () => String(this); + }, + }); +} + +export * from "./FileMetadataRepo"; +export * from "./SnsEventRepository"; +export * from "./EvmJsonRPCBlockRepository"; diff --git a/blockchain-watcher/src/start.ts b/blockchain-watcher/src/start.ts new file mode 100644 index 00000000..e095aa74 --- /dev/null +++ b/blockchain-watcher/src/start.ts @@ -0,0 +1,98 @@ +import { HandleEvmLogs } from "./domain/actions/HandleEvmLogs"; +import { PollEvmLogs, PollEvmLogsConfig } from "./domain/actions/PollEvmLogs"; +import { LogFoundEvent } from "./domain/entities"; +import { configuration } from "./infrastructure/config"; +import { evmLogMessagePublishedMapper } from "./infrastructure/mappers/evmLogMessagePublishedMapper"; +import { RepositoriesBuilder } from "./infrastructure/RepositoriesBuilder"; + +let repos: RepositoriesBuilder; + +async function run(): Promise { + console.log(`Starting: dryRunEnabled -> ${configuration.dryRun}`); + + repos = new RepositoriesBuilder(configuration); + + /** Job definition is hardcoded, but should be loaded from cfg or a data store soon enough */ + const jobs = [ + { + id: "poll-log-message-published-ethereum", + chain: "ethereum", + source: { + action: "PollEvmLogs", + config: { + fromBlock: 10012499n, + toBlock: 10012999n, + blockBatchSize: 100, + commitment: "latest", + interval: 15_000, + addresses: ["0x706abc4E45D419950511e474C7B9Ed348A4a716c"], + topics: [], + }, + }, + handlers: [ + { + action: "HandleEvmLogs", + target: "sns", + mapper: "evmLogMessagePublishedMapper", + config: { + abi: "event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel)", + filter: { + addresses: ["0x706abc4E45D419950511e474C7B9Ed348A4a716c"], + topics: ["0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2"], + }, + }, + }, + ], + }, + ]; + + const pollEvmLogs = new PollEvmLogs( + repos.getEvmBlockRepository("ethereum"), + repos.getMetadataRepository(), + new PollEvmLogsConfig({ ...jobs[0].source.config, id: jobs[0].id }) + ); + + const snsTarget = async (events: LogFoundEvent[]) => { + const result = await repos.getSnsEventRepository().publish(events); + if (result.status === "error") { + console.error(`Error publishing events to SNS: ${result.reason ?? result.reasons}`); + throw new Error(`Error publishing events to SNS: ${result.reason}`); + } + console.log(`Published ${events.length} events to SNS`); + }; + const handleEvmLogs = new HandleEvmLogs>( + jobs[0].handlers[0].config, + evmLogMessagePublishedMapper, + configuration.dryRun ? async (events) => console.log(`Got ${events.length} events`) : snsTarget + ); + + pollEvmLogs.start([handleEvmLogs.handle.bind(handleEvmLogs)]); + + // Just keep this running until killed + setInterval(() => { + console.log("Still running"); + }, 20_000); + + console.log("Started"); + // Handle shutdown + process.on("SIGINT", handleShutdown); + process.on("SIGTERM", handleShutdown); +} + +const handleShutdown = async () => { + try { + await Promise.allSettled([ + repos.close(), + // call stop() on all the things + ]); + + process.exit(); + } catch (error: unknown) { + process.exit(1); + } +}; + +run().catch((e) => { + console.error(e); + console.error("Fatal error caused process to exit"); +}); diff --git a/blockchain-watcher/test/domain/HandleEvmLogs.test.ts b/blockchain-watcher/test/domain/HandleEvmLogs.test.ts index da7b167a..ef257335 100644 --- a/blockchain-watcher/test/domain/HandleEvmLogs.test.ts +++ b/blockchain-watcher/test/domain/HandleEvmLogs.test.ts @@ -10,7 +10,7 @@ const mapper = (log: EvmLog, args: ReadonlyArray) => { chainId: 1, txHash: "0x0", blockHeight: 0n, - blockTime: 0n, + blockTime: 0, attributes: { sequence: args[0].toString(), deliveryQuote: args[1].toString(), @@ -74,13 +74,13 @@ const givenEvmLogs = (length: number, matchingFilterOnes: number) => { let address = "0x392f472048681816e91026cd768c60958b55352add2837adea9ea6249178b8a8"; let topic: string | undefined = undefined; if (matchingCount < matchingFilterOnes) { - address = cfg.filter.addresses![0]; + address = cfg.filter.addresses![0].toUpperCase(); topic = cfg.filter.topics![0]; matchingCount++; } evmLogs.push({ - blockTime: 0n, + blockTime: 0, blockNumber: BigInt(i + 1), blockHash: "0x1a07d0bd31c84f0dab36eac31a2f3aa801852bf8240ffba19113c62463f694fa", address: address, diff --git a/blockchain-watcher/test/domain/PollEvmLogs.test.ts b/blockchain-watcher/test/domain/PollEvmLogs.test.ts index dbea79c4..894dd8e1 100644 --- a/blockchain-watcher/test/domain/PollEvmLogs.test.ts +++ b/blockchain-watcher/test/domain/PollEvmLogs.test.ts @@ -28,22 +28,23 @@ describe("PollEvmLogs", () => { await pollEvmLogs.stop(); }); - it("should be able to read logs from given start", async () => { + it("should be able to read logs from latest block when no fromBlock is configured", async () => { const currentHeight = 10n; const blocksAhead = 1n; givenEvmBlockRepository(currentHeight, blocksAhead); givenMetadataRepository(); - givenPollEvmLogs(currentHeight); + givenPollEvmLogs(); await whenPollEvmLogsStarts(); await thenWaitForAssertion( + () => expect(getBlocksSpy).toHaveReturnedTimes(1), () => expect(getBlocksSpy).toHaveBeenCalledWith(new Set([currentHeight, currentHeight + 1n])), () => expect(getLogsSpy).toBeCalledWith({ addresses: cfg.addresses, topics: cfg.topics, - fromBlock: currentHeight, + fromBlock: currentHeight + blocksAhead, toBlock: currentHeight + blocksAhead, }) ); @@ -100,7 +101,7 @@ const givenEvmBlockRepository = (height?: bigint, blocksAhead?: bigint) => { logsResponse.push({ blockNumber: height + index, blockHash: `0x0${index}`, - blockTime: 0n, + blockTime: 0, address: "", removed: false, data: "", @@ -110,7 +111,7 @@ const givenEvmBlockRepository = (height?: bigint, blocksAhead?: bigint) => { logIndex: 0, }); blocksResponse[`0x0${index}`] = { - timestamp: 0n, + timestamp: 0, hash: `0x0${index}`, number: height + index, }; @@ -137,7 +138,7 @@ const givenMetadataRepository = (data?: PollEvmLogsMetadata) => { }; const givenPollEvmLogs = (from?: bigint) => { - cfg.fromBlock = from ?? cfg.fromBlock; + cfg.setFromBlock(from); pollEvmLogs = new PollEvmLogs(evmBlockRepo, metadataRepo, cfg); }; @@ -153,10 +154,10 @@ const thenWaitForAssertion = async (...assertions: (() => void)[]) => { } break; } catch (error) { - await setTimeout(10, undefined, { ref: false }); if (index === 4) { throw error; } + await setTimeout(10, undefined, { ref: false }); } } }; diff --git a/blockchain-watcher/test/infrastructure/mappers/evmLogMessagePublished.test.ts b/blockchain-watcher/test/infrastructure/mappers/evmLogMessagePublished.test.ts index 78c37172..e9a96ad6 100644 --- a/blockchain-watcher/test/infrastructure/mappers/evmLogMessagePublished.test.ts +++ b/blockchain-watcher/test/infrastructure/mappers/evmLogMessagePublished.test.ts @@ -19,7 +19,7 @@ describe("evmLogMessagePublished", () => { it("should be able to map log to LogMessagePublished", async () => { const [result] = await handler.handle([ { - blockTime: 1699375895n, + blockTime: 1699443287, blockNumber: 18521386n, blockHash: "0x894136d03446d47116319d59b5ec3190c05248e16c8728c2848bf7452732341c", address: "0x98f3c9e6e3face36baad05fe09d375ef1464288b", @@ -38,7 +38,7 @@ describe("evmLogMessagePublished", () => { "0xcbdefc83080a8f60cbde7785eb2978548fd5c1f7d0ea2c024cce537845d339c7" ); expect(result.blockHeight).toBe(18521386n); - expect(result.blockTime).toBe(1699375895n); + expect(result.blockTime).toBe(1699443287); expect(result.attributes.sequence).toBe(135858); expect(result.attributes.sender.toLowerCase()).toBe( diff --git a/blockchain-watcher/test/infrastructure/repositories/EvmJsonRPCBlockRepository.integration.test.ts b/blockchain-watcher/test/infrastructure/repositories/EvmJsonRPCBlockRepository.integration.test.ts new file mode 100644 index 00000000..0c96d49e --- /dev/null +++ b/blockchain-watcher/test/infrastructure/repositories/EvmJsonRPCBlockRepository.integration.test.ts @@ -0,0 +1,184 @@ +import { describe, it, expect, afterEach, afterAll } from "@jest/globals"; +import { EvmJsonRPCBlockRepository } from "../../../src/infrastructure/repositories"; +import axios from "axios"; +import nock from "nock"; +import { EvmLogFilter, EvmTag } from "../../../src/domain/entities"; + +axios.defaults.adapter = "http"; // needed by nock +const axiosInstance = axios.create(); +const rpc = "http://localhost"; +const address = "0x98f3c9e6e3face36baad05fe09d375ef1464288b"; +const topic = "0x6eb224fb001ed210e379b335e35efe88672a8ce935d981a6896b27ffdf52a3b2"; +const txHash = "0xcbdefc83080a8f60cbde7785eb2978548fd5c1f7d0ea2c024cce537845d339c7"; + +let repo: EvmJsonRPCBlockRepository; + +describe("EvmJsonRPCBlockRepository", () => { + afterAll(() => { + nock.restore(); + }); + + afterEach(() => { + nock.cleanAll(); + }); + + it("should be able to get block height", async () => { + const expectedHeight = 1980809n; + givenARepo(); + givenBlockHeightIs(expectedHeight, "latest"); + + const result = await repo.getBlockHeight("latest"); + + expect(result).toBe(expectedHeight); + }); + + it("should be able to get several blocks", async () => { + const blockNumbers = [2n, 3n, 4n]; + givenARepo(); + givenBlocksArePresent(blockNumbers); + + const result = await repo.getBlocks(new Set(blockNumbers)); + + expect(Object.keys(result)).toHaveLength(blockNumbers.length); + blockNumbers.forEach((blockNumber) => { + expect(result[blockHash(blockNumber)].number).toBe(blockNumber); + }); + }); + + it("should be able to get logs", async () => { + const filter: EvmLogFilter = { + fromBlock: "safe", + toBlock: "latest", + addresses: [address], + topics: [], + }; + + givenLogsPresent(filter); + + const logs = await repo.getFilteredLogs(filter); + + expect(logs).toHaveLength(1); + expect(logs[0].blockNumber).toBe(1n); + expect(logs[0].blockHash).toBe(blockHash(1n)); + expect(logs[0].address).toBe(address); + }); +}); + +const givenARepo = () => { + repo = new EvmJsonRPCBlockRepository({ rpc, timeout: 100, chain: "ethereum" }, axiosInstance); +}; + +const givenBlockHeightIs = (height: bigint, commitment: EvmTag) => { + nock(rpc) + .post("/", { + jsonrpc: "2.0", + method: "eth_getBlockByNumber", + params: [commitment, false], + id: 1, + }) + .reply(200, { + jsonrpc: "2.0", + id: 1, + result: { + number: `0x${height.toString(16)}`, + hash: blockHash(height), + timestamp: "0x654a892f", + }, + }); +}; + +const givenBlocksArePresent = (blockNumbers: bigint[]) => { + const requests = blockNumbers.map((blockNumber) => ({ + jsonrpc: "2.0", + method: "eth_getBlockByNumber", + params: [blockNumber.toString(), false], + id: blockNumber.toString(), + })); + const response = blockNumbers.map((blockNumber) => ({ + jsonrpc: "2.0", + id: blockNumber.toString(), + result: { + number: `0x${blockNumber.toString(16)}`, + hash: blockHash(blockNumber), + timestamp: "0x654a892f", + }, + })); + + nock(rpc).post("/", requests).reply(200, response); +}; + +const givenLogsPresent = (filter: EvmLogFilter) => { + const response = { + jsonrpc: "2.0", + id: 1, + result: [ + { + address: filter.addresses[0], + topics: [topic], + data: "0x", + blockNumber: "0x1", + blockHash: blockHash(1n), + transactionHash: txHash, + transactionIndex: "0x0", + logIndex: 0, + removed: false, + }, + ], + }; + + nock(rpc).post("/").reply(200, response); +}; + +const blockHash = (blockNumber: bigint) => `0x${blockNumber.toString(16)}`; + +/* Examples: + - blockByNumber: + { + "jsonrpc":"2.0", + "method":"eth_getBlockByNumber", + "params":[ + "latest", + true + ], + "id":1 + } + -> + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "baseFeePerGas": "0x78d108bbb", + "difficulty": "0x0", + "extraData": "0x406275696c64657230783639", + "gasLimit": "0x1c9c380", + "gasUsed": "0xfca882", + "hash": "0xb29ad2fa313f50d293fcf5679c6862ee7f4a3d641f09b227ad0ee3fba10d1cbb", + "logsBloom": "0x312390b5e798baf83b514972932b522118d98b9888f5880461db7e26f4bece2e8141717140d492028f887928435127083671a3488c3b6c240130a6eeb3692d908417d91c65fbfd396d0ade2b57a263a080c64f59fb4d3c4033415503e833306057524072daeae803a45cc020c1a32f436f30037b49003cd257c965d9214b441922012654b681e5202053a7d58500a64aa040cec9d90a0c9e5e3321d821503d90cfb84961594a72f02e92c7c2559d95c86504c54260c708ea63e5e4a2538f1143096c2422250a0a20b321a8814678d26e6a6d6a872e232a500a402a3a6445b85b3cf92b481e9020c20a969eac4c50ca08667cda68812f8141108908b3d175f649", + "miner": "0x690b9a9e9aa1c9db991c7721a92d351db4fac990", + "mixHash": "0xbdeea2aa4f2a026b27bc720d28c73680a35ad3e5017568cddcb066b5c12b1f60", + "nonce": "0x0000000000000000", + "number": "0x11a9fa9", + "parentHash": "0x7f8c4ecd8772eab825ee3c8e713c5088c6a32b41d61dbd1c0833e7d4df337713", + "receiptsRoot": "0x06e3cd06761468089708b204a092545576c508739f0eff936c96914da2e277e9", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "size": "0x25301", + "stateRoot": "0x3e1333543583ec7e5fb4e337261c43ef94aeb4f77c4e7f657a538fc3c2e5b6de", + "timestamp": "0x654a892f", + "totalDifficulty": "0xc70d815d562d3cfa955", + "transactions": [ + "0x5e59c0bb917e7a5a64f098cd6a370bac4f40ecdf6ca79deaccf25736fe117ef7" + ], + "transactionsRoot": "0xbf23b57ac6f6aede4d886a556b7bbee868721542b9a1d912ffa5f4ead0b8ec72", + "uncles": [], + "withdrawals": [ + { + "index": "0x16b0d86", + "validatorIndex": "0x2a57b", + "address": "0xdaac5ce35ad7892d5f2dd364954066f4323c9a57", + "amount": "0x105fdec" + } + ] + } + } + - blockByHash: +*/ diff --git a/blockchain-watcher/test/infrastructure/repositories/FileMetadataRepo.test.ts b/blockchain-watcher/test/infrastructure/repositories/FileMetadataRepo.test.ts new file mode 100644 index 00000000..77d0e9db --- /dev/null +++ b/blockchain-watcher/test/infrastructure/repositories/FileMetadataRepo.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; +import fs from "fs"; +import { FileMetadataRepo } from "../../../src/infrastructure/repositories"; + +describe("FileMetadataRepo", () => { + const dirPath = "./metadata-repo"; + const repo = new FileMetadataRepo(dirPath); + + beforeEach(() => { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath); + } + }); + + afterEach(() => { + fs.rm(dirPath, () => {}); + }); + + describe("get", () => { + it("should return null if the file does not exist", async () => { + const metadata = await repo.get("non-existent-file"); + expect(metadata).toBeNull(); + }); + + it("should return the metadata if the file exists", async () => { + const id = "test-file"; + const metadata = { foo: "bar" }; + await repo.save(id, metadata); + + const retrievedMetadata = await repo.get(id); + expect(retrievedMetadata).toEqual(metadata); + }); + }); + + describe("save", () => { + it("should create a new file with the given metadata", async () => { + const id = "test-file"; + const metadata = { foo: "bar" }; + await repo.save(id, metadata); + + const fileExists = fs.existsSync(`${dirPath}/${id}.json`); + expect(fileExists).toBe(true); + + const fileContents = fs.readFileSync(`${dirPath}/${id}.json`, "utf8"); + expect(JSON.parse(fileContents)).toEqual(metadata); + }); + + it("should overwrite an existing file with the given metadata", async () => { + const id = "test-file"; + const initialMetadata = { foo: "bar" }; + const updatedMetadata = { baz: "qux" }; + await repo.save(id, initialMetadata); + await repo.save(id, updatedMetadata); + + const fileContents = fs.readFileSync(`${dirPath}/${id}.json`, "utf8"); + expect(JSON.parse(fileContents)).toEqual(updatedMetadata); + }); + }); +}); diff --git a/blockchain-watcher/test/infrastructure/repositories/SnsEventRepository.test.ts b/blockchain-watcher/test/infrastructure/repositories/SnsEventRepository.test.ts new file mode 100644 index 00000000..9365257e --- /dev/null +++ b/blockchain-watcher/test/infrastructure/repositories/SnsEventRepository.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it, jest } from "@jest/globals"; +import { SnsEventRepository, SnsConfig } from "../../../src/infrastructure/repositories"; +import { SNSClient } from "@aws-sdk/client-sns"; + +let snsEventRepository: SnsEventRepository; +let snsClient: SNSClient; +let snsConfig: SnsConfig; + +describe("SnsEventRepository", () => { + it("should not call sns client when no events given", async () => { + givenSnsEventRepository(); + + const result = await snsEventRepository.publish([]); + + expect(result).toEqual({ status: "success" }); + expect(snsClient.send).not.toHaveBeenCalled(); + }); + + it("should publish", async () => { + givenSnsEventRepository(); + + const result = await snsEventRepository.publish([ + { + chainId: 1, + txHash: "0x123", + blockHeight: 123n, + blockTime: 0, + name: "LogMessagePublished", + attributes: {}, + }, + ]); + + expect(result).toEqual({ status: "success" }); + expect(snsClient.send).toHaveBeenCalledTimes(1); + }); +}); + +const givenSnsEventRepository = () => { + snsConfig = { + region: "us-east-1", + topicArn: "arn:aws:sns:us-east-1:123456789012:MyTopic", + groupId: "groupId", + subject: "subject", + }; + snsClient = { + send: jest.fn().mockReturnThis(), + } as unknown as SNSClient; + snsEventRepository = new SnsEventRepository(snsClient, snsConfig); +}; diff --git a/deploy/blockchain-watcher/env/staging-testnet.env b/deploy/blockchain-watcher/env/staging-testnet.env new file mode 100644 index 00000000..133c196e --- /dev/null +++ b/deploy/blockchain-watcher/env/staging-testnet.env @@ -0,0 +1,17 @@ +NODE_ENV=staging +BLOCKCHAIN_ENV=testnet +NAMESPACE=wormscan-testnet +NAME=blockchain-watcher +DRY_RUN_ENABLED=false +REPLICAS=1 +IMAGE_NAME= +PORT=3005 +LOG_LEVEL=info + +RESOURCES_LIMITS_MEMORY=256Mi +RESOURCES_LIMITS_CPU=200m +RESOURCES_REQUESTS_MEMORY=128Mi +RESOURCES_REQUESTS_CPU=100m + +SNS_TOPIC_ARN= +SNS_REGION= diff --git a/deploy/blockchain-watcher/metadata-pv.yaml b/deploy/blockchain-watcher/metadata-pv.yaml new file mode 100644 index 00000000..3e6267ec --- /dev/null +++ b/deploy/blockchain-watcher/metadata-pv.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: blockchain-watcher-metadata-pvc + namespace: {{ .NAMESPACE }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Mi + storageClassName: gp2 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: blockchain-watcher-metadata-pv + namespace: {{ .NAMESPACE }} +spec: + accessModes: + - ReadWriteOnce + - ReadWriteMany + capacity: + storage: 50Mi + storageClassName: gp2 + hostPath: + path: /home/node/app/metadata-repo \ No newline at end of file diff --git a/deploy/blockchain-watcher/stateful-set.yaml b/deploy/blockchain-watcher/stateful-set.yaml new file mode 100644 index 00000000..ac3ee9ec --- /dev/null +++ b/deploy/blockchain-watcher/stateful-set.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ .NAME }} + namespace: {{ .NAMESPACE }} +spec: + replicas: {{ .REPLICAS }} + serviceName: {{ .NAME }}-service + selector: + matchLabels: + app: {{ .NAME }} + template: + metadata: + labels: + app: {{ .NAME }} + spec: + restartPolicy: Always + terminationGracePeriodSeconds: 30 + serviceAccountName: event-watcher + containers: + - name: {{ .NAME }} + image: {{ .IMAGE_NAME }} + env: + - name: NODE_ENV + value: {{ .NODE_ENV }} + - name: PORT + value: "{{ .PORT }}" + - name: LOG_LEVEL + value: {{ .LOG_LEVEL }} + - name: BLOCKCHAIN_ENV + value: {{ .BLOCKCHAIN_ENV }} + - name: DRY_RUN_ENABLED + value: "{{ .DRY_RUN_ENABLED }}" + - name: SNS_TOPIC_ARN + value: {{ .SNS_TOPIC_ARN }} + - name: SNS_REGION + value: {{ .SNS_REGION }} + resources: + limits: + memory: {{ .RESOURCES_LIMITS_MEMORY }} + cpu: {{ .RESOURCES_LIMITS_CPU }} + requests: + memory: {{ .RESOURCES_REQUESTS_MEMORY }} + cpu: {{ .RESOURCES_REQUESTS_CPU }} + volumeMounts: + - name: metadata-volume + mountPath: /home/node/app/metadata-repo + volumes: + - name: metadata-volume + persistentVolumeClaim: + claimName: blockchain-watcher-metadata-pvc + \ No newline at end of file