diff --git a/.env.test b/.env.test index 5ab9791db..63ac498c4 100644 --- a/.env.test +++ b/.env.test @@ -1,5 +1,5 @@ THIRDWEB_API_SECRET_KEY="test" -POSTGRES_CONNECTION_URL="postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable" +POSTGRES_CONNECTION_URL="postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable&timezone=utc" ADMIN_WALLET_ADDRESS="test" ENCRYPTION_PASSWORD="test" ENABLE_KEYPAIR_AUTH="true" diff --git a/.gitignore b/.gitignore index 1c447602d..38fb2a3a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Generated SDK sdk/replacement_log.txt +.cursor + # Logs logs *.log diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index f3bcd4c90..000000000 --- a/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "singleQuote": false, - "trailingComma": "all" -} diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index 4f14322dc..000000000 --- a/.yarnrc +++ /dev/null @@ -1 +0,0 @@ ---ignore-engines true diff --git a/Dockerfile b/Dockerfile index 4cf99266f..8a44ed26c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,71 +1,31 @@ -FROM node:18.20-slim AS base - -WORKDIR /app - -# Upgrade packages -RUN apt-get -y update && \ - apt-get -y upgrade && \ - apt-get -y install libssl-dev - -############################## -############################## -############################## -############################## +FROM oven/bun:1 AS base +WORKDIR /usr/src/app # Generate cert for local https FROM base AS certs - -WORKDIR /app/src/https - -RUN apt-get -y install openssl - +WORKDIR /usr/src/app/src/https +RUN apt-get update && apt-get install -y openssl RUN openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 \ -subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=localhost" \ -passout pass:thirdweb-engine && \ chmod 600 key.pem cert.pem -############################## -############################## -############################## -############################## - -FROM base AS build - -# Install Python3-Pip -RUN apt-get -y install python3-pip - -# Copy the entire project directory -COPY . . - -# Install dependencies for both development and production (May need devDependencies to build) -# Build the project -# Prune dev dependencies from the packages -RUN yarn install --frozen-lockfile --production=false --network-timeout 1000000 && \ - yarn build && \ - yarn copy-files && \ - yarn install --frozen-lockfile --production=true --network-timeout 1000000 - -############################## -############################## -############################## -############################## - -FROM base AS prod - -EXPOSE 3005 +# Install dependencies +FROM base AS install +RUN mkdir -p /temp/prod +COPY package.json bun.lock /temp/prod/ +RUN cd /temp/prod && bun install --frozen-lockfile --production +# Final image +FROM base AS release ARG ENGINE_VERSION ENV ENGINE_VERSION=${ENGINE_VERSION} -ENV NODE_ENV="production" \ - PATH=/app/node_modules/.bin:$PATH - -COPY --from=certs /app/src/https ./dist/https -COPY --from=build /app/package.json . -COPY --from=build /app/node_modules ./node_modules -COPY --from=build /app/src/prisma/* ./src/prisma/ -COPY --from=build /app/dist ./dist +ENV NODE_ENV="production" -# Replace the schema path in the package.json file -RUN sed -i 's_"schema": "./src/prisma/schema.prisma"_"schema": "./dist/prisma/schema.prisma"_g' package.json +COPY --from=install /temp/prod/node_modules node_modules +COPY --from=certs /usr/src/app/src/https ./src/https +COPY . . -ENTRYPOINT [ "yarn", "start"] +USER bun +EXPOSE 3005 +ENTRYPOINT [ "bun", "run", "src/index.ts" ] diff --git a/biome.json b/biome.json index f173292df..0c4712e1b 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.2/schema.json", + "$schema": "https://biomejs.dev/schemas/2.0.0-beta.1/schema.json", "vcs": { "enabled": true, "clientKind": "git", @@ -10,14 +10,51 @@ "enabled": true, "indentStyle": "space" }, - "organizeImports": { - "enabled": true + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } }, "linter": { "enabled": true, "rules": { + "style": { + "useLiteralEnumMembers": "error", + "noCommaOperator": "error", + "useNodejsImportProtocol": "error", + "useAsConstAssertion": "error", + "useNumericLiterals": "error", + "useEnumInitializers": "error", + "useSelfClosingElements": "error", + "useConst": "error", + "useSingleVarDeclarator": "error", + "noUnusedTemplateLiteral": "error", + "useNumberNamespace": "error", + "noInferrableTypes": "error", + "useExponentiationOperator": "error", + "useTemplate": "error", + "noParameterAssign": "error", + "noNonNullAssertion": "error", + "useDefaultParameterLast": "error", + "noArguments": "error", + "useImportType": "error", + "useExportType": "error", + "noUselessElse": "error", + "useShorthandFunctionType": "error" + }, "correctness": { - "noNewSymbol": "error", + "useImportExtensions": { + "level": "error", + "options": { + "forceJsExtensions": true + }, + "fix": "safe" + }, + "noInvalidBuiltinInstantiation": { + "level": "error" + }, "noUnusedImports": "error", "noUnusedVariables": "error", "useArrayLiterals": "error" @@ -28,6 +65,6 @@ } }, "files": { - "ignore": ["sdk"] + "includes": ["**", "!**/sdk", "!**/old-routes"] } } diff --git a/bun.lock b/bun.lock new file mode 100644 index 000000000..2a12df235 --- /dev/null +++ b/bun.lock @@ -0,0 +1,2218 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "engine", + "dependencies": { + "@aws-sdk/client-kms": "^3.679.0", + "@bull-board/api": "^6.7.9", + "@bull-board/hono": "^6.7.9", + "@circle-fin/developer-controlled-wallets": "^7.0.0", + "@cloud-cryptographic-wallet/cloud-kms-signer": "^0.1.2", + "@cloud-cryptographic-wallet/signer": "^0.0.5", + "@fastify/swagger": "^9.4.2", + "@fastify/type-provider-typebox": "^5.1.0", + "@fastify/websocket": "^11.0.0", + "@google-cloud/kms": "^4.4.0", + "@hono/zod-validator": "^0.4.3", + "@noble/ciphers": "^1.2.1", + "@noble/curves": "^1.8.1", + "@noble/hashes": "^1.7.1", + "@scalar/hono-api-reference": "^0.8.2", + "@sinclair/typebox": "^0.31.28", + "@t3-oss/env-core": "^0.6.0", + "@types/base-64": "^1.0.2", + "abitype": "^1.0.8", + "aws-kms-signer": "^0.5.3", + "base-64": "^1.0.0", + "bullmq": "^5.41.3", + "cron-parser": "^4.9.0", + "dd-trace": "^5.37.0", + "dotenv": "^16.4.7", + "drizzle-orm": "^0.39.3", + "drizzle-zod": "^0.7.0", + "hono": "^4.7.1", + "hono-openapi": "^0.4.4", + "http-status-codes": "^2.2.0", + "ioredis": "^5.5.0", + "jose": "^6.0.10", + "jsonwebtoken": "^9.0.2", + "knex": "^3.1.0", + "ky": "^1.8.0", + "lru-cache": "^11.0.2", + "mnemonist": "^0.39.8", + "neverthrow": "^8.1.1", + "node-cron": "^3.0.2", + "ox": "^0.6.12", + "pg": "^8.13.3", + "prom-client": "^15.1.3", + "superjson": "^2.2.1", + "thirdweb": "^5.96.4", + "undici": "^6.20.1", + "uuid": "^9.0.1", + "viem": "^2.21.54", + "winston": "^3.14.1", + "zod": "^3.24.2", + "zod-openapi": "^4.2.3", + }, + "devDependencies": { + "@biomejs/biome": "^2.0.0-beta.1", + "@types/bun": "^1.2.2", + "@types/cli-progress": "^3.11.3", + "@types/crypto-js": "^4.2.2", + "@types/jsonwebtoken": "^9.0.6", + "@types/node-cron": "^3.0.8", + "@types/pg": "^8.11.11", + "@types/uuid": "^9.0.1", + "@types/ws": "^8.5.5", + "@vitest/coverage-v8": "^2.0.3", + "drizzle-kit": "^0.30.4", + "openapi-typescript-codegen": "^0.25.0", + "prool": "^0.0.16", + "typescript": "^5.7.3", + "vitest": "^2.0.3", + }, + }, + }, + "packages": { + "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.0", "", {}, "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg=="], + + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@9.0.9", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.6", "call-me-maybe": "^1.0.1", "js-yaml": "^4.1.0" } }, "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w=="], + + "@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="], + + "@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="], + + "@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="], + + "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], + + "@aws-sdk/client-kms": ["@aws-sdk/client-kms@3.744.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.744.0", "@aws-sdk/credential-provider-node": "3.744.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", "@aws-sdk/middleware-user-agent": "3.744.0", "@aws-sdk/region-config-resolver": "3.734.0", "@aws-sdk/types": "3.734.0", "@aws-sdk/util-endpoints": "3.743.0", "@aws-sdk/util-user-agent-browser": "3.734.0", "@aws-sdk/util-user-agent-node": "3.744.0", "@smithy/config-resolver": "^4.0.1", "@smithy/core": "^3.1.2", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", "@smithy/middleware-content-length": "^4.0.1", "@smithy/middleware-endpoint": "^4.0.3", "@smithy/middleware-retry": "^4.0.4", "@smithy/middleware-serde": "^4.0.2", "@smithy/middleware-stack": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/node-http-handler": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.4", "@smithy/util-defaults-mode-node": "^4.0.4", "@smithy/util-endpoints": "^3.0.1", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-TcXGL5XwA8kGoaXCEeG1iJds4C51aLc9SULyCSrcyGRyPmgiaJASO5s+LzJudFkyDENfxCREYYhBPN9TnZR2mQ=="], + + "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.744.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.744.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", "@aws-sdk/middleware-user-agent": "3.744.0", "@aws-sdk/region-config-resolver": "3.734.0", "@aws-sdk/types": "3.734.0", "@aws-sdk/util-endpoints": "3.743.0", "@aws-sdk/util-user-agent-browser": "3.734.0", "@aws-sdk/util-user-agent-node": "3.744.0", "@smithy/config-resolver": "^4.0.1", "@smithy/core": "^3.1.2", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", "@smithy/middleware-content-length": "^4.0.1", "@smithy/middleware-endpoint": "^4.0.3", "@smithy/middleware-retry": "^4.0.4", "@smithy/middleware-serde": "^4.0.2", "@smithy/middleware-stack": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/node-http-handler": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.4", "@smithy/util-defaults-mode-node": "^4.0.4", "@smithy/util-endpoints": "^3.0.1", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-mzJxPQ9mcnNY50pi7+pxB34/Dt7PUn0OgkashHdJPTnavoriLWvPcaQCG1NEVAtyzxNdowhpi4KjC+aN1EwAeA=="], + + "@aws-sdk/core": ["@aws-sdk/core@3.744.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/core": "^3.1.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/signature-v4": "^5.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" } }, "sha512-R0XLfDDq7MAXYyDf7tPb+m0R7gmzTRRDtPNQ5jvuq8dbkefph5gFMkxZ2zSx7dfTsfYHhBPuTBsQ0c5Xjal3Vg=="], + + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.744.0", "", { "dependencies": { "@aws-sdk/core": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/property-provider": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-hyjC7xqzAeERorYYjhQG1ivcr1XlxgfBpa+r4pG29toFG60mACyVzaR7+og3kgzjRFAB7D1imMxPQyEvQ1QokA=="], + + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.744.0", "", { "dependencies": { "@aws-sdk/core": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/node-http-handler": "^4.0.2", "@smithy/property-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/util-stream": "^4.0.2", "tslib": "^2.6.2" } }, "sha512-k+P1Tl5ewBvVByR6hB726qFIzANgQVf2cY87hZ/e09pQYlH4bfBcyY16VJhkqYnKmv6HMdWxKHX7D8nwlc8Obg=="], + + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.744.0", "", { "dependencies": { "@aws-sdk/core": "3.744.0", "@aws-sdk/credential-provider-env": "3.744.0", "@aws-sdk/credential-provider-http": "3.744.0", "@aws-sdk/credential-provider-process": "3.744.0", "@aws-sdk/credential-provider-sso": "3.744.0", "@aws-sdk/credential-provider-web-identity": "3.744.0", "@aws-sdk/nested-clients": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/property-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-hjEWgkF86tkvg8PIsDiB3KkTj7z8ZFGR0v0OLQYD47o17q1qfoMzZmg9wae3wXp9KzU+lZETo+8oMqX9a+7aVQ=="], + + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.744.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.744.0", "@aws-sdk/credential-provider-http": "3.744.0", "@aws-sdk/credential-provider-ini": "3.744.0", "@aws-sdk/credential-provider-process": "3.744.0", "@aws-sdk/credential-provider-sso": "3.744.0", "@aws-sdk/credential-provider-web-identity": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/property-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-4oUfRd6pe/VGmKoav17pPoOO0WP0L6YXmHqtJHSDmFUOAa+Vh0ZRljTj/yBdleRgdO6rOfdWqoGLFSFiAZDrsQ=="], + + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.744.0", "", { "dependencies": { "@aws-sdk/core": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/property-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-m0d/pDBIaiEAAxWXt/c79RHsKkUkyPOvF2SAMRddVhhOt1GFZI4ml+3f4drmAZfXldIyJmvJTJJqWluVPwTIqQ=="], + + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.744.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.744.0", "@aws-sdk/core": "3.744.0", "@aws-sdk/token-providers": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/property-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-xdMufTZOvpbDoDPI2XLu0/Rg3qJ/txpS8IJR63NsCGotHJZ/ucLNKwTcGS40hllZB8qSHTlvmlOzElDahTtx/A=="], + + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.744.0", "", { "dependencies": { "@aws-sdk/core": "3.744.0", "@aws-sdk/nested-clients": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/property-provider": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-cNk93GZxORzqEojWfXdrPBF6a7Nu3LpPCWG5mV+lH2tbuGsmw6XhKkwpt7o+OiIP4tKCpHlvqOD8f1nmhe1KDA=="], + + "@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.734.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw=="], + + "@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.734.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w=="], + + "@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.734.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA=="], + + "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.744.0", "", { "dependencies": { "@aws-sdk/core": "3.744.0", "@aws-sdk/types": "3.734.0", "@aws-sdk/util-endpoints": "3.743.0", "@smithy/core": "^3.1.2", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-ROUbDQHfVWiBHXd4m9E9mKj1Azby8XCs8RC8OCf9GVH339GSE6aMrPJSzMlsV1LmzPdPIypgp5qqh5NfSrKztg=="], + + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.744.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.744.0", "@aws-sdk/middleware-host-header": "3.734.0", "@aws-sdk/middleware-logger": "3.734.0", "@aws-sdk/middleware-recursion-detection": "3.734.0", "@aws-sdk/middleware-user-agent": "3.744.0", "@aws-sdk/region-config-resolver": "3.734.0", "@aws-sdk/types": "3.734.0", "@aws-sdk/util-endpoints": "3.743.0", "@aws-sdk/util-user-agent-browser": "3.734.0", "@aws-sdk/util-user-agent-node": "3.744.0", "@smithy/config-resolver": "^4.0.1", "@smithy/core": "^3.1.2", "@smithy/fetch-http-handler": "^5.0.1", "@smithy/hash-node": "^4.0.1", "@smithy/invalid-dependency": "^4.0.1", "@smithy/middleware-content-length": "^4.0.1", "@smithy/middleware-endpoint": "^4.0.3", "@smithy/middleware-retry": "^4.0.4", "@smithy/middleware-serde": "^4.0.2", "@smithy/middleware-stack": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/node-http-handler": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.4", "@smithy/util-defaults-mode-node": "^4.0.4", "@smithy/util-endpoints": "^3.0.1", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-Mnrlh4lRY1gZQnKvN2Lh/5WXcGkzC41NM93mtn2uaqOh+DZLCXCttNCfbUesUvYJLOo3lYaOpiDsjTkPVB1yjw=="], + + "@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.734.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/node-config-provider": "^4.0.1", "@smithy/types": "^4.1.0", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.1", "tslib": "^2.6.2" } }, "sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ=="], + + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.744.0", "", { "dependencies": { "@aws-sdk/nested-clients": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/property-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-v/1+lWkDCd60Ei6oyhJqli6mTsPEVepLoSMB50vHUVlJP0fzXu/3FMje90/RzeUoh/VugZQJCEv/NNpuC6wztg=="], + + "@aws-sdk/types": ["@aws-sdk/types@3.734.0", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg=="], + + "@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.743.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/types": "^4.1.0", "@smithy/util-endpoints": "^3.0.1", "tslib": "^2.6.2" } }, "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw=="], + + "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.723.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw=="], + + "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.734.0", "", { "dependencies": { "@aws-sdk/types": "3.734.0", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng=="], + + "@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.744.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.744.0", "@aws-sdk/types": "3.734.0", "@smithy/node-config-provider": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-BJURjwIXhNa4heXkLC0+GcL+8wVXaU7JoyW6ckdvp93LL+sVHeR1d5FxXZHQW/pMI4E3gNlKyBqjKaT75tObNQ=="], + + "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@babel/generator": ["@babel/generator@7.26.8", "", { "dependencies": { "@babel/parser": "^7.26.8", "@babel/types": "^7.26.8", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@babel/parser": ["@babel/parser@7.26.8", "", { "dependencies": { "@babel/types": "^7.26.8" }, "bin": "./bin/babel-parser.js" }, "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw=="], + + "@babel/runtime": ["@babel/runtime@7.26.7", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ=="], + + "@babel/template": ["@babel/template@7.26.8", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.26.8", "@babel/types": "^7.26.8" } }, "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q=="], + + "@babel/traverse": ["@babel/traverse@7.26.8", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.8", "@babel/parser": "^7.26.8", "@babel/template": "^7.26.8", "@babel/types": "^7.26.8", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA=="], + + "@babel/types": ["@babel/types@7.26.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA=="], + + "@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="], + + "@biomejs/biome": ["@biomejs/biome@2.0.0-beta.1", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.0.0-beta.1", "@biomejs/cli-darwin-x64": "2.0.0-beta.1", "@biomejs/cli-linux-arm64": "2.0.0-beta.1", "@biomejs/cli-linux-arm64-musl": "2.0.0-beta.1", "@biomejs/cli-linux-x64": "2.0.0-beta.1", "@biomejs/cli-linux-x64-musl": "2.0.0-beta.1", "@biomejs/cli-win32-arm64": "2.0.0-beta.1", "@biomejs/cli-win32-x64": "2.0.0-beta.1" }, "bin": { "biome": "bin/biome" } }, "sha512-MqRoy9CbTkrS45zW+S4u8p4kQUIFx0mGUWi789W1R3b1kXYIudEqsTKgXKtTGsI0kWOlvnjuKqwTrabjaGchhQ=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.0.0-beta.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RaGmpNLl5NFooXaoCwvgvcuU6Am/rMZ3R48pQeCVxjrCcz1BIlKLTai5UosiedazW7JbXAvgXdSNizYG7ITlAQ=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.0.0-beta.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-sTzSshkne7HKZFNfiIhmAji7gjtCBXvkTujZELCZWIZC7oj1Tjw/gvAzbdFj2UyHd5/i90pND4ybFOLQZm9gpg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.0.0-beta.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-bxce2O4nooBmp20Ey0+IFIZyy/b0RVnciIQk9euCfAi9evq7SvFtMBYo3YUZej0KIvrau5H7tJk5OqmRJk2l+g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.0.0-beta.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-0MPUKzz9uBBxAYSJ+OlFi4+yGwiRcZeFqq39H0MxXCQ9MMpKJFH2Ek72fw8sXwG7Prn7EsW/3u1b7najyn1XGQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.0.0-beta.1", "", { "os": "linux", "cpu": "x64" }, "sha512-6P/AtJv4hOH8mu8ez0c4UInUpiet9NEoF25+O7OPyb4w6ZHJMp2qzvayJS7TKrTQzE5KUvSiNsACGRz34DzUkg=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.0.0-beta.1", "", { "os": "linux", "cpu": "x64" }, "sha512-dFvisnP1hFpVILNw0PZfs8piBwe8+aykO04Tb/4AJDVVzKkGgJfwSefwo4jqzO/Wk/Zruvhcp1nKbjgRXM+vDg=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.0.0-beta.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-0C9YSqWHf2cJGnjKDbLi49xv6H9IfqbDsFav7X557PqwY64O6IKWqcmZzi/PkDFHjQM9opU6uhKapeGKGDxziQ=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.0.0-beta.1", "", { "os": "win32", "cpu": "x64" }, "sha512-o8W6+DX0YRjt1kS8Y3ismq6EkjwiVDv7X0TEpfnFywoVG8HoJ7G7/m9r8LM1yE46WI3maPH2A0MoVpQ1ZNG++A=="], + + "@bull-board/api": ["@bull-board/api@6.7.9", "", { "dependencies": { "redis-info": "^3.0.8" }, "peerDependencies": { "@bull-board/ui": "6.7.9" } }, "sha512-wgUoaOq7JmY0udhQ+AyMrRdFRpGCtaQJpSgM/QLkAqKRpRpVz5yHFJK9uI6iV+uNvGJkUWE6hNsn3xamzcMy5A=="], + + "@bull-board/hono": ["@bull-board/hono@6.7.9", "", { "dependencies": { "@bull-board/api": "6.7.9", "@bull-board/ui": "6.7.9", "ejs": "^3.1.10", "hono": "^4.6.11" } }, "sha512-HbqBDKlbYZA78Ivs3Pc9lTl4rzURpZNug+RH7nAwhI0cQrPaQo+SF1nCFPRLmYrH4KFcotC4TwCI+WC65qiQdQ=="], + + "@bull-board/ui": ["@bull-board/ui@6.7.9", "", { "dependencies": { "@bull-board/api": "6.7.9" } }, "sha512-41a6rr04wu5uVCtnozqYaAhxUMlJZ3Mu4UwbEmGEvwrkTplKb3TKc8uvP3x0KgKUcIl7WU34Wr9N3lHciAUosQ=="], + + "@circle-fin/developer-controlled-wallets": ["@circle-fin/developer-controlled-wallets@7.1.0", "", { "dependencies": { "axios": "^1.6.2" } }, "sha512-tRquLDpp1PcCgSznqW+URDwT9B7asqcKvder3LOe8ORgYFjYSQxiDD8HTDIJB/3HksBH/H/qiOaUNLrgRn/1IA=="], + + "@cloud-cryptographic-wallet/asn1-parser": ["@cloud-cryptographic-wallet/asn1-parser@0.0.4", "", { "dependencies": { "asn1js": "^3.0.5" } }, "sha512-2Mwc2TSJsBmZluvw4mPqtt5UdymDvGRA3DqNAMU6xifh8Ytms0UtAm0YHNpuD2O2LnQr19q2d7eDg0eaS5qIPg=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer": ["@cloud-cryptographic-wallet/cloud-kms-signer@0.1.2", "", { "dependencies": { "@cloud-cryptographic-wallet/asn1-parser": "^0.0.4", "@cloud-cryptographic-wallet/signer": "^0.0.5", "@google-cloud/kms": "^3.0.1", "@node-lightning/checksum": "^0.27.0" } }, "sha512-A+d2nb9RfL2Tfkwoodga+arX5Yg2SX8UNE1dFK6QkQKDgr/fMHGuc994y2QHG+u6VAJsF+977T44FAR96Tx4CQ=="], + + "@cloud-cryptographic-wallet/signer": ["@cloud-cryptographic-wallet/signer@0.0.5", "", { "dependencies": { "bn.js": "^5.2.0", "keccak": "^3.0.2", "secp256k1": "^4.0.3" } }, "sha512-CfD3o1PWN3JF1F7bsfgcIET+RpNHeb953TrlMhQ+4yqFzIKGbqTLk3TQT+IoTKdxCWGqo/bzXpLO7aqqzIpPbg=="], + + "@coinbase/wallet-sdk": ["@coinbase/wallet-sdk@4.3.0", "", { "dependencies": { "@noble/hashes": "^1.4.0", "clsx": "^1.2.1", "eventemitter3": "^5.0.1", "preact": "^10.24.2" } }, "sha512-T3+SNmiCw4HzDm4we9wCHCxlP0pqCiwKe4sOwPH3YAK2KSKjxPRydKu6UQJrdONFVLG7ujXvbd/6ZqmvJb8rkw=="], + + "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], + + "@dabh/diagnostics": ["@dabh/diagnostics@2.0.3", "", { "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA=="], + + "@datadog/libdatadog": ["@datadog/libdatadog@0.4.0", "", {}, "sha512-kGZfFVmQInzt6J4FFGrqMbrDvOxqwk3WqhAreS6n9b/De+iMVy/NMu3V7uKsY5zAvz+uQw0liDJm3ZDVH/MVVw=="], + + "@datadog/native-appsec": ["@datadog/native-appsec@8.4.0", "", { "dependencies": { "node-gyp-build": "^3.9.0" } }, "sha512-LC47AnpVLpQFEUOP/nIIs+i0wLb8XYO+et3ACaJlHa2YJM3asR4KZTqQjDQNy08PTAUbVvYWKwfSR1qVsU/BeA=="], + + "@datadog/native-iast-rewriter": ["@datadog/native-iast-rewriter@2.8.0", "", { "dependencies": { "lru-cache": "^7.14.0", "node-gyp-build": "^4.5.0" } }, "sha512-DKmtvlmCld9RIJwDcPKWNkKYWYQyiuOrOtynmBppJiUv/yfCOuZtsQV4Zepj40H33sLiQyi5ct6dbWl53vxqkA=="], + + "@datadog/native-iast-taint-tracking": ["@datadog/native-iast-taint-tracking@3.3.0", "", { "dependencies": { "node-gyp-build": "^3.9.0" } }, "sha512-OzmjOncer199ATSYeCAwSACCRyQimo77LKadSHDUcxa/n9FYU+2U/bYQTYsK3vquSA2E47EbSVq9rytrlTdvnA=="], + + "@datadog/native-metrics": ["@datadog/native-metrics@3.1.0", "", { "dependencies": { "node-addon-api": "^6.1.0", "node-gyp-build": "^3.9.0" } }, "sha512-yOBi4x0OQRaGNPZ2bx9TGvDIgEdQ8fkudLTFAe7gEM1nAlvFmbE5YfpH8WenEtTSEBwojSau06m2q7axtEEmCg=="], + + "@datadog/pprof": ["@datadog/pprof@5.5.1", "", { "dependencies": { "delay": "^5.0.0", "node-gyp-build": "<4.0", "p-limit": "^3.1.0", "pprof-format": "^2.1.0", "source-map": "^0.7.4" } }, "sha512-3pZVYqc5YkZJOj9Rc8kQ/wG4qlygcnnwFU/w0QKX6dEdJh+1+dWniuUu+GSEjy/H0jc14yhdT2eJJf/F2AnHNw=="], + + "@datadog/sketches-js": ["@datadog/sketches-js@2.1.1", "", {}, "sha512-d5RjycE+MObE/hU+8OM5Zp4VjTwiPLRa8299fj7muOmR16fb942z8byoMbCErnGh0lBevvgkGrLclQDvINbIyg=="], + + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], + + "@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/serialize": "^1.3.3", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="], + + "@emotion/cache": ["@emotion/cache@11.14.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="], + + "@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="], + + "@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.3.1", "", { "dependencies": { "@emotion/memoize": "^0.9.0" } }, "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw=="], + + "@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="], + + "@emotion/react": ["@emotion/react@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="], + + "@emotion/serialize": ["@emotion/serialize@1.3.3", "", { "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="], + + "@emotion/sheet": ["@emotion/sheet@1.4.0", "", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="], + + "@emotion/styled": ["@emotion/styled@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/is-prop-valid": "^1.3.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", "react": ">=16.8.0" } }, "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA=="], + + "@emotion/unitless": ["@emotion/unitless@0.10.0", "", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="], + + "@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="], + + "@emotion/utils": ["@emotion/utils@1.4.2", "", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="], + + "@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="], + + "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], + + "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.19.12", "", { "os": "android", "cpu": "arm64" }, "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.19.12", "", { "os": "android", "cpu": "x64" }, "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.19.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.19.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.19.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.19.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.19.12", "", { "os": "linux", "cpu": "arm" }, "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.19.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.19.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.19.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.19.12", "", { "os": "linux", "cpu": "none" }, "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.19.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.19.12", "", { "os": "linux", "cpu": "x64" }, "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.19.12", "", { "os": "none", "cpu": "x64" }, "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.19.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.19.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.19.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.19.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.19.12", "", { "os": "win32", "cpu": "x64" }, "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA=="], + + "@fastify/swagger": ["@fastify/swagger@9.4.2", "", { "dependencies": { "fastify-plugin": "^5.0.0", "json-schema-resolver": "^3.0.0", "openapi-types": "^12.1.3", "rfdc": "^1.3.1", "yaml": "^2.4.2" } }, "sha512-WjSUu6QnmysLx1GeX7+oQAQUG/vBK5L8Qzcsht2SEpZiykpHURefMZpf+u3XbwSuH7TjeWOPgGIJIsEgj8AvxQ=="], + + "@fastify/type-provider-typebox": ["@fastify/type-provider-typebox@5.1.0", "", { "peerDependencies": { "@sinclair/typebox": ">=0.26 <=0.34" } }, "sha512-F1AQHeLiKp1hu6GMWm5W6fZ6zXQ0mTV+qHOzrptAie9AYewvFr5Q3blfy8Qmx9gUgwA3Yj+CWvQQJeTwDgTnIg=="], + + "@fastify/websocket": ["@fastify/websocket@11.0.2", "", { "dependencies": { "duplexify": "^4.1.3", "fastify-plugin": "^5.0.0", "ws": "^8.16.0" } }, "sha512-1oyJkNSZNJGjo/A5fXvlpEcm1kTBD91nRAN9lA7RNVsVNsyC5DuhOXdNL9/4UawVe7SKvzPT/QVI4RdtE9ylnA=="], + + "@floating-ui/core": ["@floating-ui/core@1.6.9", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.6.13", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.9" } }, "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w=="], + + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.2", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], + + "@google-cloud/kms": ["@google-cloud/kms@4.5.0", "", { "dependencies": { "google-gax": "^4.0.3" } }, "sha512-i2vC0DI7bdfEhQszqASTw0KVvbB7HsO2CwTBod423NawAu7FWi+gVVa7NLfXVNGJaZZayFfci2Hu+om/HmyEjQ=="], + + "@grpc/grpc-js": ["@grpc/grpc-js@1.12.6", "", { "dependencies": { "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-JXUj6PI0oqqzTGvKtzOkxtpsyPRNsrmhh41TtIz/zEB6J+AUiZZ0dxWzcMwO9Ns5rmSPuMdghlTbUuqIM48d3Q=="], + + "@grpc/proto-loader": ["@grpc/proto-loader@0.7.13", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw=="], + + "@hey-api/client-fetch": ["@hey-api/client-fetch@0.10.0", "", { "peerDependencies": { "@hey-api/openapi-ts": "< 2" } }, "sha512-C7vzj4t52qPiHCqjn1l8cRTI2p4pZCd7ViLtJDTHr5ZwI4sWOYC1tmv6bd529qqY6HFFbhGCz4TAZSwKAMJncg=="], + + "@hey-api/json-schema-ref-parser": ["@hey-api/json-schema-ref-parser@1.0.5", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0", "lodash": "^4.17.21" } }, "sha512-bWUV9ICwvU5I3YKVZqWIUXFC2SIXznUi/u+LqurJx6ILiyImfZD5+g/lj3w4EiyXxmjqyaxptzUz/1IgK3vVtw=="], + + "@hey-api/openapi-ts": ["@hey-api/openapi-ts@0.66.6", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.5", "c12": "2.0.1", "commander": "13.0.0", "handlebars": "4.7.8" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-EmZHVqfHuGNoyBDPcL+3vGHLb/qEbjIix3dnQ/CzfZQ+xm4vnOecpR7JaaaR9u2W8Ldeyqnk7NwmEqOBgkgG4Q=="], + + "@hono/zod-validator": ["@hono/zod-validator@0.4.3", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.19.1" } }, "sha512-xIgMYXDyJ4Hj6ekm9T9Y27s080Nl9NXHcJkOvkXPhubOLj8hZkOL8pDnnXfvCf5xEE8Q4oMFenQUZZREUY2gqQ=="], + + "@ioredis/commands": ["@ioredis/commands@1.2.0", "", {}, "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], + + "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="], + + "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="], + + "@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="], + + "@jsdoc/salty": ["@jsdoc/salty@0.2.9", "", { "dependencies": { "lodash": "^4.17.21" } }, "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw=="], + + "@lit-labs/ssr-dom-shim": ["@lit-labs/ssr-dom-shim@1.3.0", "", {}, "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ=="], + + "@lit/reactive-element": ["@lit/reactive-element@1.6.3", "", { "dependencies": { "@lit-labs/ssr-dom-shim": "^1.0.0" } }, "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ=="], + + "@motionone/animation": ["@motionone/animation@10.18.0", "", { "dependencies": { "@motionone/easing": "^10.18.0", "@motionone/types": "^10.17.1", "@motionone/utils": "^10.18.0", "tslib": "^2.3.1" } }, "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw=="], + + "@motionone/dom": ["@motionone/dom@10.18.0", "", { "dependencies": { "@motionone/animation": "^10.18.0", "@motionone/generators": "^10.18.0", "@motionone/types": "^10.17.1", "@motionone/utils": "^10.18.0", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A=="], + + "@motionone/easing": ["@motionone/easing@10.18.0", "", { "dependencies": { "@motionone/utils": "^10.18.0", "tslib": "^2.3.1" } }, "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg=="], + + "@motionone/generators": ["@motionone/generators@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "@motionone/utils": "^10.18.0", "tslib": "^2.3.1" } }, "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg=="], + + "@motionone/svelte": ["@motionone/svelte@10.16.4", "", { "dependencies": { "@motionone/dom": "^10.16.4", "tslib": "^2.3.1" } }, "sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA=="], + + "@motionone/types": ["@motionone/types@10.17.1", "", {}, "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A=="], + + "@motionone/utils": ["@motionone/utils@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw=="], + + "@motionone/vue": ["@motionone/vue@10.16.4", "", { "dependencies": { "@motionone/dom": "^10.16.4", "tslib": "^2.3.1" } }, "sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg=="], + + "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw=="], + + "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw=="], + + "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw=="], + + "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg=="], + + "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg=="], + + "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="], + + "@noble/ciphers": ["@noble/ciphers@1.2.1", "", {}, "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA=="], + + "@noble/curves": ["@noble/curves@1.8.1", "", { "dependencies": { "@noble/hashes": "1.7.1" } }, "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ=="], + + "@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], + + "@node-lightning/checksum": ["@node-lightning/checksum@0.27.4", "", {}, "sha512-33DuXWqVVvHPnO7O38L2wtz9cSjCXeqi3+xUHZpPhZHpez4atw0JUcc1Fa1SJ4aEjDX81t6rLloMW083z9ZHYQ=="], + + "@opentelemetry/api": ["@opentelemetry/api@1.8.0", "", {}, "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w=="], + + "@opentelemetry/core": ["@opentelemetry/core@1.30.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ=="], + + "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], + + "@passwordless-id/webauthn": ["@passwordless-id/webauthn@2.2.0", "", {}, "sha512-EwwK6PiJ3H/LaWYE3is5EuMhBBZ3igsX9nSHuB5zT/ugD9TmOwGs8/D0lnkBJDRcgV8/smsW/GOXisIJXDPT1Q=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@prisma/client": ["@prisma/client@6.3.1", "", { "peerDependencies": { "prisma": "*", "typescript": ">=5.1.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-ARAJaPs+eBkemdky/XU3cvGRl+mIPHCN2lCXsl5Vlb0E2gV+R6IN7aCI8CisRGszEZondwIsW9Iz8EJkTdykyA=="], + + "@prisma/debug": ["@prisma/debug@6.3.1", "", {}, "sha512-RrEBkd+HLZx+ydfmYT0jUj7wjLiS95wfTOSQ+8FQbvb6vHh5AeKfEPt/XUQ5+Buljj8hltEfOslEW57/wQIVeA=="], + + "@prisma/engines": ["@prisma/engines@6.3.1", "", { "dependencies": { "@prisma/debug": "6.3.1", "@prisma/engines-version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", "@prisma/fetch-engine": "6.3.1", "@prisma/get-platform": "6.3.1" } }, "sha512-sXdqEVLyGAJ5/iUoG/Ea5AdHMN71m6PzMBWRQnLmhhOejzqAaEr8rUd623ql6OJpED4s/U4vIn4dg1qkF7vGag=="], + + "@prisma/engines-version": ["@prisma/engines-version@6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", "", {}, "sha512-R/ZcMuaWZT2UBmgX3Ko6PAV3f8//ZzsjRIG1eKqp3f2rqEqVtCv+mtzuH2rBPUC9ujJ5kCb9wwpxeyCkLcHVyA=="], + + "@prisma/fetch-engine": ["@prisma/fetch-engine@6.3.1", "", { "dependencies": { "@prisma/debug": "6.3.1", "@prisma/engines-version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", "@prisma/get-platform": "6.3.1" } }, "sha512-HOf/0umOgt+/S2xtZze+FHKoxpVg4YpVxROr6g2YG09VsI3Ipyb+rGvD6QGbCqkq5NTWAAZoOGNL+oy7t+IhaQ=="], + + "@prisma/get-platform": ["@prisma/get-platform@6.3.1", "", { "dependencies": { "@prisma/debug": "6.3.1" } }, "sha512-AYLq6Hk9xG73JdLWJ3Ip9Wg/vlP7xPvftGBalsPzKDOHr/ImhwJ09eS8xC2vNT12DlzGxhfk8BkL0ve2OriNhQ=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], + + "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw=="], + + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], + + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.7", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.4", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.6", "@radix-ui/react-presence": "1.1.3", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m6pZb0gEM5uHPSb+i2nKKGQi/HMSVjARMsLMWQfKDP+eJ6B+uqryHnXhpnohTWElw+vEcMk/o4wJODtdRKHwqg=="], + + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-j5+WBUdhccJsmH5/H0K6RncjDtoALSEr6jbkaZu+bjw6hOPOhHycr6vEUujl+HBK8kjUfWcoCJXxP6e4lUlMZw=="], + + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA=="], + + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-r2annK27lIW5w9Ho5NyQgqs0MmgZSTIKXWpVCJaLC1q2kZrZkcqnmHkCHMEmv8XLvsLlurKMPT+kbKkRkm/xVA=="], + + "@radix-ui/react-icons": ["@radix-ui/react-icons@1.3.2", "", { "peerDependencies": { "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" } }, "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g=="], + + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], + + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.4", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.4", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3p2Rgm/a1cK0r/UVkx5F/K9v/EplfjAeIFCGOPYPO4lZ0jtg4iSQXt/YGTSLWaf4x7NG6Z4+uKFcylcTZjeqDA=="], + + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.6", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw=="], + + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA=="], + + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.0", "", { "dependencies": { "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw=="], + + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="], + + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.4", "@radix-ui/react-portal": "1.1.6", "@radix-ui/react-presence": "1.1.3", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0KX7jUYFA02np01Y11NWkk6Ip6TqMNmD4ijLelYAzeIndl2aVeltjJFJ2gwjNa1P8U/dgjQ+8cr9Y3Ni+ZNoRA=="], + + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], + + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], + + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], + + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], + + "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="], + + "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.0", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-rQj0aAWOpCdCMRbI6pLQm8r7S2BM3YhTa0SzOYD55k+hJA8oo9J+H+9wLM9oMlZWOX/wJWPTzfDfmZkf7LvCfg=="], + + "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.6", "", { "os": "android", "cpu": "arm" }, "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.6", "", { "os": "android", "cpu": "arm64" }, "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.6", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.6", "", { "os": "linux", "cpu": "arm" }, "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.6", "", { "os": "linux", "cpu": "arm" }, "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.6", "", { "os": "linux", "cpu": "none" }, "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.6", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.6", "", { "os": "linux", "cpu": "none" }, "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.6", "", { "os": "linux", "cpu": "s390x" }, "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.6", "", { "os": "linux", "cpu": "x64" }, "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.6", "", { "os": "linux", "cpu": "x64" }, "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.6", "", { "os": "win32", "cpu": "x64" }, "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w=="], + + "@scalar/core": ["@scalar/core@0.2.8", "", { "dependencies": { "@scalar/types": "0.1.8" } }, "sha512-4WjhJl0hJGgPGznmRvMFscY4ZMRbXgfEAsDGWl9eVqE/ZdXFxnoY2LsGhBALSKEYfwgNwLzk3A+0bCv2oU6N7g=="], + + "@scalar/hono-api-reference": ["@scalar/hono-api-reference@0.8.2", "", { "dependencies": { "@scalar/core": "0.2.8" }, "peerDependencies": { "hono": "^4.0.0" } }, "sha512-sgNtRst9KTamZMxE66fuIczgTsG7Yeputoelvxw/O+5dcN4KPeZ8ac67aqFH9sG1t+bbQyxqZ+qn+6ESoZMJQw=="], + + "@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="], + + "@scalar/types": ["@scalar/types@0.1.8", "", { "dependencies": { "@scalar/openapi-types": "0.2.0", "@unhead/schema": "^1.11.11", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "zod": "^3.23.8" } }, "sha512-VL1dcLB6w7V0htFxIgcdQeQhD5LFW1oqWk9ZWfzd9Ekl0a3bDGc81R5S3fk6qCHahPZR3cVPr4rHVQh0aX+FrQ=="], + + "@scure/base": ["@scure/base@1.2.4", "", {}, "sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ=="], + + "@scure/bip32": ["@scure/bip32@1.6.2", "", { "dependencies": { "@noble/curves": "~1.8.1", "@noble/hashes": "~1.7.1", "@scure/base": "~1.2.2" } }, "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw=="], + + "@scure/bip39": ["@scure/bip39@1.5.4", "", { "dependencies": { "@noble/hashes": "~1.7.1", "@scure/base": "~1.2.4" } }, "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA=="], + + "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.31.28", "", {}, "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ=="], + + "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], + + "@smithy/abort-controller": ["@smithy/abort-controller@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g=="], + + "@smithy/config-resolver": ["@smithy/config-resolver@4.0.1", "", { "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/types": "^4.1.0", "@smithy/util-config-provider": "^4.0.0", "@smithy/util-middleware": "^4.0.1", "tslib": "^2.6.2" } }, "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ=="], + + "@smithy/core": ["@smithy/core@3.1.2", "", { "dependencies": { "@smithy/middleware-serde": "^4.0.2", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-stream": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q=="], + + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.0.1", "", { "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "tslib": "^2.6.2" } }, "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg=="], + + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.0.1", "", { "dependencies": { "@smithy/protocol-http": "^5.0.1", "@smithy/querystring-builder": "^4.0.1", "@smithy/types": "^4.1.0", "@smithy/util-base64": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA=="], + + "@smithy/hash-node": ["@smithy/hash-node@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w=="], + + "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ=="], + + "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw=="], + + "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.0.1", "", { "dependencies": { "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ=="], + + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.0.3", "", { "dependencies": { "@smithy/core": "^3.1.2", "@smithy/middleware-serde": "^4.0.2", "@smithy/node-config-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "@smithy/url-parser": "^4.0.1", "@smithy/util-middleware": "^4.0.1", "tslib": "^2.6.2" } }, "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q=="], + + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.0.4", "", { "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/service-error-classification": "^4.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-retry": "^4.0.1", "tslib": "^2.6.2", "uuid": "^9.0.1" } }, "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ=="], + + "@smithy/middleware-serde": ["@smithy/middleware-serde@4.0.2", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ=="], + + "@smithy/middleware-stack": ["@smithy/middleware-stack@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA=="], + + "@smithy/node-config-provider": ["@smithy/node-config-provider@4.0.1", "", { "dependencies": { "@smithy/property-provider": "^4.0.1", "@smithy/shared-ini-file-loader": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ=="], + + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.0.2", "", { "dependencies": { "@smithy/abort-controller": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/querystring-builder": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw=="], + + "@smithy/property-provider": ["@smithy/property-provider@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ=="], + + "@smithy/protocol-http": ["@smithy/protocol-http@5.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ=="], + + "@smithy/querystring-builder": ["@smithy/querystring-builder@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg=="], + + "@smithy/querystring-parser": ["@smithy/querystring-parser@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw=="], + + "@smithy/service-error-classification": ["@smithy/service-error-classification@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0" } }, "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA=="], + + "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw=="], + + "@smithy/signature-v4": ["@smithy/signature-v4@5.0.1", "", { "dependencies": { "@smithy/is-array-buffer": "^4.0.0", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "@smithy/util-hex-encoding": "^4.0.0", "@smithy/util-middleware": "^4.0.1", "@smithy/util-uri-escape": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA=="], + + "@smithy/smithy-client": ["@smithy/smithy-client@4.1.3", "", { "dependencies": { "@smithy/core": "^3.1.2", "@smithy/middleware-endpoint": "^4.0.3", "@smithy/middleware-stack": "^4.0.1", "@smithy/protocol-http": "^5.0.1", "@smithy/types": "^4.1.0", "@smithy/util-stream": "^4.0.2", "tslib": "^2.6.2" } }, "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A=="], + + "@smithy/types": ["@smithy/types@4.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw=="], + + "@smithy/url-parser": ["@smithy/url-parser@4.0.1", "", { "dependencies": { "@smithy/querystring-parser": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g=="], + + "@smithy/util-base64": ["@smithy/util-base64@4.0.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg=="], + + "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA=="], + + "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg=="], + + "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.0.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug=="], + + "@smithy/util-config-provider": ["@smithy/util-config-provider@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w=="], + + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.0.4", "", { "dependencies": { "@smithy/property-provider": "^4.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw=="], + + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.0.4", "", { "dependencies": { "@smithy/config-resolver": "^4.0.1", "@smithy/credential-provider-imds": "^4.0.1", "@smithy/node-config-provider": "^4.0.1", "@smithy/property-provider": "^4.0.1", "@smithy/smithy-client": "^4.1.3", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw=="], + + "@smithy/util-endpoints": ["@smithy/util-endpoints@3.0.1", "", { "dependencies": { "@smithy/node-config-provider": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA=="], + + "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw=="], + + "@smithy/util-middleware": ["@smithy/util-middleware@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA=="], + + "@smithy/util-retry": ["@smithy/util-retry@4.0.1", "", { "dependencies": { "@smithy/service-error-classification": "^4.0.1", "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw=="], + + "@smithy/util-stream": ["@smithy/util-stream@4.0.2", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.0.1", "@smithy/node-http-handler": "^4.0.2", "@smithy/types": "^4.1.0", "@smithy/util-base64": "^4.0.0", "@smithy/util-buffer-from": "^4.0.0", "@smithy/util-hex-encoding": "^4.0.0", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA=="], + + "@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="], + + "@smithy/util-utf8": ["@smithy/util-utf8@4.0.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow=="], + + "@t3-oss/env-core": ["@t3-oss/env-core@0.6.1", "", { "peerDependencies": { "typescript": ">=4.7.2", "zod": "^3.0.0" } }, "sha512-KQD7qEDJtkWIWWmTVjNvk0wnHpkvAQ6CRbUxbWMFNG/fiosBQDQvtRpBNu6USxBscJCoC4z6y7P9MN52/mLOzw=="], + + "@tanstack/query-core": ["@tanstack/query-core@5.74.4", "", {}, "sha512-YuG0A0+3i9b2Gfo9fkmNnkUWh5+5cFhWBN0pJAHkHilTx6A0nv8kepkk4T4GRt4e5ahbtFj2eTtkiPcVU1xO4A=="], + + "@tanstack/react-query": ["@tanstack/react-query@5.74.4", "", { "dependencies": { "@tanstack/query-core": "5.74.4" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-mAbxw60d4ffQ4qmRYfkO1xzRBPUEf/72Dgo3qqea0J66nIKuDTLEqQt0ku++SDFlMGMnB6uKDnEG1xD/TDse4Q=="], + + "@thirdweb-dev/insight": ["@thirdweb-dev/insight@1.0.0", "", { "dependencies": { "@hey-api/client-fetch": "0.10.0", "tslib": "^2.8.1" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-7A84reyKVhFSZXzKiuUYLgllPqyDQjZj5MebasetkCAB0VK8L0cv09VrfiBOd+eJDvJkhJfnAV/q3ujXegsVfg=="], + + "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], + + "@types/base-64": ["@types/base-64@1.0.2", "", {}, "sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw=="], + + "@types/bun": ["@types/bun@1.2.2", "", { "dependencies": { "bun-types": "1.2.2" } }, "sha512-tr74gdku+AEDN5ergNiBnplr7hpDp3V1h7fqI2GcR/rsUaM39jpSeKH0TFibRvU0KwniRx5POgaYnaXbk0hU+w=="], + + "@types/caseless": ["@types/caseless@0.12.5", "", {}, "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="], + + "@types/cli-progress": ["@types/cli-progress@3.11.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA=="], + + "@types/crypto-js": ["@types/crypto-js@4.2.2", "", {}, "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="], + + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + + "@types/glob": ["@types/glob@8.1.0", "", { "dependencies": { "@types/minimatch": "^5.1.2", "@types/node": "*" } }, "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/jsonwebtoken": ["@types/jsonwebtoken@9.0.8", "", { "dependencies": { "@types/ms": "*", "@types/node": "*" } }, "sha512-7fx54m60nLFUVYlxAB1xpe9CBWX2vSrk50Y6ogRJ1v5xxtba7qXTg5BgYDN5dq+yuQQ9HaVlHJyAAt1/mxryFg=="], + + "@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="], + + "@types/long": ["@types/long@4.0.2", "", {}, "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA=="], + + "@types/markdown-it": ["@types/markdown-it@14.1.2", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="], + + "@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="], + + "@types/minimatch": ["@types/minimatch@5.1.2", "", {}, "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/node": ["@types/node@22.13.4", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg=="], + + "@types/node-cron": ["@types/node-cron@3.0.11", "", {}, "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg=="], + + "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], + + "@types/pg": ["@types/pg@8.11.11", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^4.0.1" } }, "sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw=="], + + "@types/request": ["@types/request@2.48.12", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw=="], + + "@types/rimraf": ["@types/rimraf@3.0.2", "", { "dependencies": { "@types/glob": "*", "@types/node": "*" } }, "sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ=="], + + "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + + "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="], + + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + + "@types/uuid": ["@types/uuid@9.0.8", "", {}, "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="], + + "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + + "@unhead/schema": ["@unhead/schema@1.11.19", "", { "dependencies": { "hookable": "^5.5.3", "zhead": "^2.2.4" } }, "sha512-7VhYHWK7xHgljdv+C01MepCSYZO2v6OhgsfKWPxRQBDDGfUKCUaChox0XMq3tFvXP6u4zSp6yzcDw2yxCfVMwg=="], + + "@vitest/coverage-v8": ["@vitest/coverage-v8@2.1.9", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", "debug": "^4.3.7", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magic-string": "^0.30.12", "magicast": "^0.3.5", "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, "peerDependencies": { "@vitest/browser": "2.1.9", "vitest": "2.1.9" }, "optionalPeers": ["@vitest/browser"] }, "sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ=="], + + "@vitest/expect": ["@vitest/expect@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw=="], + + "@vitest/mocker": ["@vitest/mocker@2.1.9", "", { "dependencies": { "@vitest/spy": "2.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@2.1.9", "", { "dependencies": { "tinyrainbow": "^1.2.0" } }, "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ=="], + + "@vitest/runner": ["@vitest/runner@2.1.9", "", { "dependencies": { "@vitest/utils": "2.1.9", "pathe": "^1.1.2" } }, "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g=="], + + "@vitest/snapshot": ["@vitest/snapshot@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "magic-string": "^0.30.12", "pathe": "^1.1.2" } }, "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ=="], + + "@vitest/spy": ["@vitest/spy@2.1.9", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ=="], + + "@vitest/utils": ["@vitest/utils@2.1.9", "", { "dependencies": { "@vitest/pretty-format": "2.1.9", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ=="], + + "@walletconnect/core": ["@walletconnect/core@2.19.1", "", { "dependencies": { "@walletconnect/heartbeat": "1.2.2", "@walletconnect/jsonrpc-provider": "1.0.14", "@walletconnect/jsonrpc-types": "1.0.4", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/jsonrpc-ws-connection": "1.0.16", "@walletconnect/keyvaluestorage": "1.1.1", "@walletconnect/logger": "2.1.2", "@walletconnect/relay-api": "1.0.11", "@walletconnect/relay-auth": "1.1.0", "@walletconnect/safe-json": "1.0.2", "@walletconnect/time": "1.0.2", "@walletconnect/types": "2.19.1", "@walletconnect/utils": "2.19.1", "@walletconnect/window-getters": "1.0.1", "es-toolkit": "1.33.0", "events": "3.3.0", "uint8arrays": "3.1.0" } }, "sha512-rMvpZS0tQXR/ivzOxN1GkHvw3jRRMlI/jRX5g7ZteLgg2L0ZcANsFvAU5IxILxIKcIkTCloF9TcfloKVbK3qmw=="], + + "@walletconnect/environment": ["@walletconnect/environment@1.0.1", "", { "dependencies": { "tslib": "1.14.1" } }, "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg=="], + + "@walletconnect/ethereum-provider": ["@walletconnect/ethereum-provider@2.19.1", "", { "dependencies": { "@walletconnect/jsonrpc-http-connection": "1.0.8", "@walletconnect/jsonrpc-provider": "1.0.14", "@walletconnect/jsonrpc-types": "1.0.4", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/keyvaluestorage": "1.1.1", "@walletconnect/modal": "2.7.0", "@walletconnect/sign-client": "2.19.1", "@walletconnect/types": "2.19.1", "@walletconnect/universal-provider": "2.19.1", "@walletconnect/utils": "2.19.1", "events": "3.3.0" } }, "sha512-bs8Kiwdw3cGb8ITO8+YymesGfFnucJreQmVbZ0vl/Ogoh38n1T5w0ekjmD/NjTDS3oZaUQyBm3V2UjIBR0qedw=="], + + "@walletconnect/events": ["@walletconnect/events@1.0.1", "", { "dependencies": { "keyvaluestorage-interface": "^1.0.0", "tslib": "1.14.1" } }, "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ=="], + + "@walletconnect/heartbeat": ["@walletconnect/heartbeat@1.2.2", "", { "dependencies": { "@walletconnect/events": "^1.0.1", "@walletconnect/time": "^1.0.2", "events": "^3.3.0" } }, "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw=="], + + "@walletconnect/jsonrpc-http-connection": ["@walletconnect/jsonrpc-http-connection@1.0.8", "", { "dependencies": { "@walletconnect/jsonrpc-utils": "^1.0.6", "@walletconnect/safe-json": "^1.0.1", "cross-fetch": "^3.1.4", "events": "^3.3.0" } }, "sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw=="], + + "@walletconnect/jsonrpc-provider": ["@walletconnect/jsonrpc-provider@1.0.14", "", { "dependencies": { "@walletconnect/jsonrpc-utils": "^1.0.8", "@walletconnect/safe-json": "^1.0.2", "events": "^3.3.0" } }, "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow=="], + + "@walletconnect/jsonrpc-types": ["@walletconnect/jsonrpc-types@1.0.4", "", { "dependencies": { "events": "^3.3.0", "keyvaluestorage-interface": "^1.0.0" } }, "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ=="], + + "@walletconnect/jsonrpc-utils": ["@walletconnect/jsonrpc-utils@1.0.8", "", { "dependencies": { "@walletconnect/environment": "^1.0.1", "@walletconnect/jsonrpc-types": "^1.0.3", "tslib": "1.14.1" } }, "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw=="], + + "@walletconnect/jsonrpc-ws-connection": ["@walletconnect/jsonrpc-ws-connection@1.0.16", "", { "dependencies": { "@walletconnect/jsonrpc-utils": "^1.0.6", "@walletconnect/safe-json": "^1.0.2", "events": "^3.3.0", "ws": "^7.5.1" } }, "sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q=="], + + "@walletconnect/keyvaluestorage": ["@walletconnect/keyvaluestorage@1.1.1", "", { "dependencies": { "@walletconnect/safe-json": "^1.0.1", "idb-keyval": "^6.2.1", "unstorage": "^1.9.0" }, "peerDependencies": { "@react-native-async-storage/async-storage": "1.x" }, "optionalPeers": ["@react-native-async-storage/async-storage"] }, "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA=="], + + "@walletconnect/logger": ["@walletconnect/logger@2.1.2", "", { "dependencies": { "@walletconnect/safe-json": "^1.0.2", "pino": "7.11.0" } }, "sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw=="], + + "@walletconnect/modal": ["@walletconnect/modal@2.7.0", "", { "dependencies": { "@walletconnect/modal-core": "2.7.0", "@walletconnect/modal-ui": "2.7.0" } }, "sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw=="], + + "@walletconnect/modal-core": ["@walletconnect/modal-core@2.7.0", "", { "dependencies": { "valtio": "1.11.2" } }, "sha512-oyMIfdlNdpyKF2kTJowTixZSo0PGlCJRdssUN/EZdA6H6v03hZnf09JnwpljZNfir2M65Dvjm/15nGrDQnlxSA=="], + + "@walletconnect/modal-ui": ["@walletconnect/modal-ui@2.7.0", "", { "dependencies": { "@walletconnect/modal-core": "2.7.0", "lit": "2.8.0", "motion": "10.16.2", "qrcode": "1.5.3" } }, "sha512-gERYvU7D7K1ANCN/8vUgsE0d2hnRemfAFZ2novm9aZBg7TEd/4EgB+AqbJ+1dc7GhOL6dazckVq78TgccHb7mQ=="], + + "@walletconnect/relay-api": ["@walletconnect/relay-api@1.0.11", "", { "dependencies": { "@walletconnect/jsonrpc-types": "^1.0.2" } }, "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q=="], + + "@walletconnect/relay-auth": ["@walletconnect/relay-auth@1.1.0", "", { "dependencies": { "@noble/curves": "1.8.0", "@noble/hashes": "1.7.0", "@walletconnect/safe-json": "^1.0.1", "@walletconnect/time": "^1.0.2", "uint8arrays": "^3.0.0" } }, "sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ=="], + + "@walletconnect/safe-json": ["@walletconnect/safe-json@1.0.2", "", { "dependencies": { "tslib": "1.14.1" } }, "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA=="], + + "@walletconnect/sign-client": ["@walletconnect/sign-client@2.19.1", "", { "dependencies": { "@walletconnect/core": "2.19.1", "@walletconnect/events": "1.0.1", "@walletconnect/heartbeat": "1.2.2", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/logger": "2.1.2", "@walletconnect/time": "1.0.2", "@walletconnect/types": "2.19.1", "@walletconnect/utils": "2.19.1", "events": "3.3.0" } }, "sha512-OgBHRPo423S02ceN3lAzcZ3MYb1XuLyTTkKqLmKp/icYZCyRzm3/ynqJDKndiBLJ5LTic0y07LiZilnliYqlvw=="], + + "@walletconnect/time": ["@walletconnect/time@1.0.2", "", { "dependencies": { "tslib": "1.14.1" } }, "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g=="], + + "@walletconnect/types": ["@walletconnect/types@2.19.1", "", { "dependencies": { "@walletconnect/events": "1.0.1", "@walletconnect/heartbeat": "1.2.2", "@walletconnect/jsonrpc-types": "1.0.4", "@walletconnect/keyvaluestorage": "1.1.1", "@walletconnect/logger": "2.1.2", "events": "3.3.0" } }, "sha512-XWWGLioddH7MjxhyGhylL7VVariVON2XatJq/hy0kSGJ1hdp31z194nHN5ly9M495J9Hw8lcYjGXpsgeKvgxzw=="], + + "@walletconnect/universal-provider": ["@walletconnect/universal-provider@2.19.1", "", { "dependencies": { "@walletconnect/events": "1.0.1", "@walletconnect/jsonrpc-http-connection": "1.0.8", "@walletconnect/jsonrpc-provider": "1.0.14", "@walletconnect/jsonrpc-types": "1.0.4", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/keyvaluestorage": "1.1.1", "@walletconnect/logger": "2.1.2", "@walletconnect/sign-client": "2.19.1", "@walletconnect/types": "2.19.1", "@walletconnect/utils": "2.19.1", "es-toolkit": "1.33.0", "events": "3.3.0" } }, "sha512-4rdLvJ2TGDIieNWW3sZw2MXlX65iHpTuKb5vyvUHQtjIVNLj+7X/09iUAI/poswhtspBK0ytwbH+AIT/nbGpjg=="], + + "@walletconnect/utils": ["@walletconnect/utils@2.19.1", "", { "dependencies": { "@noble/ciphers": "1.2.1", "@noble/curves": "1.8.1", "@noble/hashes": "1.7.1", "@walletconnect/jsonrpc-utils": "1.0.8", "@walletconnect/keyvaluestorage": "1.1.1", "@walletconnect/relay-api": "1.0.11", "@walletconnect/relay-auth": "1.1.0", "@walletconnect/safe-json": "1.0.2", "@walletconnect/time": "1.0.2", "@walletconnect/types": "2.19.1", "@walletconnect/window-getters": "1.0.1", "@walletconnect/window-metadata": "1.0.1", "bs58": "6.0.0", "detect-browser": "5.3.0", "elliptic": "6.6.1", "query-string": "7.1.3", "uint8arrays": "3.1.0", "viem": "2.23.2" } }, "sha512-aOwcg+Hpph8niJSXLqkU25pmLR49B8ECXp5gFQDW5IeVgXHoOoK7w8a79GBhIBheMLlIt1322sTKQ7Rq5KzzFg=="], + + "@walletconnect/window-getters": ["@walletconnect/window-getters@1.0.1", "", { "dependencies": { "tslib": "1.14.1" } }, "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q=="], + + "@walletconnect/window-metadata": ["@walletconnect/window-metadata@1.0.1", "", { "dependencies": { "@walletconnect/window-getters": "^1.0.1", "tslib": "1.14.1" } }, "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA=="], + + "abitype": ["abitype@1.0.8", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3 >=3.22.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg=="], + + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], + + "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + + "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], + + "ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "aria-hidden": ["aria-hidden@1.2.4", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A=="], + + "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + + "asn1js": ["asn1js@3.0.5", "", { "dependencies": { "pvtsutils": "^1.3.2", "pvutils": "^1.1.3", "tslib": "^2.4.0" } }, "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], + + "aws-kms-signer": ["aws-kms-signer@0.5.3", "", { "dependencies": { "@aws-sdk/client-kms": "^3.28.0", "asn1js": "^3.0.5", "bn.js": "^5.2.0", "keccak": "^3.0.2", "secp256k1": "4.0" } }, "sha512-NUtftorrEcO+ODBfL4S/IIxNJMljaM/l233TRCFK0L0sOY/nOjbm2BLqLQOK/EUZ5i0pP1HK/32Lp6APdY9nCg=="], + + "aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], + + "axios": ["axios@1.7.9", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw=="], + + "babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="], + + "base-x": ["base-x@5.0.1", "", {}, "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bignumber.js": ["bignumber.js@9.1.2", "", {}, "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "bintrees": ["bintrees@1.0.2", "", {}, "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="], + + "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], + + "bn.js": ["bn.js@5.2.1", "", {}, "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="], + + "bowser": ["bowser@2.11.0", "", {}, "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="], + + "brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "brorand": ["brorand@1.1.0", "", {}, "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="], + + "bs58": ["bs58@6.0.0", "", { "dependencies": { "base-x": "^5.0.0" } }, "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw=="], + + "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "bufferutil": ["bufferutil@4.0.9", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw=="], + + "bullmq": ["bullmq@5.41.3", "", { "dependencies": { "cron-parser": "^4.9.0", "ioredis": "^5.4.1", "msgpackr": "^1.11.2", "node-abort-controller": "^3.1.1", "semver": "^7.5.4", "tslib": "^2.0.0", "uuid": "^9.0.0" } }, "sha512-tWTeuO/BHDg6gKVnQJMjO42zkhsGss6s4bMdgJU24JVBT53yUvDjaO9H0L/BHKAtsMi4xlxkrDuMNSYWeHlekA=="], + + "bun-types": ["bun-types@1.2.2", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-RCbMH5elr9gjgDGDhkTTugA21XtJAy/9jkKe/G3WR2q17VPGhcquf9Sir6uay9iW+7P/BV0CAHA1XlHXMAVKHg=="], + + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + + "c12": ["c12@2.0.1", "", { "dependencies": { "chokidar": "^4.0.1", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^2.3.0", "mlly": "^1.7.1", "ohash": "^1.1.4", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A=="], + + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + + "call-me-maybe": ["call-me-maybe@1.0.2", "", {}, "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], + + "catharsis": ["catharsis@0.9.0", "", { "dependencies": { "lodash": "^4.17.15" } }, "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A=="], + + "chai": ["chai@5.1.2", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw=="], + + "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + + "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], + + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], + + "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], + + "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], + + "clsx": ["clsx@1.2.1", "", {}, "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="], + + "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], + + "color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="], + + "color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], + + "color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "colorette": ["colorette@2.0.19", "", {}, "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ=="], + + "colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + + "convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="], + + "cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], + + "copy-anything": ["copy-anything@3.0.5", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w=="], + + "cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="], + + "cron-parser": ["cron-parser@4.9.0", "", { "dependencies": { "luxon": "^3.2.1" } }, "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q=="], + + "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "crossws": ["crossws@0.3.4", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-uj0O1ETYX1Bh6uSgktfPvwDiPYGQ3aI4qVsaC/LWpkIzGj1nUYm5FK3K+t11oOlpN01lGbprFCH4wBlKdJjVgw=="], + + "crypto-randomuuid": ["crypto-randomuuid@1.0.0", "", {}, "sha512-/RC5F4l1SCqD/jazwUF6+t34Cd8zTSAGZ7rvvZu1whZUhD2a5MOGKjSGowoGcpj/cbVZk1ZODIooJEQQq3nNAA=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "dc-polyfill": ["dc-polyfill@0.1.6", "", {}, "sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ=="], + + "dd-trace": ["dd-trace@5.37.0", "", { "dependencies": { "@datadog/libdatadog": "^0.4.0", "@datadog/native-appsec": "8.4.0", "@datadog/native-iast-rewriter": "2.8.0", "@datadog/native-iast-taint-tracking": "3.3.0", "@datadog/native-metrics": "^3.1.0", "@datadog/pprof": "5.5.1", "@datadog/sketches-js": "^2.1.0", "@isaacs/ttlcache": "^1.4.1", "@opentelemetry/api": ">=1.0.0 <1.9.0", "@opentelemetry/core": "^1.14.0", "crypto-randomuuid": "^1.0.0", "dc-polyfill": "^0.1.4", "ignore": "^5.2.4", "import-in-the-middle": "1.11.2", "istanbul-lib-coverage": "3.2.0", "jest-docblock": "^29.7.0", "koalas": "^1.0.2", "limiter": "1.1.5", "lodash.sortby": "^4.7.0", "lru-cache": "^7.14.0", "module-details-from-path": "^1.0.3", "opentracing": ">=0.12.1", "path-to-regexp": "^0.1.12", "pprof-format": "^2.1.0", "protobufjs": "^7.2.5", "retry": "^0.13.1", "rfdc": "^1.3.1", "semifies": "^1.0.0", "shell-quote": "^1.8.1", "source-map": "^0.7.4", "tlhunter-sorted-set": "^0.1.0", "ttl-set": "^1.0.0" } }, "sha512-eqLzAJuU4ozR+ImGnFOlltMwL7nAU3re2Y+txcwFss9nETufFydZQgT6mmKhzIp+WFasFuk0Z3uaZ8uVJ4o8/Q=="], + + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], + + "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], + + "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="], + + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "default-browser": ["default-browser@5.2.1", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg=="], + + "default-browser-id": ["default-browser-id@5.0.0", "", {}, "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA=="], + + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "delay": ["delay@5.0.0", "", {}, "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="], + + "destr": ["destr@2.0.3", "", {}, "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ=="], + + "detect-browser": ["detect-browser@5.3.0", "", {}, "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w=="], + + "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], + + "detect-newline": ["detect-newline@3.1.0", "", {}, "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA=="], + + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], + + "dijkstrajs": ["dijkstrajs@1.0.3", "", {}, "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="], + + "dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="], + + "drizzle-kit": ["drizzle-kit@0.30.4", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-B2oJN5UkvwwNHscPWXDG5KqAixu7AUzZ3qbe++KU9SsQ+cZWR4DXEPYcvWplyFAno0dhRJECNEhNxiDmFaPGyQ=="], + + "drizzle-orm": ["drizzle-orm@0.39.3", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-EZ8ZpYvDIvKU9C56JYLOmUskazhad+uXZCTCRN4OnRMsL+xAJ05dv1eCpAG5xzhsm1hqiuC5kAZUCS924u2DTw=="], + + "drizzle-zod": ["drizzle-zod@0.7.0", "", { "peerDependencies": { "drizzle-orm": ">=0.36.0", "zod": ">=3.0.0" } }, "sha512-xgCRYYVEzRkeXTS33GSMgoowe3vKsMNBjSI+cwG1oLQVEhAWWbqtb/AAMlm7tkmV4fG/uJjEmWzdzlEmTgWOoQ=="], + + "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + + "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], + + "elliptic": ["elliptic@6.6.1", "", { "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g=="], + + "emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="], + + "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="], + + "encode-utf8": ["encode-utf8@1.0.3", "", {}, "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="], + + "end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], + + "es-module-lexer": ["es-module-lexer@1.6.0", "", {}, "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ=="], + + "es-toolkit": ["es-toolkit@1.33.0", "", {}, "sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg=="], + + "esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], + + "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "escodegen": ["escodegen@1.14.3", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "esm": ["esm@3.2.25", "", {}, "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="], + + "espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + + "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + + "execa": ["execa@9.5.2", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.3", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.0.0" } }, "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q=="], + + "expect-type": ["expect-type@1.1.0", "", {}, "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="], + + "fast-text-encoding": ["fast-text-encoding@1.0.6", "", {}, "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w=="], + + "fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="], + + "fast-xml-parser": ["fast-xml-parser@4.4.1", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw=="], + + "fastify-plugin": ["fastify-plugin@5.0.1", "", {}, "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ=="], + + "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], + + "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], + + "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="], + + "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], + + "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + + "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="], + + "follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="], + + "foreground-child": ["foreground-child@3.3.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" } }, "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg=="], + + "form-data": ["form-data@4.0.1", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw=="], + + "fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], + + "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "fuse.js": ["fuse.js@7.1.0", "", {}, "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="], + + "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], + + "gcp-metadata": ["gcp-metadata@6.1.1", "", { "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", "json-bigint": "^1.0.0" } }, "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="], + + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + + "get-package-type": ["get-package-type@0.1.0", "", {}, "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="], + + "get-port": ["get-port@7.1.0", "", {}, "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw=="], + + "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], + + "get-tsconfig": ["get-tsconfig@4.10.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A=="], + + "getopts": ["getopts@2.3.0", "", {}, "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA=="], + + "giget": ["giget@1.2.5", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.5.4", "pathe": "^2.0.3", "tar": "^6.2.1" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug=="], + + "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "google-auth-library": ["google-auth-library@9.15.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^6.1.1", "gcp-metadata": "^6.1.0", "gtoken": "^7.0.0", "jws": "^4.0.0" } }, "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng=="], + + "google-gax": ["google-gax@4.4.1", "", { "dependencies": { "@grpc/grpc-js": "^1.10.9", "@grpc/proto-loader": "^0.7.13", "@types/long": "^4.0.0", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", "google-auth-library": "^9.3.0", "node-fetch": "^2.7.0", "object-hash": "^3.0.0", "proto3-json-serializer": "^2.0.2", "protobufjs": "^7.3.2", "retry-request": "^7.0.0", "uuid": "^9.0.1" } }, "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg=="], + + "google-logging-utils": ["google-logging-utils@0.0.2", "", {}, "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ=="], + + "google-p12-pem": ["google-p12-pem@4.0.1", "", { "dependencies": { "node-forge": "^1.3.1" }, "bin": { "gp12-pem": "build/src/bin/gp12-pem.js" } }, "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "gtoken": ["gtoken@7.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" } }, "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw=="], + + "h3": ["h3@1.15.0", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.3", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "ohash": "^1.1.4", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3" } }, "sha512-OsjX4JW8J4XGgCgEcad20pepFQWnuKH+OwkCJjogF3C+9AZ1iYdtB4hX6vAb5DskBiu5ljEXqApINjR8CqoCMQ=="], + + "handlebars": ["handlebars@4.7.8", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "hash.js": ["hash.js@1.1.7", "", { "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="], + + "hmac-drbg": ["hmac-drbg@1.0.1", "", { "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.1" } }, "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg=="], + + "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], + + "hono": ["hono@4.7.1", "", {}, "sha512-V3eWoPkBxoNgFCkSc5Y5rpLF6YoQQx1pkYO4qrF6YfOw8RZbujUNlJLZCxh0z9gZct70+je2Ih7Zrdpv21hP9w=="], + + "hono-openapi": ["hono-openapi@0.4.4", "", { "dependencies": { "json-schema-walker": "^2.0.0" }, "peerDependencies": { "@hono/arktype-validator": "^2.0.0", "@hono/effect-validator": "^1.2.0", "@hono/typebox-validator": "^0.2.0 || ^0.3.0", "@hono/valibot-validator": "^0.5.1", "@hono/zod-validator": "^0.4.1", "@sinclair/typebox": "^0.34.9", "@valibot/to-json-schema": "^1.0.0-beta.3", "arktype": "^2.0.0-rc.25", "effect": "^3.11.3", "hono": "^4.6.13", "openapi-types": "^12.1.3", "valibot": "^1.0.0-beta.9", "zod": "^3.23.8", "zod-openapi": "^4.0.0" }, "optionalPeers": ["@hono/arktype-validator", "@hono/effect-validator", "@hono/typebox-validator", "@hono/valibot-validator", "@hono/zod-validator", "@sinclair/typebox", "@valibot/to-json-schema", "arktype", "effect", "hono", "openapi-types", "valibot", "zod", "zod-openapi"] }, "sha512-8UdlOwqGuKwtmGgiUcxRarIi0XOY9ZED+XfpVaZr9un5jl9p9dTLrnIhs1i+eTqvHNHV4QNF0C5bbfxdMBYe+w=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], + + "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="], + + "http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], + + "http-status-codes": ["http-status-codes@2.3.0", "", {}, "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "human-signals": ["human-signals@8.0.0", "", {}, "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA=="], + + "idb-keyval": ["idb-keyval@6.2.1", "", {}, "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "import-in-the-middle": ["import-in-the-middle@1.11.2", "", { "dependencies": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="], + + "interpret": ["interpret@2.2.0", "", {}, "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw=="], + + "ioredis": ["ioredis@5.5.0", "", { "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw=="], + + "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], + + "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + + "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "is-stream-ended": ["is-stream-ended@0.1.4", "", {}, "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw=="], + + "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], + + "is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], + + "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "isows": ["isows@1.0.6", "", { "peerDependencies": { "ws": "*" } }, "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw=="], + + "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], + + "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="], + + "istanbul-lib-source-maps": ["istanbul-lib-source-maps@5.0.6", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0" } }, "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A=="], + + "istanbul-reports": ["istanbul-reports@3.1.7", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "jake": ["jake@10.9.2", "", { "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", "filelist": "^1.0.4", "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" } }, "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA=="], + + "jest-docblock": ["jest-docblock@29.7.0", "", { "dependencies": { "detect-newline": "^3.0.0" } }, "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g=="], + + "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + + "jose": ["jose@6.0.10", "", {}, "sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "js2xmlparser": ["js2xmlparser@4.0.2", "", { "dependencies": { "xmlcreate": "^2.0.4" } }, "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA=="], + + "jsdoc": ["jsdoc@4.0.4", "", { "dependencies": { "@babel/parser": "^7.20.15", "@jsdoc/salty": "^0.2.1", "@types/markdown-it": "^14.1.1", "bluebird": "^3.7.2", "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", "klaw": "^3.0.0", "markdown-it": "^14.1.0", "markdown-it-anchor": "^8.6.7", "marked": "^4.0.10", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", "strip-json-comments": "^3.1.0", "underscore": "~1.13.2" }, "bin": { "jsdoc": "./jsdoc.js" } }, "sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + + "json-schema-ref-parser": ["json-schema-ref-parser@9.0.9", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "9.0.9" } }, "sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q=="], + + "json-schema-resolver": ["json-schema-resolver@3.0.0", "", { "dependencies": { "debug": "^4.1.1", "fast-uri": "^3.0.5", "rfdc": "^1.1.4" } }, "sha512-HqMnbz0tz2DaEJ3ntsqtx3ezzZyDE7G56A/pPY/NGmrPu76UzsWquOpHFRAf5beTNXoH2LU5cQePVvRli1nchA=="], + + "json-schema-walker": ["json-schema-walker@2.0.0", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.1.0", "clone": "^2.1.2" } }, "sha512-nXN2cMky0Iw7Af28w061hmxaPDaML5/bQD9nwm1lOoIKEGjHcRGxqWe4MfrkYThYAPjSUhmsp4bJNoLAyVn9Xw=="], + + "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], + + "jsonwebtoken": ["jsonwebtoken@9.0.2", "", { "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ=="], + + "jwa": ["jwa@1.4.1", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA=="], + + "jws": ["jws@3.2.2", "", { "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA=="], + + "keccak": ["keccak@3.0.4", "", { "dependencies": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0", "readable-stream": "^3.6.0" } }, "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q=="], + + "keyvaluestorage-interface": ["keyvaluestorage-interface@1.0.0", "", {}, "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g=="], + + "klaw": ["klaw@3.0.0", "", { "dependencies": { "graceful-fs": "^4.1.9" } }, "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g=="], + + "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "knex": ["knex@3.1.0", "", { "dependencies": { "colorette": "2.0.19", "commander": "^10.0.0", "debug": "4.3.4", "escalade": "^3.1.1", "esm": "^3.2.25", "get-package-type": "^0.1.0", "getopts": "2.3.0", "interpret": "^2.2.0", "lodash": "^4.17.21", "pg-connection-string": "2.6.2", "rechoir": "^0.8.0", "resolve-from": "^5.0.0", "tarn": "^3.0.2", "tildify": "2.0.0" }, "bin": { "knex": "bin/cli.js" } }, "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw=="], + + "koalas": ["koalas@1.0.2", "", {}, "sha512-RYhBbYaTTTHId3l6fnMZc3eGQNW6FVCqMG6AMwA5I1Mafr6AflaXeoi6x3xQuATRotGYRLk6+1ELZH4dstFNOA=="], + + "kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="], + + "ky": ["ky@1.8.0", "", {}, "sha512-DoKGmG27nT8t/1F9gV8vNzggJ3mLAyD49J8tTMWHeZvS8qLc7GlyTieicYtFzvDznMe/q2u38peOjkWc5/pjvw=="], + + "levn": ["levn@0.3.0", "", { "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" } }, "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA=="], + + "limiter": ["limiter@1.1.5", "", {}, "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="], + + "lit": ["lit@2.8.0", "", { "dependencies": { "@lit/reactive-element": "^1.6.0", "lit-element": "^3.3.0", "lit-html": "^2.8.0" } }, "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA=="], + + "lit-element": ["lit-element@3.3.3", "", { "dependencies": { "@lit-labs/ssr-dom-shim": "^1.1.0", "@lit/reactive-element": "^1.3.0", "lit-html": "^2.8.0" } }, "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA=="], + + "lit-html": ["lit-html@2.8.0", "", { "dependencies": { "@types/trusted-types": "^2.0.2" } }, "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q=="], + + "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], + + "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], + + "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], + + "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], + + "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], + + "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], + + "lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="], + + "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + + "lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="], + + "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], + + "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="], + + "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], + + "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], + + "long": ["long@5.3.0", "", {}, "sha512-5vvY5yF1zF/kXk+L94FRiTDa1Znom46UjPCH6/XbSvS8zBKMFBHTJk8KDMqJ+2J6QezQFi7k1k8v21ClJYHPaw=="], + + "loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="], + + "lru-cache": ["lru-cache@11.0.2", "", {}, "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA=="], + + "luxon": ["luxon@3.5.0", "", {}, "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ=="], + + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="], + + "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], + + "markdown-it": ["markdown-it@14.1.0", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg=="], + + "markdown-it-anchor": ["markdown-it-anchor@8.6.7", "", { "peerDependencies": { "@types/markdown-it": "*", "markdown-it": "*" } }, "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA=="], + + "marked": ["marked@4.3.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A=="], + + "mdurl": ["mdurl@2.0.0", "", {}, "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + + "minimalistic-assert": ["minimalistic-assert@1.0.1", "", {}, "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="], + + "minimalistic-crypto-utils": ["minimalistic-crypto-utils@1.0.1", "", {}, "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg=="], + + "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "minizlib": ["minizlib@3.0.1", "", { "dependencies": { "minipass": "^7.0.4", "rimraf": "^5.0.5" } }, "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg=="], + + "mipd": ["mipd@0.0.7", "", { "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg=="], + + "mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], + + "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], + + "mnemonist": ["mnemonist@0.39.8", "", { "dependencies": { "obliterator": "^2.0.1" } }, "sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ=="], + + "module-details-from-path": ["module-details-from-path@1.0.3", "", {}, "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A=="], + + "motion": ["motion@10.16.2", "", { "dependencies": { "@motionone/animation": "^10.15.1", "@motionone/dom": "^10.16.2", "@motionone/svelte": "^10.16.2", "@motionone/types": "^10.15.1", "@motionone/utils": "^10.15.1", "@motionone/vue": "^10.16.2" } }, "sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "msgpackr": ["msgpackr@1.11.2", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g=="], + + "msgpackr-extract": ["msgpackr-extract@3.0.3", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA=="], + + "multiformats": ["multiformats@9.9.0", "", {}, "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="], + + "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], + + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + + "neverthrow": ["neverthrow@8.1.1", "", { "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.24.0" } }, "sha512-DpbZ/UDI0B+TxJB1JysXSfi1++3YK2xLBqQLTlRN0b4zxlZ2MoiB+dKKV8dMRzt1fAFjRKDknXOVJgpl+a4Amw=="], + + "node-abort-controller": ["node-abort-controller@3.1.1", "", {}, "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="], + + "node-addon-api": ["node-addon-api@2.0.2", "", {}, "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA=="], + + "node-cron": ["node-cron@3.0.3", "", { "dependencies": { "uuid": "8.3.2" } }, "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "node-fetch-native": ["node-fetch-native@1.6.6", "", {}, "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="], + + "node-forge": ["node-forge@1.3.1", "", {}, "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA=="], + + "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], + + "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], + + "node-mock-http": ["node-mock-http@1.0.0", "", {}, "sha512-0uGYQ1WQL1M5kKvGRXWQ3uZCHtLTO8hln3oBjIusM75WoesZ909uQJs/Hb946i2SS+Gsrhkaa6iAO17jRIv6DQ=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], + + "nypm": ["nypm@0.5.4", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "tinyexec": "^0.3.2", "ufo": "^1.5.4" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA=="], + + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + + "obliterator": ["obliterator@2.0.5", "", {}, "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw=="], + + "obuf": ["obuf@1.1.2", "", {}, "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="], + + "ofetch": ["ofetch@1.4.1", "", { "dependencies": { "destr": "^2.0.3", "node-fetch-native": "^1.6.4", "ufo": "^1.5.4" } }, "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw=="], + + "ohash": ["ohash@1.1.4", "", {}, "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g=="], + + "on-exit-leak-free": ["on-exit-leak-free@0.2.0", "", {}, "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="], + + "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + + "open": ["open@10.1.1", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA=="], + + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], + + "openapi-typescript-codegen": ["openapi-typescript-codegen@0.25.0", "", { "dependencies": { "camelcase": "^6.3.0", "commander": "^11.0.0", "fs-extra": "^11.1.1", "handlebars": "^4.7.7", "json-schema-ref-parser": "^9.0.9" }, "bin": { "openapi": "bin/index.js" } }, "sha512-nN/TnIcGbP58qYgwEEy5FrAAjePcYgfMaCe3tsmYyTgI3v4RR9v8os14L+LEWDvV50+CmqiyTzRkKKtJeb6Ybg=="], + + "opentracing": ["opentracing@0.14.7", "", {}, "sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q=="], + + "optionator": ["optionator@0.8.3", "", { "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "word-wrap": "~1.2.3" } }, "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA=="], + + "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], + + "ox": ["ox@0.6.12", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-78hziRGLj0qTDa0UW4+ynv9tW2Cp1vmCfGokL8D7kiSDh6Y0LAfHL+HaDN4l2a9jcrOG3fexTDtLNtDNkEwLtg=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + + "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="], + + "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + + "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + + "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "pg": ["pg@8.13.3", "", { "dependencies": { "pg-connection-string": "^2.7.0", "pg-pool": "^3.7.1", "pg-protocol": "^1.7.1", "pg-types": "^2.1.0", "pgpass": "1.x" }, "optionalDependencies": { "pg-cloudflare": "^1.1.1" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-P6tPt9jXbL9HVu/SSRERNYaYG++MjnscnegFh9pPHihfoBSujsrka0hyuymMzeJKFWrcG8wvCKy8rCe8e5nDUQ=="], + + "pg-cloudflare": ["pg-cloudflare@1.1.1", "", {}, "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q=="], + + "pg-connection-string": ["pg-connection-string@2.6.2", "", {}, "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA=="], + + "pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="], + + "pg-numeric": ["pg-numeric@1.0.2", "", {}, "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw=="], + + "pg-pool": ["pg-pool@3.7.1", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-xIOsFoh7Vdhojas6q3596mXFsR8nwBQBXX5JiV7p9buEVAGqYL4yFzclON5P9vFrpu1u7Zwl2oriyDa89n0wbw=="], + + "pg-protocol": ["pg-protocol@1.7.1", "", {}, "sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ=="], + + "pg-types": ["pg-types@4.0.2", "", { "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", "postgres-array": "~3.0.1", "postgres-bytea": "~3.0.0", "postgres-date": "~2.1.0", "postgres-interval": "^3.0.0", "postgres-range": "^1.1.1" } }, "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng=="], + + "pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pino": ["pino@7.11.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.0.0", "on-exit-leak-free": "^0.2.0", "pino-abstract-transport": "v0.5.0", "pino-std-serializers": "^4.0.0", "process-warning": "^1.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.1.0", "safe-stable-stringify": "^2.1.0", "sonic-boom": "^2.2.1", "thread-stream": "^0.15.1" }, "bin": { "pino": "bin.js" } }, "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg=="], + + "pino-abstract-transport": ["pino-abstract-transport@0.5.0", "", { "dependencies": { "duplexify": "^4.1.2", "split2": "^4.0.0" } }, "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ=="], + + "pino-std-serializers": ["pino-std-serializers@4.0.0", "", {}, "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q=="], + + "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + + "pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="], + + "postcss": ["postcss@8.5.2", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA=="], + + "postgres-array": ["postgres-array@3.0.2", "", {}, "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog=="], + + "postgres-bytea": ["postgres-bytea@3.0.0", "", { "dependencies": { "obuf": "~1.1.2" } }, "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw=="], + + "postgres-date": ["postgres-date@2.1.0", "", {}, "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA=="], + + "postgres-interval": ["postgres-interval@3.0.0", "", {}, "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw=="], + + "postgres-range": ["postgres-range@1.1.4", "", {}, "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w=="], + + "pprof-format": ["pprof-format@2.1.0", "", {}, "sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw=="], + + "preact": ["preact@10.25.4", "", {}, "sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA=="], + + "prelude-ls": ["prelude-ls@1.1.2", "", {}, "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w=="], + + "pretty-ms": ["pretty-ms@9.2.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg=="], + + "prisma": ["prisma@6.3.1", "", { "dependencies": { "@prisma/engines": "6.3.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-JKCZWvBC3enxk51tY4TWzS4b5iRt4sSU1uHn2I183giZTvonXaQonzVtjLzpOHE7qu9MxY510kAtFGJwryKe3Q=="], + + "process-warning": ["process-warning@1.0.0", "", {}, "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q=="], + + "prom-client": ["prom-client@15.1.3", "", { "dependencies": { "@opentelemetry/api": "^1.4.0", "tdigest": "^0.1.1" } }, "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g=="], + + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + + "prool": ["prool@0.0.16", "", { "dependencies": { "change-case": "5.4.4", "eventemitter3": "^5.0.1", "execa": "^9.1.0", "get-port": "^7.1.0", "http-proxy": "^1.18.1", "tar": "7.2.0" }, "peerDependencies": { "@pimlico/alto": "*" }, "optionalPeers": ["@pimlico/alto"] }, "sha512-s+i66jsINIJQd8w5iGunT8hCeM6RSXjL8qgXDTvcIuaAOjVRVMh0/PgbJ90KR3JAprXWXpa5XQnDEc4fLnvy1Q=="], + + "proto3-json-serializer": ["proto3-json-serializer@2.0.2", "", { "dependencies": { "protobufjs": "^7.2.5" } }, "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ=="], + + "protobufjs": ["protobufjs@7.4.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw=="], + + "protobufjs-cli": ["protobufjs-cli@1.1.1", "", { "dependencies": { "chalk": "^4.0.0", "escodegen": "^1.13.0", "espree": "^9.0.0", "estraverse": "^5.1.0", "glob": "^8.0.0", "jsdoc": "^4.0.0", "minimist": "^1.2.0", "semver": "^7.1.2", "tmp": "^0.2.1", "uglify-js": "^3.7.7" }, "peerDependencies": { "protobufjs": "^7.0.0" }, "bin": { "pbjs": "bin/pbjs", "pbts": "bin/pbts" } }, "sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA=="], + + "proxy-compare": ["proxy-compare@2.5.1", "", {}, "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="], + + "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], + + "pvutils": ["pvutils@1.1.3", "", {}, "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ=="], + + "qrcode": ["qrcode@1.5.3", "", { "dependencies": { "dijkstrajs": "^1.0.1", "encode-utf8": "^1.0.3", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, "bin": { "qrcode": "bin/qrcode" } }, "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg=="], + + "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="], + + "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], + + "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], + + "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], + + "react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + + "react-remove-scroll": ["react-remove-scroll@2.6.3", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ=="], + + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], + + "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "real-require": ["real-require@0.1.0", "", {}, "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg=="], + + "rechoir": ["rechoir@0.8.0", "", { "dependencies": { "resolve": "^1.20.0" } }, "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ=="], + + "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], + + "redis-info": ["redis-info@3.1.0", "", { "dependencies": { "lodash": "^4.17.11" } }, "sha512-ER4L9Sh/vm63DkIE0bkSjxluQlioBiBgf5w1UuldaW/3vPcecdljVDisZhmnCMvsxHNiARTTDDHGg9cGwTfrKg=="], + + "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], + + "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "require-main-filename": ["require-main-filename@2.0.0", "", {}, "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="], + + "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="], + + "requizzle": ["requizzle@0.2.4", "", { "dependencies": { "lodash": "^4.17.21" } }, "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw=="], + + "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], + + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], + + "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + + "retry-request": ["retry-request@7.0.2", "", { "dependencies": { "@types/request": "^2.48.8", "extend": "^3.0.2", "teeny-request": "^9.0.0" } }, "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w=="], + + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], + + "rollup": ["rollup@4.34.6", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.6", "@rollup/rollup-android-arm64": "4.34.6", "@rollup/rollup-darwin-arm64": "4.34.6", "@rollup/rollup-darwin-x64": "4.34.6", "@rollup/rollup-freebsd-arm64": "4.34.6", "@rollup/rollup-freebsd-x64": "4.34.6", "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", "@rollup/rollup-linux-arm-musleabihf": "4.34.6", "@rollup/rollup-linux-arm64-gnu": "4.34.6", "@rollup/rollup-linux-arm64-musl": "4.34.6", "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", "@rollup/rollup-linux-riscv64-gnu": "4.34.6", "@rollup/rollup-linux-s390x-gnu": "4.34.6", "@rollup/rollup-linux-x64-gnu": "4.34.6", "@rollup/rollup-linux-x64-musl": "4.34.6", "@rollup/rollup-win32-arm64-msvc": "4.34.6", "@rollup/rollup-win32-ia32-msvc": "4.34.6", "@rollup/rollup-win32-x64-msvc": "4.34.6", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ=="], + + "run-applescript": ["run-applescript@7.0.0", "", {}, "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + + "scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "secp256k1": ["secp256k1@4.0.4", "", { "dependencies": { "elliptic": "^6.5.7", "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" } }, "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw=="], + + "semifies": ["semifies@1.0.0", "", {}, "sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw=="], + + "semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], + + "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "shell-quote": ["shell-quote@1.8.2", "", {}, "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA=="], + + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "sonic-boom": ["sonic-boom@2.8.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg=="], + + "source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + + "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="], + + "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + + "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], + + "std-env": ["std-env@3.8.0", "", {}, "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w=="], + + "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], + + "stream-events": ["stream-events@1.0.5", "", { "dependencies": { "stubs": "^3.0.0" } }, "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg=="], + + "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="], + + "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="], + + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "strnum": ["strnum@1.0.5", "", {}, "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="], + + "stubs": ["stubs@3.0.0", "", {}, "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw=="], + + "stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="], + + "superjson": ["superjson@2.2.2", "", { "dependencies": { "copy-anything": "^3.0.2" } }, "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "tar": ["tar@7.2.0", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.0", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w=="], + + "tarn": ["tarn@3.0.2", "", {}, "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ=="], + + "tdigest": ["tdigest@0.1.2", "", { "dependencies": { "bintrees": "1.0.2" } }, "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA=="], + + "teeny-request": ["teeny-request@9.0.0", "", { "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g=="], + + "test-exclude": ["test-exclude@7.0.1", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", "minimatch": "^9.0.4" } }, "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg=="], + + "text-hex": ["text-hex@1.0.0", "", {}, "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="], + + "thirdweb": ["thirdweb@5.96.4", "", { "dependencies": { "@coinbase/wallet-sdk": "4.3.0", "@emotion/react": "11.14.0", "@emotion/styled": "11.14.0", "@noble/curves": "1.8.2", "@noble/hashes": "1.7.2", "@passwordless-id/webauthn": "^2.1.2", "@radix-ui/react-dialog": "1.1.10", "@radix-ui/react-focus-scope": "1.1.4", "@radix-ui/react-icons": "1.3.2", "@radix-ui/react-tooltip": "1.2.3", "@tanstack/react-query": "5.74.4", "@thirdweb-dev/insight": "1.0.0", "@walletconnect/ethereum-provider": "2.19.1", "@walletconnect/sign-client": "2.19.1", "abitype": "1.0.8", "cross-spawn": "7.0.6", "fuse.js": "7.1.0", "input-otp": "^1.4.1", "mipd": "0.0.7", "open": "10.1.1", "ora": "8.2.0", "ox": "0.7.0", "prompts": "2.4.2", "toml": "3.0.0", "uqr": "0.1.2", "viem": "2.27.2" }, "peerDependencies": { "@aws-sdk/client-lambda": "^3", "@aws-sdk/credential-providers": "^3", "@coinbase/wallet-mobile-sdk": "^1", "@mobile-wallet-protocol/client": "^1", "@react-native-async-storage/async-storage": "^1 || ^2", "ethers": "^5 || ^6", "expo-linking": "^6", "expo-web-browser": "^13 || ^14", "react": "^18 || ^19", "react-native": "*", "react-native-aes-gcm-crypto": "^0.2", "react-native-passkey": "^3", "react-native-quick-crypto": ">=0.7.0-rc.6 || >=0.7", "react-native-svg": "^15", "typescript": ">=5.0.4" }, "optionalPeers": ["@aws-sdk/client-lambda", "@aws-sdk/credential-providers", "@coinbase/wallet-mobile-sdk", "@mobile-wallet-protocol/client", "@react-native-async-storage/async-storage", "ethers", "expo-linking", "expo-web-browser", "react", "react-native", "react-native-aes-gcm-crypto", "react-native-passkey", "react-native-quick-crypto", "react-native-svg", "typescript"], "bin": { "thirdweb": "dist/esm/cli/bin.js", "thirdweb-cli": "dist/esm/cli/bin.js" } }, "sha512-NASXEkaY96lYnPhVAaSBoUZ1Dpb1F0E/II+r/Gksmd+JCUNumylmmAwPwfQj58n0DuEM+tZ6kp2GhdHl4UAisA=="], + + "thread-stream": ["thread-stream@0.15.2", "", { "dependencies": { "real-require": "^0.1.0" } }, "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA=="], + + "tildify": ["tildify@2.0.0", "", {}, "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + + "tinypool": ["tinypool@1.0.2", "", {}, "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA=="], + + "tinyrainbow": ["tinyrainbow@1.2.0", "", {}, "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ=="], + + "tinyspy": ["tinyspy@3.0.2", "", {}, "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q=="], + + "tlhunter-sorted-set": ["tlhunter-sorted-set@0.1.0", "", {}, "sha512-eGYW4bjf1DtrHzUYxYfAcSytpOkA44zsr7G2n3PV7yOUR23vmkGe3LL4R+1jL9OsXtbsFOwe8XtbCrabeaEFnw=="], + + "tmp": ["tmp@0.2.3", "", {}, "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "triple-beam": ["triple-beam@1.4.1", "", {}, "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "ttl-set": ["ttl-set@1.0.0", "", { "dependencies": { "fast-fifo": "^1.3.2" } }, "sha512-2fuHn/UR+8Z9HK49r97+p2Ru1b5Eewg2QqPrU14BVCQ9QoyU3+vLLZk2WEiyZ9sgJh6W8G1cZr9I2NBLywAHrA=="], + + "type-check": ["type-check@0.3.2", "", { "dependencies": { "prelude-ls": "~1.1.2" } }, "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg=="], + + "type-fest": ["type-fest@4.40.0", "", {}, "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw=="], + + "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], + + "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="], + + "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], + + "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], + + "uint8arrays": ["uint8arrays@3.1.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog=="], + + "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], + + "underscore": ["underscore@1.13.7", "", {}, "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g=="], + + "undici": ["undici@6.21.1", "", {}, "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ=="], + + "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], + + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "unstorage": ["unstorage@1.14.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^3.6.0", "destr": "^2.0.3", "h3": "^1.13.0", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.4", "ofetch": "^1.4.1", "ufo": "^1.5.4" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.5.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3", "@deno/kv": ">=0.8.4", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.1" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-1SYeamwuYeQJtJ/USE1x4l17LkmQBzg7deBJ+U9qOBoHo15d1cDxG4jM31zKRgF7pG0kirZy4wVMX6WL6Zoscg=="], + + "uqr": ["uqr@0.1.2", "", {}, "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA=="], + + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], + + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + + "use-sync-external-store": ["use-sync-external-store@1.2.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="], + + "utf-8-validate": ["utf-8-validate@5.0.10", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + + "valtio": ["valtio@1.11.2", "", { "dependencies": { "proxy-compare": "2.5.1", "use-sync-external-store": "1.2.0" }, "peerDependencies": { "@types/react": ">=16.8", "react": ">=16.8" }, "optionalPeers": ["@types/react", "react"] }, "sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw=="], + + "viem": ["viem@2.23.2", "", { "dependencies": { "@noble/curves": "1.8.1", "@noble/hashes": "1.7.1", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", "ox": "0.6.7", "ws": "8.18.0" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA=="], + + "vite": ["vite@5.4.14", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA=="], + + "vite-node": ["vite-node@2.1.9", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA=="], + + "vitest": ["vitest@2.1.9", "", { "dependencies": { "@vitest/expect": "2.1.9", "@vitest/mocker": "2.1.9", "@vitest/pretty-format": "^2.1.9", "@vitest/runner": "2.1.9", "@vitest/snapshot": "2.1.9", "@vitest/spy": "2.1.9", "@vitest/utils": "2.1.9", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", "vite-node": "2.1.9", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", "@vitest/browser": "2.1.9", "@vitest/ui": "2.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="], + + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + + "winston": ["winston@3.17.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw=="], + + "winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + + "xmlcreate": ["xmlcreate@2.0.4", "", {}, "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg=="], + + "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], + + "yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="], + + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="], + + "zhead": ["zhead@2.2.4", "", {}, "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag=="], + + "zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="], + + "zod-openapi": ["zod-openapi@4.2.3", "", { "peerDependencies": { "zod": "^3.21.4" } }, "sha512-i0SqpcdXfsvVWTIY1Jl3Tk421s9fBIkpXvaA86zDas+8FjfZjm+GX6ot6SPB2SyuHwUNTN02gE5uIVlYXlyrDQ=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + + "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms": ["@google-cloud/kms@3.0.1", "", { "dependencies": { "google-gax": "^3.0.1" } }, "sha512-xUrhzattC5mkNqbfMcIgBzwAab9eXCYrn1R1KYUNV5E96fK7ciT57bJESaUQvin7XKd18sQcLRD+uOJ6eTfXbg=="], + + "@datadog/native-appsec/node-gyp-build": ["node-gyp-build@3.9.0", "", { "bin": { "node-gyp-build": "./bin.js", "node-gyp-build-test": "./build-test.js", "node-gyp-build-optional": "./optional.js" } }, "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A=="], + + "@datadog/native-iast-rewriter/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + + "@datadog/native-iast-taint-tracking/node-gyp-build": ["node-gyp-build@3.9.0", "", { "bin": { "node-gyp-build": "./bin.js", "node-gyp-build-test": "./build-test.js", "node-gyp-build-optional": "./optional.js" } }, "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A=="], + + "@datadog/native-metrics/node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="], + + "@datadog/native-metrics/node-gyp-build": ["node-gyp-build@3.9.0", "", { "bin": { "node-gyp-build": "./bin.js", "node-gyp-build-test": "./build-test.js", "node-gyp-build-optional": "./optional.js" } }, "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A=="], + + "@datadog/pprof/node-gyp-build": ["node-gyp-build@3.9.0", "", { "bin": { "node-gyp-build": "./bin.js", "node-gyp-build-test": "./build-test.js", "node-gyp-build-optional": "./optional.js" } }, "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A=="], + + "@emotion/babel-plugin/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], + + "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], + + "@hey-api/openapi-ts/commander": ["commander@13.0.0", "", {}, "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ=="], + + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@scalar/types/nanoid": ["nanoid@5.1.5", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw=="], + + "@types/request/form-data": ["form-data@2.5.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12", "safe-buffer": "^5.2.1" } }, "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q=="], + + "@walletconnect/environment/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "@walletconnect/events/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "@walletconnect/jsonrpc-utils/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "@walletconnect/jsonrpc-ws-connection/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], + + "@walletconnect/relay-auth/@noble/curves": ["@noble/curves@1.8.0", "", { "dependencies": { "@noble/hashes": "1.7.0" } }, "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ=="], + + "@walletconnect/relay-auth/@noble/hashes": ["@noble/hashes@1.7.0", "", {}, "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w=="], + + "@walletconnect/safe-json/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "@walletconnect/time/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "@walletconnect/window-getters/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "@walletconnect/window-metadata/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "c12/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "cosmiconfig/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "dd-trace/istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.0", "", {}, "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw=="], + + "dd-trace/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + + "elliptic/bn.js": ["bn.js@4.12.1", "", {}, "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg=="], + + "error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + + "escodegen/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], + + "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "execa/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + + "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + + "giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "giget/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + + "google-auth-library/jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + + "gtoken/jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + + "handlebars/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "http-proxy/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], + + "http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "jake/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "jake/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "jsdoc/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], + + "jsdoc/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "json-schema-walker/@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@11.9.1", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-OvyhwtYaWSTfo8NfibmFlgl+pIMaBOmN0OwZ3CPaGscEK3B8FCVDuQ7zgxY8seU/1kfSvNWnyB0DtKJyNLxX7g=="], + + "knex/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + + "knex/debug": ["debug@4.3.4", "", { "dependencies": { "ms": "2.1.2" } }, "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ=="], + + "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], + + "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "node-cron/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], + + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "pg/pg-connection-string": ["pg-connection-string@2.7.0", "", {}, "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA=="], + + "pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="], + + "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "prom-client/@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], + + "protobufjs-cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "protobufjs-cli/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], + + "qrcode/yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="], + + "secp256k1/node-addon-api": ["node-addon-api@5.1.0", "", {}, "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA=="], + + "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "thirdweb/@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], + + "thirdweb/@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], + + "thirdweb/ox": ["ox@0.7.0", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-mgRXlQdaNukQcsvGsPENGbyFvr7glob8UmOusDfWTw7A6LcjI+9OCelQ6NoAiSk6iM77R667qyUzn+n2Cr4SJw=="], + + "thirdweb/viem": ["viem@2.27.2", "", { "dependencies": { "@noble/curves": "1.8.1", "@noble/hashes": "1.7.1", "@scure/bip32": "1.6.2", "@scure/bip39": "1.5.4", "abitype": "1.0.8", "isows": "1.0.6", "ox": "0.6.9", "ws": "8.18.1" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-VwsB+RswcflbwBNPMvzTHuafDA51iT8v4SuIFcudTP2skmxcdodbgoOLP4dYELVnCzcedxoSJDOeext4V3zdnA=="], + + "unstorage/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "viem/ox": ["ox@0.6.7", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA=="], + + "vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "wrap-ansi/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + + "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax": ["google-gax@3.6.1", "", { "dependencies": { "@grpc/grpc-js": "~1.8.0", "@grpc/proto-loader": "^0.7.0", "@types/long": "^4.0.0", "@types/rimraf": "^3.0.2", "abort-controller": "^3.0.0", "duplexify": "^4.0.0", "fast-text-encoding": "^1.0.3", "google-auth-library": "^8.0.2", "is-stream-ended": "^0.1.4", "node-fetch": "^2.6.1", "object-hash": "^3.0.0", "proto3-json-serializer": "^1.0.0", "protobufjs": "7.2.4", "protobufjs-cli": "1.1.1", "retry-request": "^5.0.0" }, "bin": { "compileProtos": "build/tools/compileProtos.js", "minifyProtoJson": "build/tools/minify.js" } }, "sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="], + + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], + + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "c12/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "giget/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "giget/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "giget/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "giget/tar/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "giget/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "google-auth-library/jws/jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], + + "gtoken/jws/jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], + + "jake/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "knex/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], + + "pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="], + + "pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="], + + "pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="], + + "pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="], + + "protobufjs-cli/glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + + "qrcode/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="], + + "qrcode/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "qrcode/yargs/y18n": ["y18n@4.0.3", "", {}, "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="], + + "qrcode/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "thirdweb/viem/@noble/curves": ["@noble/curves@1.8.1", "", { "dependencies": { "@noble/hashes": "1.7.1" } }, "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ=="], + + "thirdweb/viem/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], + + "thirdweb/viem/ox": ["ox@0.6.9", "", { "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", "@noble/hashes": "^1.5.0", "@scure/bip32": "^1.5.0", "@scure/bip39": "^1.4.0", "abitype": "^1.0.6", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug=="], + + "thirdweb/viem/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], + + "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + + "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/@grpc/grpc-js": ["@grpc/grpc-js@1.8.22", "", { "dependencies": { "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" } }, "sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library": ["google-auth-library@8.9.0", "", { "dependencies": { "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "fast-text-encoding": "^1.0.0", "gaxios": "^5.0.0", "gcp-metadata": "^5.3.0", "gtoken": "^6.1.0", "jws": "^4.0.0", "lru-cache": "^6.0.0" } }, "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/proto3-json-serializer": ["proto3-json-serializer@1.1.1", "", { "dependencies": { "protobufjs": "^7.0.0" } }, "sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/protobufjs": ["protobufjs@7.2.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/retry-request": ["retry-request@5.0.2", "", { "dependencies": { "debug": "^4.1.1", "extend": "^3.0.2" } }, "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ=="], + + "giget/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "qrcode/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "qrcode/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + + "qrcode/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "qrcode/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "qrcode/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], + + "yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/gaxios": ["gaxios@5.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^5.0.0", "is-stream": "^2.0.0", "node-fetch": "^2.6.9" } }, "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/gcp-metadata": ["gcp-metadata@5.3.0", "", { "dependencies": { "gaxios": "^5.0.0", "json-bigint": "^1.0.0" } }, "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/gtoken": ["gtoken@6.1.2", "", { "dependencies": { "gaxios": "^5.0.1", "google-p12-pem": "^4.0.0", "jws": "^4.0.0" } }, "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/proto3-json-serializer/protobufjs": ["protobufjs@7.4.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw=="], + + "qrcode/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "qrcode/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/gaxios/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/jws/jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "@cloud-cryptographic-wallet/cloud-kms-signer/@google-cloud/kms/google-gax/google-auth-library/gaxios/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + } +} diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 000000000..c56676d6d --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from "drizzle-kit"; + +const databaseUrl = process.env.POSTGRES_CONNECTION_URL; + +if (!databaseUrl) { + throw new Error("DATABASE_URL environment variable is not set"); +} + +export default defineConfig({ + out: "./drizzle", + schema: "./src/db/schema.ts", + dialect: "postgresql", + dbCredentials: { + url: databaseUrl, + }, +}); diff --git a/drizzle/0000_broad_blacklash.sql b/drizzle/0000_broad_blacklash.sql new file mode 100644 index 000000000..8431563ef --- /dev/null +++ b/drizzle/0000_broad_blacklash.sql @@ -0,0 +1,142 @@ +CREATE TABLE "address_subscriptions" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "chainId" text NOT NULL, + "address" text NOT NULL, + "conditions" jsonb[], + "webhookId" uuid, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + "deletedAt" timestamp with time zone +); +--> statement-breakpoint +CREATE TABLE "configuration" ( + "id" text PRIMARY KEY DEFAULT 'default' NOT NULL, + "chainOverrides" json DEFAULT '[]'::json NOT NULL, + "webhookAuthBearerToken" text, + "authDomain" text DEFAULT 'thirdweb.com' NOT NULL, + "authEoaEncryptedJson" text NOT NULL, + "accessControlAllowOrigin" json DEFAULT '["https://thirdweb.com/","https://embed.ipfscdn.io/"]'::json NOT NULL, + "ipAllowlist" json[], + "mtlsCertificateEncrypted" text, + "mtlsPrivateKeyEncrypted" text, + "walletProviderConfigs" json DEFAULT '{}'::json NOT NULL +); +--> statement-breakpoint +CREATE TABLE "eoa_credentials" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "type" text NOT NULL, + "label" text NOT NULL, + "data" json NOT NULL, + "isDefault" boolean DEFAULT false NOT NULL, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + "deletedAt" timestamp with time zone +); +--> statement-breakpoint +CREATE TABLE "eoas" ( + "address" text PRIMARY KEY NOT NULL, + "type" text NOT NULL, + "encryptedJson" text, + "label" text NOT NULL, + "credentialId" uuid, + "platformIdentifiers" jsonb, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + "deletedAt" timestamp with time zone +); +--> statement-breakpoint +CREATE TABLE "keypairs" ( + "hash" text PRIMARY KEY NOT NULL, + "publicKey" text NOT NULL, + "algorithm" text NOT NULL, + "label" text, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + "deletedAt" timestamp with time zone +); +--> statement-breakpoint +CREATE TABLE "permissions" ( + "accountAddress" text PRIMARY KEY NOT NULL, + "permissions" text NOT NULL, + "label" text +); +--> statement-breakpoint +CREATE TABLE "relayers" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "label" text, + "chainId" text NOT NULL, + "accountAddress" text NOT NULL, + "allowedContracts" jsonb DEFAULT '[]'::jsonb, + "allowedForwarders" jsonb DEFAULT '[]'::jsonb +); +--> statement-breakpoint +CREATE TABLE "smart_accounts" ( + "address" text NOT NULL, + "signerAddress" text NOT NULL, + "label" text NOT NULL, + "factoryAddress" text NOT NULL, + "entrypointAddress" text NOT NULL, + "accountSalt" text, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + "deletedAt" timestamp with time zone, + CONSTRAINT "smart_accounts_address_signerAddress_pk" PRIMARY KEY("address","signerAddress") +); +--> statement-breakpoint +CREATE TABLE "tokens" ( + "id" text PRIMARY KEY NOT NULL, + "tokenMask" text NOT NULL, + "accountAddress" text NOT NULL, + "isAccessToken" boolean NOT NULL, + "label" text, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "expiresAt" timestamp with time zone NOT NULL, + "revokedAt" timestamp with time zone +); +--> statement-breakpoint +CREATE TABLE "transactions" ( + "id" text NOT NULL, + "batchIndex" integer NOT NULL, + "chainId" text NOT NULL, + "from" text, + "transactionParams" jsonb NOT NULL, + "transactionHash" text, + "confirmedAt" timestamp with time zone, + "confirmedAtBlockNumber" text, + "enrichedData" jsonb DEFAULT '[]'::jsonb NOT NULL, + "executionParams" jsonb NOT NULL, + "executionResult" jsonb, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "errorMessage" text, + "cancelledAt" timestamp with time zone, + CONSTRAINT "transactions_id_batchIndex_pk" PRIMARY KEY("id","batchIndex") +); +--> statement-breakpoint +CREATE TABLE "webhooks" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "label" text, + "url" text NOT NULL, + "secret" text NOT NULL, + "eventType" text NOT NULL, + "createdAt" timestamp with time zone DEFAULT now() NOT NULL, + "updatedAt" timestamp with time zone NOT NULL, + "revokedAt" timestamp with time zone +); +--> statement-breakpoint +ALTER TABLE "address_subscriptions" ADD CONSTRAINT "address_subscriptions_webhookId_webhooks_id_fk" FOREIGN KEY ("webhookId") REFERENCES "public"."webhooks"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "eoas" ADD CONSTRAINT "eoas_credentialId_eoa_credentials_id_fk" FOREIGN KEY ("credentialId") REFERENCES "public"."eoa_credentials"("id") ON DELETE set null ON UPDATE cascade;--> statement-breakpoint +ALTER TABLE "smart_accounts" ADD CONSTRAINT "smart_accounts_signerAddress_eoas_address_fk" FOREIGN KEY ("signerAddress") REFERENCES "public"."eoas"("address") ON DELETE no action ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "address_subscriptions_deleted_at_not_null_idx" ON "address_subscriptions" USING btree ("deletedAt") WHERE "address_subscriptions"."deletedAt" IS NOT NULL;--> statement-breakpoint +CREATE INDEX "address_subscriptions_webhook_id_idx" ON "address_subscriptions" USING btree ("webhookId");--> statement-breakpoint +CREATE INDEX "address_subscriptions_chainId_idx" ON "address_subscriptions" USING btree ("chainId");--> statement-breakpoint +CREATE INDEX "address_subscriptions_address_idx" ON "address_subscriptions" USING btree ("address");--> statement-breakpoint +CREATE INDEX "eoa_credentials_type_idx" ON "eoa_credentials" USING btree ("type");--> statement-breakpoint +CREATE UNIQUE INDEX "eoa_credentials_type_is_default_key" ON "eoa_credentials" USING btree ("type") WHERE "eoa_credentials"."isDefault" IS TRUE;--> statement-breakpoint +CREATE INDEX "eoa_credentials_deleted_at_not_null_idx" ON "eoa_credentials" USING btree ("deletedAt") WHERE "eoa_credentials"."deletedAt" IS NOT NULL;--> statement-breakpoint +CREATE INDEX "eoas_deleted_at_not_null_idx" ON "eoas" USING btree ("deletedAt") WHERE "eoas"."deletedAt" IS NOT NULL;--> statement-breakpoint +CREATE INDEX "smart_accounts_signer_address_idx" ON "smart_accounts" USING btree ("signerAddress");--> statement-breakpoint +CREATE INDEX "smart_accounts_deleted_at_not_null_idx" ON "smart_accounts" USING btree ("deletedAt") WHERE "smart_accounts"."deletedAt" IS NOT NULL;--> statement-breakpoint +CREATE INDEX "transaction_hash_idx" ON "transactions" USING btree ("transactionHash");--> statement-breakpoint +CREATE INDEX "from_idx" ON "transactions" USING btree ("from");--> statement-breakpoint +CREATE INDEX "execution_params_idx" ON "transactions" USING gin ("executionParams");--> statement-breakpoint +CREATE INDEX "execution_result_idx" ON "transactions" USING gin ("executionResult"); \ No newline at end of file diff --git a/drizzle/0001_absent_vertigo.sql b/drizzle/0001_absent_vertigo.sql new file mode 100644 index 000000000..057a958ee --- /dev/null +++ b/drizzle/0001_absent_vertigo.sql @@ -0,0 +1,2 @@ +ALTER TABLE "transactions" ADD COLUMN "clientId" text DEFAULT 'PRE_MIGRATION' NOT NULL;--> statement-breakpoint +CREATE INDEX "client_id_idx" ON "transactions" USING btree ("clientId"); \ No newline at end of file diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json new file mode 100644 index 000000000..fa2e1792f --- /dev/null +++ b/drizzle/meta/0000_snapshot.json @@ -0,0 +1,1001 @@ +{ + "id": "5fbb4f8e-28bd-4802-877f-23a45622e6c6", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.address_subscriptions": { + "name": "address_subscriptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chainId": { + "name": "chainId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conditions": { + "name": "conditions", + "type": "jsonb[]", + "primaryKey": false, + "notNull": false + }, + "webhookId": { + "name": "webhookId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "address_subscriptions_deleted_at_not_null_idx": { + "name": "address_subscriptions_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"address_subscriptions\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "address_subscriptions_webhook_id_idx": { + "name": "address_subscriptions_webhook_id_idx", + "columns": [ + { + "expression": "webhookId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "address_subscriptions_chainId_idx": { + "name": "address_subscriptions_chainId_idx", + "columns": [ + { + "expression": "chainId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "address_subscriptions_address_idx": { + "name": "address_subscriptions_address_idx", + "columns": [ + { + "expression": "address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "address_subscriptions_webhookId_webhooks_id_fk": { + "name": "address_subscriptions_webhookId_webhooks_id_fk", + "tableFrom": "address_subscriptions", + "tableTo": "webhooks", + "columnsFrom": [ + "webhookId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.configuration": { + "name": "configuration", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'default'" + }, + "chainOverrides": { + "name": "chainOverrides", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'[]'::json" + }, + "webhookAuthBearerToken": { + "name": "webhookAuthBearerToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "authDomain": { + "name": "authDomain", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'thirdweb.com'" + }, + "authEoaEncryptedJson": { + "name": "authEoaEncryptedJson", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessControlAllowOrigin": { + "name": "accessControlAllowOrigin", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'[\"https://thirdweb.com/",\"https://embed.ipfscdn.io/"]'::json" + }, + "ipAllowlist": { + "name": "ipAllowlist", + "type": "json[]", + "primaryKey": false, + "notNull": false + }, + "mtlsCertificateEncrypted": { + "name": "mtlsCertificateEncrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mtlsPrivateKeyEncrypted": { + "name": "mtlsPrivateKeyEncrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "walletProviderConfigs": { + "name": "walletProviderConfigs", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'::json" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.eoa_credentials": { + "name": "eoa_credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "isDefault": { + "name": "isDefault", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "eoa_credentials_type_idx": { + "name": "eoa_credentials_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "eoa_credentials_type_is_default_key": { + "name": "eoa_credentials_type_is_default_key", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"eoa_credentials\".\"isDefault\" IS TRUE", + "concurrently": false, + "method": "btree", + "with": {} + }, + "eoa_credentials_deleted_at_not_null_idx": { + "name": "eoa_credentials_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"eoa_credentials\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.eoas": { + "name": "eoas", + "schema": "", + "columns": { + "address": { + "name": "address", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "encryptedJson": { + "name": "encryptedJson", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credentialId": { + "name": "credentialId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "platformIdentifiers": { + "name": "platformIdentifiers", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "eoas_deleted_at_not_null_idx": { + "name": "eoas_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"eoas\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "eoas_credentialId_eoa_credentials_id_fk": { + "name": "eoas_credentialId_eoa_credentials_id_fk", + "tableFrom": "eoas", + "tableTo": "eoa_credentials", + "columnsFrom": [ + "credentialId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.keypairs": { + "name": "keypairs", + "schema": "", + "columns": { + "hash": { + "name": "hash", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publicKey": { + "name": "publicKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "algorithm": { + "name": "algorithm", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "accountAddress": { + "name": "accountAddress", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.relayers": { + "name": "relayers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chainId": { + "name": "chainId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accountAddress": { + "name": "accountAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allowedContracts": { + "name": "allowedContracts", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "allowedForwarders": { + "name": "allowedForwarders", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.smart_accounts": { + "name": "smart_accounts", + "schema": "", + "columns": { + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signerAddress": { + "name": "signerAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "factoryAddress": { + "name": "factoryAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entrypointAddress": { + "name": "entrypointAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accountSalt": { + "name": "accountSalt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "smart_accounts_signer_address_idx": { + "name": "smart_accounts_signer_address_idx", + "columns": [ + { + "expression": "signerAddress", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "smart_accounts_deleted_at_not_null_idx": { + "name": "smart_accounts_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"smart_accounts\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "smart_accounts_signerAddress_eoas_address_fk": { + "name": "smart_accounts_signerAddress_eoas_address_fk", + "tableFrom": "smart_accounts", + "tableTo": "eoas", + "columnsFrom": [ + "signerAddress" + ], + "columnsTo": [ + "address" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "smart_accounts_address_signerAddress_pk": { + "name": "smart_accounts_address_signerAddress_pk", + "columns": [ + "address", + "signerAddress" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tokens": { + "name": "tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tokenMask": { + "name": "tokenMask", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accountAddress": { + "name": "accountAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isAccessToken": { + "name": "isAccessToken", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "revokedAt": { + "name": "revokedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.transactions": { + "name": "transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "batchIndex": { + "name": "batchIndex", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "chainId": { + "name": "chainId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "from": { + "name": "from", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transactionParams": { + "name": "transactionParams", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "transactionHash": { + "name": "transactionHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "confirmedAt": { + "name": "confirmedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "confirmedAtBlockNumber": { + "name": "confirmedAtBlockNumber", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enrichedData": { + "name": "enrichedData", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "executionParams": { + "name": "executionParams", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "executionResult": { + "name": "executionResult", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "errorMessage": { + "name": "errorMessage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancelledAt": { + "name": "cancelledAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "transaction_hash_idx": { + "name": "transaction_hash_idx", + "columns": [ + { + "expression": "transactionHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "from_idx": { + "name": "from_idx", + "columns": [ + { + "expression": "from", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_params_idx": { + "name": "execution_params_idx", + "columns": [ + { + "expression": "executionParams", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "execution_result_idx": { + "name": "execution_result_idx", + "columns": [ + { + "expression": "executionResult", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "transactions_id_batchIndex_pk": { + "name": "transactions_id_batchIndex_pk", + "columns": [ + "id", + "batchIndex" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhooks": { + "name": "webhooks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "eventType": { + "name": "eventType", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "revokedAt": { + "name": "revokedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json new file mode 100644 index 000000000..84b5fdcd2 --- /dev/null +++ b/drizzle/meta/0001_snapshot.json @@ -0,0 +1,1023 @@ +{ + "id": "c083f364-16f8-44cd-8bdc-bcd839ca6b57", + "prevId": "5fbb4f8e-28bd-4802-877f-23a45622e6c6", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.address_subscriptions": { + "name": "address_subscriptions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chainId": { + "name": "chainId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "conditions": { + "name": "conditions", + "type": "jsonb[]", + "primaryKey": false, + "notNull": false + }, + "webhookId": { + "name": "webhookId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "address_subscriptions_deleted_at_not_null_idx": { + "name": "address_subscriptions_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"address_subscriptions\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "address_subscriptions_webhook_id_idx": { + "name": "address_subscriptions_webhook_id_idx", + "columns": [ + { + "expression": "webhookId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "address_subscriptions_chainId_idx": { + "name": "address_subscriptions_chainId_idx", + "columns": [ + { + "expression": "chainId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "address_subscriptions_address_idx": { + "name": "address_subscriptions_address_idx", + "columns": [ + { + "expression": "address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "address_subscriptions_webhookId_webhooks_id_fk": { + "name": "address_subscriptions_webhookId_webhooks_id_fk", + "tableFrom": "address_subscriptions", + "tableTo": "webhooks", + "columnsFrom": [ + "webhookId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.configuration": { + "name": "configuration", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'default'" + }, + "chainOverrides": { + "name": "chainOverrides", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'[]'::json" + }, + "webhookAuthBearerToken": { + "name": "webhookAuthBearerToken", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "authDomain": { + "name": "authDomain", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'thirdweb.com'" + }, + "authEoaEncryptedJson": { + "name": "authEoaEncryptedJson", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessControlAllowOrigin": { + "name": "accessControlAllowOrigin", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'[\"https://thirdweb.com/",\"https://embed.ipfscdn.io/"]'::json" + }, + "ipAllowlist": { + "name": "ipAllowlist", + "type": "json[]", + "primaryKey": false, + "notNull": false + }, + "mtlsCertificateEncrypted": { + "name": "mtlsCertificateEncrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mtlsPrivateKeyEncrypted": { + "name": "mtlsPrivateKeyEncrypted", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "walletProviderConfigs": { + "name": "walletProviderConfigs", + "type": "json", + "primaryKey": false, + "notNull": true, + "default": "'{}'::json" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.eoa_credentials": { + "name": "eoa_credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "json", + "primaryKey": false, + "notNull": true + }, + "isDefault": { + "name": "isDefault", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "eoa_credentials_type_idx": { + "name": "eoa_credentials_type_idx", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "eoa_credentials_type_is_default_key": { + "name": "eoa_credentials_type_is_default_key", + "columns": [ + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"eoa_credentials\".\"isDefault\" IS TRUE", + "concurrently": false, + "method": "btree", + "with": {} + }, + "eoa_credentials_deleted_at_not_null_idx": { + "name": "eoa_credentials_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"eoa_credentials\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.eoas": { + "name": "eoas", + "schema": "", + "columns": { + "address": { + "name": "address", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "encryptedJson": { + "name": "encryptedJson", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credentialId": { + "name": "credentialId", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "platformIdentifiers": { + "name": "platformIdentifiers", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "eoas_deleted_at_not_null_idx": { + "name": "eoas_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"eoas\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "eoas_credentialId_eoa_credentials_id_fk": { + "name": "eoas_credentialId_eoa_credentials_id_fk", + "tableFrom": "eoas", + "tableTo": "eoa_credentials", + "columnsFrom": [ + "credentialId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.keypairs": { + "name": "keypairs", + "schema": "", + "columns": { + "hash": { + "name": "hash", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "publicKey": { + "name": "publicKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "algorithm": { + "name": "algorithm", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.permissions": { + "name": "permissions", + "schema": "", + "columns": { + "accountAddress": { + "name": "accountAddress", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.relayers": { + "name": "relayers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chainId": { + "name": "chainId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accountAddress": { + "name": "accountAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "allowedContracts": { + "name": "allowedContracts", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "allowedForwarders": { + "name": "allowedForwarders", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.smart_accounts": { + "name": "smart_accounts", + "schema": "", + "columns": { + "address": { + "name": "address", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "signerAddress": { + "name": "signerAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "factoryAddress": { + "name": "factoryAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "entrypointAddress": { + "name": "entrypointAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accountSalt": { + "name": "accountSalt", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deletedAt": { + "name": "deletedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "smart_accounts_signer_address_idx": { + "name": "smart_accounts_signer_address_idx", + "columns": [ + { + "expression": "signerAddress", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "smart_accounts_deleted_at_not_null_idx": { + "name": "smart_accounts_deleted_at_not_null_idx", + "columns": [ + { + "expression": "deletedAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"smart_accounts\".\"deletedAt\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "smart_accounts_signerAddress_eoas_address_fk": { + "name": "smart_accounts_signerAddress_eoas_address_fk", + "tableFrom": "smart_accounts", + "tableTo": "eoas", + "columnsFrom": [ + "signerAddress" + ], + "columnsTo": [ + "address" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "smart_accounts_address_signerAddress_pk": { + "name": "smart_accounts_address_signerAddress_pk", + "columns": [ + "address", + "signerAddress" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tokens": { + "name": "tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tokenMask": { + "name": "tokenMask", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accountAddress": { + "name": "accountAddress", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "isAccessToken": { + "name": "isAccessToken", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expiresAt": { + "name": "expiresAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "revokedAt": { + "name": "revokedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.transactions": { + "name": "transactions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "batchIndex": { + "name": "batchIndex", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "clientId": { + "name": "clientId", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'PRE_MIGRATION'" + }, + "chainId": { + "name": "chainId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "from": { + "name": "from", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "transactionParams": { + "name": "transactionParams", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "transactionHash": { + "name": "transactionHash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "confirmedAt": { + "name": "confirmedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "confirmedAtBlockNumber": { + "name": "confirmedAtBlockNumber", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enrichedData": { + "name": "enrichedData", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "executionParams": { + "name": "executionParams", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "executionResult": { + "name": "executionResult", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "errorMessage": { + "name": "errorMessage", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cancelledAt": { + "name": "cancelledAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "transaction_hash_idx": { + "name": "transaction_hash_idx", + "columns": [ + { + "expression": "transactionHash", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "client_id_idx": { + "name": "client_id_idx", + "columns": [ + { + "expression": "clientId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "from_idx": { + "name": "from_idx", + "columns": [ + { + "expression": "from", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "execution_params_idx": { + "name": "execution_params_idx", + "columns": [ + { + "expression": "executionParams", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + }, + "execution_result_idx": { + "name": "execution_result_idx", + "columns": [ + { + "expression": "executionResult", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "transactions_id_batchIndex_pk": { + "name": "transactions_id_batchIndex_pk", + "columns": [ + "id", + "batchIndex" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.webhooks": { + "name": "webhooks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "eventType": { + "name": "eventType", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "revokedAt": { + "name": "revokedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json new file mode 100644 index 000000000..189e901aa --- /dev/null +++ b/drizzle/meta/_journal.json @@ -0,0 +1,20 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1740684747056, + "tag": "0000_broad_blacklash", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1746474850681, + "tag": "0001_absent_vertigo", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index e8b1eb1ae..f8362076d 100644 --- a/package.json +++ b/package.json @@ -3,109 +3,107 @@ "version": "0.1.0", "license": "Apache-2.0", "description": "thirdweb Engine", - "main": "src/server/index.ts", "author": "thirdweb engineering ", "type": "module", + "engines": { + "node": ">=22.1.0", + "pnpm": ">=9" + }, "scripts": { - "dev": "yarn dev:infra && yarn dev:db && yarn dev:run", + "dev": "pnpm dev:infra && pnpm dev:run", + "check": "tsc --noEmit", "dev:infra": "docker compose -f ./docker-compose.yml up -d", - "dev:db": "yarn prisma:setup:dev", - "dev:run": "npx nodemon --watch 'src/**/*.ts' --exec 'npx tsx ./src/index.ts' --files src/index.ts", - "build": "rm -rf dist && tsc -p ./tsconfig.json --outDir dist", + "dev:run": "bun --watch src/index.ts", + "build": "rm -rf dist && tsc -p ./tsconfig.json", "build:docker": "docker build . -f Dockerfile -t prod", - "generate:sdk": "npx tsx ./src/scripts/generate-sdk && cd ./sdk && yarn build", - "prisma:setup:dev": "npx tsx ./src/scripts/setup-db.ts", - "prisma:setup:prod": "npx tsx ./dist/scripts/setup-db.js", - "start": "yarn prisma:setup:prod && yarn start:migrations && yarn start:run", - "start:migrations": "npx tsx ./dist/scripts/apply-migrations.js", - "start:run": "node --experimental-specifier-resolution=node ./dist/index.js", + "generate:sdk": "tsx ./src/scripts/generate-sdk && cd ./sdk && pnpm build", "start:docker": "docker compose --profile engine --env-file ./.env up --remove-orphans", "start:docker-force-build": "docker compose --profile engine --env-file ./.env up --remove-orphans --build", "test:unit": "vitest", "test:coverage": "vitest run --coverage", - "lint": "yarn biome lint", - "copy-files": "cp -r ./src/prisma ./dist/" + "lint": "pnpm biome lint" }, "dependencies": { "@aws-sdk/client-kms": "^3.679.0", - "@bull-board/fastify": "^5.23.0", + "@bull-board/api": "^6.7.9", + "@bull-board/hono": "^6.7.9", "@circle-fin/developer-controlled-wallets": "^7.0.0", "@cloud-cryptographic-wallet/cloud-kms-signer": "^0.1.2", "@cloud-cryptographic-wallet/signer": "^0.0.5", - "@ethersproject/json-wallets": "^5.7.0", - "@fastify/swagger": "^8.9.0", - "@fastify/type-provider-typebox": "^3.2.0", - "@fastify/websocket": "^8.2.0", + "@fastify/swagger": "^9.4.2", + "@fastify/type-provider-typebox": "^5.1.0", + "@fastify/websocket": "^11.0.0", "@google-cloud/kms": "^4.4.0", - "@prisma/client": "5.17.0", + "@hono/zod-validator": "^0.4.3", + "@noble/ciphers": "^1.2.1", + "@noble/curves": "^1.8.1", + "@noble/hashes": "^1.7.1", + "@scalar/hono-api-reference": "^0.8.2", "@sinclair/typebox": "^0.31.28", "@t3-oss/env-core": "^0.6.0", - "@thirdweb-dev/auth": "^4.1.87", - "@thirdweb-dev/chains": "^0.1.77", - "@thirdweb-dev/sdk": "^4.0.89", - "@thirdweb-dev/service-utils": "^0.4.28", "@types/base-64": "^1.0.2", + "abitype": "^1.0.8", "aws-kms-signer": "^0.5.3", "base-64": "^1.0.0", - "bullmq": "^5.11.0", + "bullmq": "^5.41.3", "cron-parser": "^4.9.0", - "crypto": "^1.0.1", - "crypto-js": "^4.2.0", - "dd-trace": "^5.23.0", - "dotenv": "^16.0.3", - "ethers": "5", - "ethers-aws-kms-signer": "^1.3.2", - "ethers-gcp-kms-signer": "^1.1.6", - "fastify": "^4.28.1", - "fastify-plugin": "^4.5.0", + "dd-trace": "^5.37.0", + "dotenv": "^16.4.7", + "drizzle-orm": "^0.39.3", + "drizzle-zod": "^0.7.0", + "hono": "^4.7.1", + "hono-openapi": "^0.4.4", "http-status-codes": "^2.2.0", - "ioredis": "^5.4.1", + "ioredis": "^5.5.0", + "jose": "^6.0.10", "jsonwebtoken": "^9.0.2", "knex": "^3.1.0", + "ky": "^1.8.0", + "lru-cache": "^11.0.2", "mnemonist": "^0.39.8", + "neverthrow": "^8.1.1", "node-cron": "^3.0.2", - "ox": "^0.6.9", - "pg": "^8.11.3", - "prisma": "^5.14.0", + "ox": "^0.6.12", + "pg": "^8.13.3", "prom-client": "^15.1.3", "superjson": "^2.2.1", - "thirdweb": "^5.83.0", + "thirdweb": "^5.96.4", "undici": "^6.20.1", "uuid": "^9.0.1", "viem": "^2.21.54", "winston": "^3.14.1", - "zod": "^3.23.8" + "zod": "^3.24.2", + "zod-openapi": "^4.2.3" }, "devDependencies": { - "@biomejs/biome": "^1.9.2", + "@biomejs/biome": "^2.0.0-beta.1", + "@types/bun": "^1.2.2", "@types/cli-progress": "^3.11.3", "@types/crypto-js": "^4.2.2", "@types/jsonwebtoken": "^9.0.6", - "@types/node": "^18.15.4", "@types/node-cron": "^3.0.8", - "@types/pg": "^8.6.6", + "@types/pg": "^8.11.11", "@types/uuid": "^9.0.1", "@types/ws": "^8.5.5", "@vitest/coverage-v8": "^2.0.3", + "drizzle-kit": "^0.30.4", "openapi-typescript-codegen": "^0.25.0", "prool": "^0.0.16", - "typescript": "^5.1.3", + "typescript": "^5.7.3", "vitest": "^2.0.3" }, - "prisma": { - "schema": "./src/prisma/schema.prisma" - }, - "resolutions": { - "@thirdweb-dev/auth/**/axios": ">=1.7.8", - "@thirdweb-dev/auth/**/web3-utils": ">=4.2.1", - "@grpc/grpc-js": ">=1.8.22", - "body-parser": ">=1.20.3", - "cookie": ">=0.7.0", - "elliptic": ">=6.6.0", - "micromatch": ">=4.0.8", - "secp256k1": ">=4.0.4", - "ws": ">=8.17.1", - "cross-spawn": ">=7.0.6" - }, - "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" + "pnpm": { + "overrides": { + "@thirdweb-dev/auth>axios": ">=1.7.8", + "@thirdweb-dev/auth>web3-utils": ">=4.2.1", + "@grpc/grpc-js": ">=1.8.22", + "body-parser": ">=1.20.3", + "cookie": ">=0.7.0", + "elliptic": ">=6.6.0", + "micromatch": ">=4.0.8", + "secp256k1": ">=4.0.4", + "ws": ">=8.17.1", + "cross-spawn": ">=7.0.6" + } + } } diff --git a/src/scripts/generate-sdk.ts b/scripts/generate-sdk.ts similarity index 100% rename from src/scripts/generate-sdk.ts rename to scripts/generate-sdk.ts diff --git a/sdk/.babelrc b/sdk/.babelrc deleted file mode 100644 index e15ac017a..000000000 --- a/sdk/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-typescript"] -} diff --git a/sdk/old_openapi.json b/sdk/old_openapi.json deleted file mode 100644 index caf76231c..000000000 --- a/sdk/old_openapi.json +++ /dev/null @@ -1,50526 +0,0 @@ -{ - "openapi": "3.0.3", - "info": { - "title": "thirdweb Engine", - "description": "The open-source server for scalable web3 apps.", - "version": "0.0.2", - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } - }, - "components": { - "securitySchemes": { - "bearerAuth": { - "type": "http", - "scheme": "bearer", - "bearerFormat": "JWT", - "description": "To authenticate server-side requests" - } - }, - "schemas": {} - }, - "paths": { - "/json": { - "get": { "responses": { "200": { "description": "Default Response" } } } - }, - "/backend-wallet/create": { - "post": { - "operationId": "create", - "summary": "Create backend wallet", - "tags": ["Backend Wallet"], - "description": "Create a backend wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "label": { "type": "string" } } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "status": { "type": "string" } - }, - "required": ["walletAddress", "status"] - } - }, - "required": ["result"], - "example": { - "result": { "walletAddress": "0x....", "status": "success" } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{walletAddress}": { - "delete": { - "operationId": "removeBackendWallet", - "summary": "Remove backend wallet", - "tags": ["Backend Wallet"], - "description": "Remove an existing backend wallet. NOTE: This is an irreversible action for local wallets. Ensure any funds are transferred out before removing a local wallet.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "walletAddress", - "required": true, - "description": "A contract or wallet address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "status": { "type": "string" } }, - "required": ["status"] - } - }, - "required": ["result"], - "example": { "result": { "status": "success" } } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/import": { - "post": { - "operationId": "import", - "summary": "Import backend wallet", - "tags": ["Backend Wallet"], - "description": "Import an existing wallet as a backend wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "awsKmsKeyId": { - "description": "AWS KMS key ID", - "examples": ["12345678-1234-1234-1234-123456789012"], - "type": "string" - }, - "awsKmsArn": { - "description": "AWS KMS key ARN", - "examples": [ - "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" - ], - "type": "string" - } - }, - "required": ["awsKmsKeyId", "awsKmsArn"] - }, - { - "type": "object", - "properties": { - "gcpKmsKeyId": { - "description": "GCP KMS key ID", - "examples": ["12345678-1234-1234-1234-123456789012"], - "type": "string" - }, - "gcpKmsKeyVersionId": { - "description": "GCP KMS key version ID", - "examples": ["1"], - "type": "string" - } - }, - "required": ["gcpKmsKeyId", "gcpKmsKeyVersionId"] - }, - { - "anyOf": [ - { - "type": "object", - "properties": { - "privateKey": { - "description": "The private key of the wallet to import", - "type": "string" - } - }, - "required": ["privateKey"] - }, - { - "type": "object", - "properties": { - "mnemonic": { - "description": "The mnemonic phrase of the wallet to import", - "type": "string" - } - }, - "required": ["mnemonic"] - }, - { - "type": "object", - "properties": { - "encryptedJson": { - "description": "The encrypted JSON of the wallet to import", - "type": "string" - }, - "password": { - "description": "The password used to encrypt the encrypted JSON", - "type": "string" - } - }, - "required": ["encryptedJson", "password"] - } - ] - } - ] - }, - "examples": { - "example1": { - "value": { - "privateKey": "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" - } - }, - "example2": { - "value": { - "mnemonic": "crouch cabbage puppy sunset fever adjust giggle blanket maze loyal wreck dream" - } - }, - "example3": { - "value": { "encryptedJson": "", "password": "password123" } - }, - "example4": { - "value": { - "awsKmsKeyId": "12345678-1234-1234-1234-123456789012", - "awsKmsArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" - } - }, - "example5": { - "value": { - "gcpKmsKeyId": "12345678-1234-1234-1234-123456789012", - "gcpKmsKeyVersionId": "1" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "status": { "type": "string" } - }, - "required": ["walletAddress", "status"] - } - }, - "required": ["result"], - "example": { - "result": { "walletAddress": "0x....", "status": "success" } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/update": { - "post": { - "operationId": "update", - "summary": "Update backend wallet", - "tags": ["Backend Wallet"], - "description": "Update a backend wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "label": { "type": "string" } - }, - "required": ["walletAddress"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "status": { "type": "string" } - }, - "required": ["walletAddress", "status"] - } - }, - "required": ["result"], - "example": { - "result": { "walletAddress": "0x....", "status": "success" } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/{walletAddress}/get-balance": { - "get": { - "operationId": "getBalance", - "summary": "Get balance", - "tags": ["Backend Wallet"], - "description": "Get the native balance for a backend wallet.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "walletAddress", - "required": true, - "description": "Backend wallet address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "walletAddress", - "name", - "symbol", - "decimals", - "value", - "displayValue" - ] - } - }, - "required": ["result"], - "example": { - "result": { - "walletAddress": "0x...", - "name": "ERC20", - "symbol": "", - "decimals": "18", - "value": "0", - "displayValue": "0.0" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all backend wallets", - "tags": ["Backend Wallet"], - "description": "Get all backend wallets.", - "parameters": [ - { - "schema": { "default": "1", "type": "number" }, - "example": "1", - "in": "query", - "name": "page", - "required": true, - "description": "The page of wallets to get." - }, - { - "schema": { "default": "10", "type": "number" }, - "example": "10", - "in": "query", - "name": "limit", - "required": true, - "description": "The number of wallets to get per page." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "address": { - "description": "Wallet Address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "type": { - "description": "Wallet Type", - "type": "string" - }, - "label": { - "anyOf": [ - { - "description": "A label for your wallet", - "type": "string" - }, - { "type": "null" } - ] - }, - "awsKmsKeyId": { - "anyOf": [ - { - "description": "AWS KMS Key ID", - "type": "string" - }, - { "type": "null" } - ] - }, - "awsKmsArn": { - "anyOf": [ - { - "description": "AWS KMS Key ARN", - "type": "string" - }, - { "type": "null" } - ] - }, - "gcpKmsKeyId": { - "anyOf": [ - { - "description": "GCP KMS Key ID", - "type": "string" - }, - { "type": "null" } - ] - }, - "gcpKmsKeyRingId": { - "anyOf": [ - { - "description": "GCP KMS Key Ring ID", - "type": "string" - }, - { "type": "null" } - ] - }, - "gcpKmsLocationId": { - "anyOf": [ - { - "description": "GCP KMS Location ID", - "type": "string" - }, - { "type": "null" } - ] - }, - "gcpKmsKeyVersionId": { - "anyOf": [ - { - "description": "GCP KMS Key Version ID", - "type": "string" - }, - { "type": "null" } - ] - }, - "gcpKmsResourcePath": { - "anyOf": [ - { - "description": "GCP KMS Resource Path", - "type": "string" - }, - { "type": "null" } - ] - } - }, - "required": [ - "address", - "type", - "label", - "awsKmsKeyId", - "awsKmsArn", - "gcpKmsKeyId", - "gcpKmsKeyRingId", - "gcpKmsLocationId", - "gcpKmsKeyVersionId", - "gcpKmsResourcePath" - ] - } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "address": "0xe201a491a204e4a78e60033ae8ed39036b55bacb", - "type": "local", - "label": "my-wallet", - "awsKmsKeyId": null, - "awsKmsArn": null, - "gcpKmsKeyId": null, - "gcpKmsKeyRingId": null, - "gcpKmsLocationId": null, - "gcpKmsKeyVersionId": null, - "gcpKmsResourcePath": null - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/transfer": { - "post": { - "operationId": "transfer", - "summary": "Transfer tokens", - "tags": ["Backend Wallet"], - "description": "Transfer native currency or ERC20 tokens to another wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "to": { - "description": "The recipient wallet address.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "currencyAddress": { - "description": "The token address to transfer. Omit to transfer the chain's native currency (e.g. ETH on Ethereum).", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x0000000000000000000000000000000000000000" - }, - "amount": { - "description": "The amount in ether to transfer. Example: \"0.1\" to send 0.1 ETH.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["to", "amount"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/withdraw": { - "post": { - "operationId": "withdraw", - "summary": "Withdraw funds", - "tags": ["Backend Wallet"], - "description": "Withdraw all funds from this wallet to another wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "toAddress": { - "description": "Address to withdraw all funds to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - }, - "required": ["toAddress"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "transactionHash": { "type": "string" } }, - "required": ["transactionHash"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/send-transaction": { - "post": { - "operationId": "sendTransaction", - "summary": "Send a transaction", - "tags": ["Backend Wallet"], - "description": "Send a transaction with transaction parameters", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "toAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "data": { "type": "string", "example": "0x..." }, - "value": { "type": "string", "example": "10000000" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - } - } - } - }, - "required": ["data", "value"] - }, - "example": { - "toAddress": "0x7a0ce8524bea337f0bee853b68fabde145dac0a0", - "data": "0x449a52f800000000000000000000000043cae0d7fe86c713530e679ce02574743b2ee9fc0000000000000000000000000000000000000000000000000de0b6b3a7640000", - "value": "0x00", - "txOverrides": { "gas": "50000" } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/send-transaction-batch": { - "post": { - "operationId": "sendTransactionBatch", - "summary": "Send a batch of raw transactions", - "tags": ["Backend Wallet"], - "description": "Send a batch of raw transactions with transaction parameters", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "toAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "data": { "type": "string", "example": "0x..." }, - "value": { "type": "string", "example": "10000000" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["data", "value"] - } - } - } - } - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueIds": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["queueIds"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/sign-transaction": { - "post": { - "operationId": "signTransaction", - "summary": "Sign a transaction", - "tags": ["Backend Wallet"], - "description": "Sign a transaction", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "transaction": { - "type": "object", - "properties": { - "to": { "type": "string" }, - "from": { "type": "string" }, - "nonce": { "type": "string" }, - "gasLimit": { "type": "string" }, - "gasPrice": { "type": "string" }, - "data": { "type": "string" }, - "value": { "type": "string" }, - "chainId": { "type": "number" }, - "type": { "type": "number" }, - "accessList": {}, - "maxFeePerGas": { "type": "string" }, - "maxPriorityFeePerGas": { "type": "string" }, - "customData": { - "type": "object", - "additionalProperties": {} - }, - "ccipReadEnabled": { "type": "boolean" } - } - } - }, - "required": ["transaction"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/sign-message": { - "post": { - "operationId": "signMessage", - "summary": "Sign a message", - "tags": ["Backend Wallet"], - "description": "Send a message", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "isBytes": { "type": "boolean" } - }, - "required": ["message"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/sign-typed-data": { - "post": { - "operationId": "signTypedData", - "summary": "Sign an EIP-712 message", - "tags": ["Backend Wallet"], - "description": "Send an EIP-712 message (\"typed data\")", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "domain": { - "additionalProperties": true, - "type": "object", - "properties": {} - }, - "types": { - "additionalProperties": true, - "type": "object", - "properties": {} - }, - "value": { - "additionalProperties": true, - "type": "object", - "properties": {} - } - }, - "required": ["domain", "types", "value"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/{walletAddress}/get-all-transactions": { - "get": { - "operationId": "getTransactionsForBackendWallet", - "summary": "Get recent transactions", - "tags": ["Backend Wallet"], - "description": "Get recent transactions for this backend wallet.", - "parameters": [ - { - "schema": { "default": 1, "minimum": 1, "type": "integer" }, - "example": 1, - "in": "query", - "name": "page", - "required": true, - "description": "Specify the page number." - }, - { - "schema": { "default": 100, "type": "integer" }, - "example": 100, - "in": "query", - "name": "limit", - "required": true, - "description": "Specify the number of results to return per page." - }, - { - "schema": { - "default": "queued", - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["cancelled"] }, - { "type": "string", "enum": ["errored"] } - ] - }, - "in": "query", - "name": "status", - "required": true, - "description": "The status to query: 'queued', 'mined', 'errored', or 'cancelled'. Default: 'queued'" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "walletAddress", - "required": true, - "description": "Backend wallet address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "transactions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "queueId": { - "anyOf": [ - { - "description": "An identifier for an enqueued blockchain write call", - "type": "string" - }, - { "type": "null" } - ] - }, - "status": { - "description": "The current state of the transaction.", - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["sent"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["errored"] }, - { "type": "string", "enum": ["cancelled"] } - ], - "example": "queued" - }, - "chainId": { - "anyOf": [ - { - "description": "The chain ID for the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "fromAddress": { - "anyOf": [ - { - "description": "The backend wallet submitting the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "toAddress": { - "anyOf": [ - { - "description": "The contract address to be called", - "type": "string" - }, - { "type": "null" } - ] - }, - "data": { - "anyOf": [ - { - "description": "Encoded calldata", - "type": "string" - }, - { "type": "null" } - ] - }, - "extension": { - "anyOf": [ - { - "description": "The extension detected by thirdweb", - "type": "string" - }, - { "type": "null" } - ] - }, - "value": { - "anyOf": [ - { - "description": "The amount of native currency to send", - "type": "string" - }, - { "type": "null" } - ] - }, - "nonce": { - "anyOf": [ - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "number" - }, - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasLimit": { - "anyOf": [ - { - "description": "The max gas unit limit", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasPrice": { - "anyOf": [ - { - "description": "The gas price used", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "transactionType": { - "anyOf": [ - { - "description": "The type of transaction", - "type": "number" - }, - { "type": "null" } - ] - }, - "transactionHash": { - "anyOf": [ - { - "description": "The transaction hash (may not be mined)", - "type": "string" - }, - { "type": "null" } - ] - }, - "queuedAt": { - "anyOf": [ - { - "description": "When the transaction is enqueued", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAt": { - "anyOf": [ - { - "description": "When the transaction is submitted to mempool", - "type": "string" - }, - { "type": "null" } - ] - }, - "minedAt": { - "anyOf": [ - { - "description": "When the transaction is mined onchain", - "type": "string" - }, - { "type": "null" } - ] - }, - "cancelledAt": { - "anyOf": [ - { - "description": "When the transactino is cancelled", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractAddress": { - "anyOf": [ - { - "description": "The address for a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractType": { - "anyOf": [ - { - "description": "The type of a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "errorMessage": { - "anyOf": [ - { - "description": "The error that occurred", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAtBlockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is submitted to mempool", - "type": "number" - }, - { "type": "null" } - ] - }, - "blockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is mined", - "type": "number" - }, - { "type": "null" } - ] - }, - "retryCount": { - "description": "The number of retry attempts", - "type": "number" - }, - "retryGasValues": { - "anyOf": [ - { - "description": "Whether to replace gas values on the next retry", - "type": "boolean" - }, - { "type": "null" } - ] - }, - "retryMaxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "retryMaxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "signerAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "accountAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "target": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "sender": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "initCode": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "verificationGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "preVerificationGas": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "paymasterAndData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "userOpHash": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionName": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionArgs": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "onChainTxStatus": { - "anyOf": [ - { "type": "number" }, - { "type": "null" } - ] - }, - "onchainStatus": { - "anyOf": [ - { "type": "string", "enum": ["success"] }, - { "type": "string", "enum": ["reverted"] }, - { "type": "null" } - ] - }, - "effectiveGasPrice": { - "anyOf": [ - { - "description": "Effective Gas Price", - "type": "string" - }, - { "type": "null" } - ] - }, - "cumulativeGasUsed": { - "anyOf": [ - { - "description": "Cumulative Gas Used", - "type": "string" - }, - { "type": "null" } - ] - } - }, - "required": [ - "queueId", - "status", - "chainId", - "fromAddress", - "toAddress", - "data", - "extension", - "value", - "nonce", - "gasLimit", - "gasPrice", - "maxFeePerGas", - "maxPriorityFeePerGas", - "transactionType", - "transactionHash", - "queuedAt", - "sentAt", - "minedAt", - "cancelledAt", - "deployedContractAddress", - "deployedContractType", - "errorMessage", - "sentAtBlockNumber", - "blockNumber", - "retryCount", - "retryGasValues", - "retryMaxFeePerGas", - "retryMaxPriorityFeePerGas", - "signerAddress", - "accountAddress", - "target", - "sender", - "initCode", - "callData", - "callGasLimit", - "verificationGasLimit", - "preVerificationGas", - "paymasterAndData", - "userOpHash", - "functionName", - "functionArgs", - "onChainTxStatus", - "onchainStatus", - "effectiveGasPrice", - "cumulativeGasUsed" - ] - } - } - }, - "required": ["transactions"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/{walletAddress}/get-transactions-by-nonce": { - "get": { - "operationId": "getTransactionsForBackendWalletByNonce", - "summary": "Get recent transactions by nonce", - "tags": ["Backend Wallet"], - "description": "Get recent transactions for this backend wallet, sorted by descending nonce.", - "parameters": [ - { - "schema": { "minimum": 0, "type": "integer" }, - "example": 100, - "in": "query", - "name": "fromNonce", - "required": true, - "description": "The earliest nonce, inclusive." - }, - { - "schema": { "minimum": 0, "type": "integer" }, - "example": 100, - "in": "query", - "name": "toNonce", - "required": false, - "description": "The latest nonce, inclusive. If omitted, queries up to the latest sent nonce." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "walletAddress", - "required": true, - "description": "Backend wallet address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "nonce": { "type": "number" }, - "transaction": { - "anyOf": [ - { - "type": "object", - "properties": { - "queueId": { - "anyOf": [ - { - "description": "An identifier for an enqueued blockchain write call", - "type": "string" - }, - { "type": "null" } - ] - }, - "status": { - "description": "The current state of the transaction.", - "examples": [ - "queued", - "sent", - "mined", - "errored", - "cancelled" - ], - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["sent"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["errored"] }, - { - "type": "string", - "enum": ["cancelled"] - } - ] - }, - "chainId": { - "anyOf": [ - { - "description": "The chain ID for the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "fromAddress": { - "anyOf": [ - { - "description": "The backend wallet submitting the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "toAddress": { - "anyOf": [ - { - "description": "The contract address to be called", - "type": "string" - }, - { "type": "null" } - ] - }, - "data": { - "anyOf": [ - { - "description": "Encoded calldata", - "type": "string" - }, - { "type": "null" } - ] - }, - "extension": { - "anyOf": [ - { - "description": "The extension detected by thirdweb", - "type": "string" - }, - { "type": "null" } - ] - }, - "value": { - "anyOf": [ - { - "description": "The amount of native currency to send", - "type": "string" - }, - { "type": "null" } - ] - }, - "nonce": { - "anyOf": [ - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "number" - }, - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasLimit": { - "anyOf": [ - { - "description": "The max gas unit limit", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasPrice": { - "anyOf": [ - { - "description": "The gas price used", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "transactionType": { - "anyOf": [ - { - "description": "The type of transaction", - "type": "number" - }, - { "type": "null" } - ] - }, - "transactionHash": { - "anyOf": [ - { - "description": "The transaction hash (may not be mined)", - "type": "string" - }, - { "type": "null" } - ] - }, - "queuedAt": { - "anyOf": [ - { - "description": "When the transaction is enqueued", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAt": { - "anyOf": [ - { - "description": "When the transaction is submitted to mempool", - "type": "string" - }, - { "type": "null" } - ] - }, - "minedAt": { - "anyOf": [ - { - "description": "When the transaction is mined onchain", - "type": "string" - }, - { "type": "null" } - ] - }, - "cancelledAt": { - "anyOf": [ - { - "description": "When the transactino is cancelled", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractAddress": { - "anyOf": [ - { - "description": "The address for a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractType": { - "anyOf": [ - { - "description": "The type of a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "errorMessage": { - "anyOf": [ - { - "description": "The error that occurred", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAtBlockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is submitted to mempool", - "type": "number" - }, - { "type": "null" } - ] - }, - "blockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is mined", - "type": "number" - }, - { "type": "null" } - ] - }, - "retryCount": { - "description": "The number of retry attempts", - "type": "number" - }, - "retryGasValues": { - "anyOf": [ - { - "description": "Whether to replace gas values on the next retry", - "type": "boolean" - }, - { "type": "null" } - ] - }, - "retryMaxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "retryMaxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "signerAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "accountAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "target": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "sender": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "initCode": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "verificationGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "preVerificationGas": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "paymasterAndData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "userOpHash": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionName": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionArgs": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "onChainTxStatus": { - "anyOf": [ - { "type": "number" }, - { "type": "null" } - ] - }, - "onchainStatus": { - "anyOf": [ - { "type": "string", "enum": ["success"] }, - { - "type": "string", - "enum": ["reverted"] - }, - { "type": "null" } - ] - }, - "effectiveGasPrice": { - "anyOf": [ - { - "description": "Effective Gas Price", - "type": "string" - }, - { "type": "null" } - ] - }, - "cumulativeGasUsed": { - "anyOf": [ - { - "description": "Cumulative Gas Used", - "type": "string" - }, - { "type": "null" } - ] - } - }, - "required": [ - "queueId", - "status", - "chainId", - "fromAddress", - "toAddress", - "data", - "extension", - "value", - "nonce", - "gasLimit", - "gasPrice", - "maxFeePerGas", - "maxPriorityFeePerGas", - "transactionType", - "transactionHash", - "queuedAt", - "sentAt", - "minedAt", - "cancelledAt", - "deployedContractAddress", - "deployedContractType", - "errorMessage", - "sentAtBlockNumber", - "blockNumber", - "retryCount", - "retryGasValues", - "retryMaxFeePerGas", - "retryMaxPriorityFeePerGas", - "signerAddress", - "accountAddress", - "target", - "sender", - "initCode", - "callData", - "callGasLimit", - "verificationGasLimit", - "preVerificationGas", - "paymasterAndData", - "userOpHash", - "functionName", - "functionArgs", - "onChainTxStatus", - "onchainStatus", - "effectiveGasPrice", - "cumulativeGasUsed" - ] - }, - { "type": "string" } - ] - } - }, - "required": ["nonce", "transaction"] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/reset-nonces": { - "post": { - "operationId": "resetNonces", - "summary": "Reset nonces", - "tags": ["Backend Wallet"], - "description": "Reset nonces for all backend wallets. This is for debugging purposes and does not impact held tokens.", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "status": { "type": "string" } }, - "required": ["status"] - } - }, - "required": ["result"], - "example": { "result": { "status": "success" } } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/{walletAddress}/get-nonce": { - "get": { - "operationId": "getNonce", - "summary": "Get nonce", - "tags": ["Backend Wallet"], - "description": "Get the last used nonce for this backend wallet. This value managed by Engine may differ from the onchain value. Use `/backend-wallet/reset-nonces` if this value looks incorrect while idle.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "walletAddress", - "required": true, - "description": "Backend wallet address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "nonce": { "type": "number" } }, - "required": ["nonce"] - } - }, - "required": ["result"], - "example": { "result": { "nonce": 100 } } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/backend-wallet/{chain}/simulate-transaction": { - "post": { - "operationId": "simulateTransaction", - "summary": "Simulate a transaction", - "tags": ["Backend Wallet"], - "description": "Simulate a transaction with transaction parameters", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "toAddress": { - "description": "The contract address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "value": { - "description": "The amount of native currency in wei", - "type": "string", - "example": "0" - }, - "functionName": { - "description": "The function to call on the contract", - "type": "string" - }, - "args": { - "description": "The arguments to call for this function", - "type": "array", - "items": { - "anyOf": [ - { "description": "String argument", "type": "string" }, - { "description": "Numeric argument", "type": "number" }, - { - "description": "Boolean argument", - "type": "boolean" - }, - { - "description": "Array argument", - "type": "array", - "items": {} - }, - { - "description": "Object argument", - "type": "object", - "properties": {} - } - ] - } - }, - "data": { "description": "Raw calldata", "type": "string" } - }, - "required": ["toAddress"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "success": { - "description": "Simulation Success", - "type": "boolean" - } - }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/wallets": { - "get": { - "operationId": "getWalletsConfiguration", - "summary": "Get wallets configuration", - "tags": ["Configuration"], - "description": "Get wallets configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["local"] } - }, - "required": ["type"] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["aws-kms"] }, - "awsAccessKeyId": { "type": "string" }, - "awsRegion": { "type": "string" } - }, - "required": ["type", "awsAccessKeyId", "awsRegion"] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["gcp-kms"] }, - "gcpApplicationProjectId": { "type": "string" }, - "gcpKmsLocationId": { "type": "string" }, - "gcpKmsKeyRingId": { "type": "string" }, - "gcpApplicationCredentialEmail": { - "type": "string" - } - }, - "required": [ - "type", - "gcpApplicationProjectId", - "gcpKmsLocationId", - "gcpKmsKeyRingId", - "gcpApplicationCredentialEmail" - ] - } - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateWalletsConfiguration", - "summary": "Update wallets configuration", - "tags": ["Configuration"], - "description": "Update wallets configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["local"] } - }, - "required": ["type"] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["aws-kms"] }, - "awsAccessKeyId": { "type": "string" }, - "awsSecretAccessKey": { "type": "string" }, - "awsRegion": { "type": "string" } - }, - "required": [ - "type", - "awsAccessKeyId", - "awsSecretAccessKey", - "awsRegion" - ] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["gcp-kms"] }, - "gcpApplicationProjectId": { "type": "string" }, - "gcpKmsLocationId": { "type": "string" }, - "gcpKmsKeyRingId": { "type": "string" }, - "gcpApplicationCredentialEmail": { "type": "string" }, - "gcpApplicationCredentialPrivateKey": { "type": "string" } - }, - "required": [ - "type", - "gcpApplicationProjectId", - "gcpKmsLocationId", - "gcpKmsKeyRingId", - "gcpApplicationCredentialEmail", - "gcpApplicationCredentialPrivateKey" - ] - } - ] - }, - "examples": { - "example1": { "value": { "type": "local" } }, - "example2": { - "value": { - "type": "aws-kms", - "awsAccessKeyId": "\u003Cyour-aws-access-key-id\u003E", - "awsSecretAccessKey": "\u003Cyour-aws-secret-access-key\u003E", - "awsRegion": "\u003Cyour-aws-region\u003E" - } - }, - "example3": { - "value": { - "type": "gcp-kms", - "gcpApplicationProjectId": "\u003Cyour-gcp-application-project-id\u003E", - "gcpKmsLocationId": "\u003Cyour-gcp-kms-location-id\u003E", - "gcpKmsKeyRingId": "\u003Cyour-gcp-key-ring-id\u003E", - "gcpApplicationCredentialEmail": "\u003Cyour-gcp-application-credential-email\u003E", - "gcpApplicationCredentialPrivateKey": "\u003Cyour-gcp-application-credential-private-key\u003E" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["local"] } - }, - "required": ["type"] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["aws-kms"] }, - "awsAccessKeyId": { "type": "string" }, - "awsRegion": { "type": "string" } - }, - "required": ["type", "awsAccessKeyId", "awsRegion"] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["gcp-kms"] }, - "gcpApplicationProjectId": { "type": "string" }, - "gcpKmsLocationId": { "type": "string" }, - "gcpKmsKeyRingId": { "type": "string" }, - "gcpApplicationCredentialEmail": { - "type": "string" - } - }, - "required": [ - "type", - "gcpApplicationProjectId", - "gcpKmsLocationId", - "gcpKmsKeyRingId", - "gcpApplicationCredentialEmail" - ] - } - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/chains": { - "get": { - "operationId": "getChainsConfiguration", - "summary": "Get chain overrides configuration", - "tags": ["Configuration"], - "description": "Get chain overrides configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "description": "Chain name", - "type": "string" - }, - "chain": { - "description": "Chain name", - "type": "string" - }, - "rpc": { - "type": "array", - "items": { - "description": "RPC URL", - "type": "string" - } - }, - "nativeCurrency": { - "type": "object", - "properties": { - "name": { - "description": "Native currency name", - "type": "string" - }, - "symbol": { - "description": "Native currency symbol", - "type": "string" - }, - "decimals": { - "description": "Native currency decimals", - "type": "number" - } - }, - "required": ["name", "symbol", "decimals"] - }, - "shortName": { - "description": "Chain short name", - "type": "string" - }, - "chainId": { - "description": "Chain ID", - "type": "number" - }, - "testnet": { - "description": "Is testnet", - "type": "boolean" - }, - "slug": { - "description": "Chain slug", - "type": "string" - } - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateChainsConfiguration", - "summary": "Update chain overrides configuration", - "tags": ["Configuration"], - "description": "Update chain overrides configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "chainOverrides": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "description": "Chain name", - "type": "string" - }, - "chain": { - "description": "Chain name", - "type": "string" - }, - "rpc": { - "type": "array", - "items": { - "description": "RPC URL", - "type": "string" - } - }, - "nativeCurrency": { - "type": "object", - "properties": { - "name": { - "description": "Native currency name", - "type": "string" - }, - "symbol": { - "description": "Native currency symbol", - "type": "string" - }, - "decimals": { - "description": "Native currency decimals", - "type": "number" - } - }, - "required": ["name", "symbol", "decimals"] - }, - "shortName": { - "description": "Chain short name", - "type": "string" - }, - "chainId": { - "description": "Chain ID", - "type": "number" - }, - "testnet": { - "description": "Is testnet", - "type": "boolean" - }, - "slug": { - "description": "Chain slug", - "type": "string" - } - } - } - } - }, - "required": ["chainOverrides"] - }, - "example": { - "chainOverrides": [ - { - "name": "Localhost", - "chain": "ETH", - "rpc": ["http://localhost:8545/"], - "nativeCurrency": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "chainId": 1337, - "slug": "localhost" - } - ] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "description": "Chain name", - "type": "string" - }, - "chain": { - "description": "Chain name", - "type": "string" - }, - "rpc": { - "type": "array", - "items": { - "description": "RPC URL", - "type": "string" - } - }, - "nativeCurrency": { - "type": "object", - "properties": { - "name": { - "description": "Native currency name", - "type": "string" - }, - "symbol": { - "description": "Native currency symbol", - "type": "string" - }, - "decimals": { - "description": "Native currency decimals", - "type": "number" - } - }, - "required": ["name", "symbol", "decimals"] - }, - "shortName": { - "description": "Chain short name", - "type": "string" - }, - "chainId": { - "description": "Chain ID", - "type": "number" - }, - "testnet": { - "description": "Is testnet", - "type": "boolean" - }, - "slug": { - "description": "Chain slug", - "type": "string" - } - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/transactions": { - "get": { - "operationId": "getTransactionConfiguration", - "summary": "Get transaction processing configuration", - "tags": ["Configuration"], - "description": "Get transactions processing configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "minTxsToProcess": { "type": "number" }, - "maxTxsToProcess": { "type": "number" }, - "minedTxListenerCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "maxTxsToUpdate": { "type": "number" }, - "retryTxListenerCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "minEllapsedBlocksBeforeRetry": { "type": "number" }, - "maxFeePerGasForRetries": { "type": "string" }, - "maxPriorityFeePerGasForRetries": { "type": "string" }, - "maxRetriesPerTx": { "type": "number" }, - "clearCacheCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - } - }, - "required": [ - "minTxsToProcess", - "maxTxsToProcess", - "minedTxListenerCronSchedule", - "maxTxsToUpdate", - "retryTxListenerCronSchedule", - "minEllapsedBlocksBeforeRetry", - "maxFeePerGasForRetries", - "maxPriorityFeePerGasForRetries", - "maxRetriesPerTx", - "clearCacheCronSchedule" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateTransactionConfiguration", - "summary": "Update transaction processing configuration", - "tags": ["Configuration"], - "description": "Update transaction processing configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "minTxsToProcess": { "type": "number" }, - "maxTxsToProcess": { "type": "number" }, - "minedTxListenerCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "maxTxsToUpdate": { "type": "number" }, - "retryTxListenerCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "minEllapsedBlocksBeforeRetry": { "type": "number" }, - "maxFeePerGasForRetries": { "type": "string" }, - "maxPriorityFeePerGasForRetries": { "type": "string" }, - "maxRetriesPerTx": { "type": "number" } - } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "minTxsToProcess": { "type": "number" }, - "maxTxsToProcess": { "type": "number" }, - "minedTxListenerCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "maxTxsToUpdate": { "type": "number" }, - "retryTxListenerCronSchedule": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "minEllapsedBlocksBeforeRetry": { "type": "number" }, - "maxFeePerGasForRetries": { "type": "string" }, - "maxPriorityFeePerGasForRetries": { "type": "string" }, - "maxRetriesPerTx": { "type": "number" } - }, - "required": [ - "minTxsToProcess", - "maxTxsToProcess", - "minedTxListenerCronSchedule", - "maxTxsToUpdate", - "retryTxListenerCronSchedule", - "minEllapsedBlocksBeforeRetry", - "maxFeePerGasForRetries", - "maxPriorityFeePerGasForRetries", - "maxRetriesPerTx" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/auth": { - "get": { - "operationId": "getAuthConfiguration", - "summary": "Get auth configuration", - "tags": ["Configuration"], - "description": "Get auth configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "domain": { "type": "string" } }, - "required": ["domain"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateAuthConfiguration", - "summary": "Update auth configuration", - "tags": ["Configuration"], - "description": "Update auth configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "domain": { "type": "string" } }, - "required": ["domain"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "domain": { "type": "string" } }, - "required": ["domain"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/backend-wallet-balance": { - "get": { - "operationId": "getBackendWalletBalanceConfiguration", - "summary": "Get wallet-balance configuration", - "tags": ["Configuration"], - "description": "Get wallet-balance configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "minWalletBalance": { - "description": "Minimum wallet balance in wei", - "type": "string" - } - }, - "required": ["minWalletBalance"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateBackendWalletBalanceConfiguration", - "summary": "Update backend wallet balance configuration", - "tags": ["Configuration"], - "description": "Update backend wallet balance configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "minWalletBalance": { - "description": "Minimum wallet balance in wei", - "type": "string" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "minWalletBalance": { - "description": "Minimum wallet balance in wei", - "type": "string" - } - }, - "required": ["minWalletBalance"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/cors": { - "get": { - "operationId": "getCorsConfiguration", - "summary": "Get CORS configuration", - "tags": ["Configuration"], - "description": "Get CORS configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "addUrlToCorsConfiguration", - "summary": "Add a CORS URL", - "tags": ["Configuration"], - "description": "Add a URL to allow client-side calls to Engine", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "urlsToAdd": { - "type": "array", - "items": { - "description": "Comma separated list of origins that will call Engine", - "minLength": 1, - "type": "string" - } - } - }, - "required": ["urlsToAdd"] - }, - "example": { - "urlsToAdd": [ - "https://example.com/", - "https://subdomain.example.com/" - ] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "delete": { - "operationId": "removeUrlToCorsConfiguration", - "summary": "Remove CORS URLs", - "tags": ["Configuration"], - "description": "Remove URLs from CORS configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "urlsToRemove": { - "type": "array", - "items": { - "description": "Comma separated list of origins to remove", - "type": "string" - } - } - }, - "required": ["urlsToRemove"] - }, - "example": { - "urlsToRemove": [ - "https://example.com/", - "https://subdomain.example.com/" - ] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "put": { - "operationId": "setUrlsToCorsConfiguration", - "summary": "Set CORS URLs", - "tags": ["Configuration"], - "description": "Replaces the CORS URLs to allow client-side calls to Engine", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "urls": { - "type": "array", - "items": { - "description": "Comma separated list of origins that will call Engine", - "minLength": 1, - "type": "string" - } - } - }, - "required": ["urls"] - }, - "example": { - "urls": ["https://example.com/", "https://subdomain.example.com/"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/cache": { - "get": { - "operationId": "getCacheConfiguration", - "summary": "Get cache configuration", - "tags": ["Configuration"], - "description": "Get cache configuration", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "clearCacheCronSchedule": { "type": "string" } - }, - "required": ["clearCacheCronSchedule"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateCacheConfiguration", - "summary": "Update cache configuration", - "tags": ["Configuration"], - "description": "Update cache configuration", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "clearCacheCronSchedule": { - "minLength": 11, - "description": "Cron expression for clearing cache. It should be in the format of 'ss mm hh * * *' where ss is seconds, mm is minutes and hh is hours. Seconds should not be '*' or less than 10", - "default": "*/30 * * * * *", - "type": "string" - } - }, - "required": ["clearCacheCronSchedule"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "clearCacheCronSchedule": { "type": "string" } - }, - "required": ["clearCacheCronSchedule"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/contract-subscriptions": { - "get": { - "operationId": "getContractSubscriptionsConfiguration", - "summary": "Get Contract Subscriptions configuration", - "tags": ["Configuration"], - "description": "Get the configuration for Contract Subscriptions", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "maxBlocksToIndex": { "type": "number" }, - "contractSubscriptionsRequeryDelaySeconds": { - "type": "string" - } - }, - "required": [ - "maxBlocksToIndex", - "contractSubscriptionsRequeryDelaySeconds" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "post": { - "operationId": "updateContractSubscriptionsConfiguration", - "summary": "Update Contract Subscriptions configuration", - "tags": ["Configuration"], - "description": "Update the configuration for Contract Subscriptions", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "maxBlocksToIndex": { - "minimum": 1, - "maximum": 25, - "type": "number" - }, - "contractSubscriptionsRequeryDelaySeconds": { - "type": "string" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "maxBlocksToIndex": { "type": "number" }, - "contractSubscriptionsRequeryDelaySeconds": { - "type": "string" - } - }, - "required": [ - "maxBlocksToIndex", - "contractSubscriptionsRequeryDelaySeconds" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/configuration/ip-allowlist": { - "get": { - "operationId": "getIpAllowlist", - "summary": "Get Allowed IP Addresses", - "tags": ["Configuration"], - "description": "Get the list of allowed IP addresses", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - }, - "put": { - "operationId": "setIpAllowlist", - "summary": "Set IP Allowlist", - "tags": ["Configuration"], - "description": "Replaces the IP Allowlist array to allow calls to Engine", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "ips": { - "description": "Array of IP addresses to allowlist", - "type": "array", - "items": { - "minLength": 7, - "description": "IP address as a string", - "type": "string" - } - } - }, - "required": ["ips"] - }, - "example": { "ips": ["8.8.8.8", "172.217.255.255"] } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/webhooks/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all webhooks configured", - "tags": ["Webhooks"], - "description": "Get all webhooks configuration data set up on Engine", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "url": { "type": "string" }, - "name": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "secret": { "type": "string" }, - "eventType": { "type": "string" }, - "active": { "type": "boolean" }, - "createdAt": { "type": "string" }, - "id": { "type": "number" } - }, - "required": [ - "url", - "name", - "eventType", - "active", - "createdAt", - "id" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/webhooks/create": { - "post": { - "operationId": "create", - "summary": "Create a webhook", - "tags": ["Webhooks"], - "description": "Create a webhook to call when certain blockchain events occur.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "url": { - "description": "Webhook URL", - "type": "string", - "example": "https://example.com/webhook" - }, - "name": { "minLength": 3, "type": "string" }, - "eventType": { - "anyOf": [ - { "type": "string", "enum": ["queued_transaction"] }, - { "type": "string", "enum": ["sent_transaction"] }, - { "type": "string", "enum": ["mined_transaction"] }, - { "type": "string", "enum": ["errored_transaction"] }, - { "type": "string", "enum": ["cancelled_transaction"] }, - { "type": "string", "enum": ["all_transactions"] }, - { "type": "string", "enum": ["backend_wallet_balance"] }, - { "type": "string", "enum": ["auth"] }, - { "type": "string", "enum": ["contract_subscription"] } - ] - } - }, - "required": ["url", "eventType"] - }, - "examples": { - "example1": { - "value": { - "url": "https://example.com/allTxUpdate", - "name": "All Transaction Events", - "eventType": "all_transactions" - } - }, - "example2": { - "value": { - "url": "https://example.com/queuedTx", - "name": "QueuedTx", - "eventType": "queued_transaction" - } - }, - "example3": { - "value": { - "url": "https://example.com/sentTx", - "name": "Sent Transaction Event", - "eventType": "sent_transaction" - } - }, - "example4": { - "value": { - "url": "https://example.com/minedTx", - "name": "Mined Transaction Event", - "eventType": "mined_transaction" - } - }, - "example5": { - "value": { - "url": "https://example.com/erroredTx", - "name": "Errored Transaction Event", - "eventType": "errored_transaction" - } - }, - "example6": { - "value": { - "url": "https://example.com/cancelledTx", - "name": "Cancelled Transaction Event", - "eventType": "cancelled_transaction" - } - }, - "example7": { - "value": { - "url": "https://example.com/walletBalance", - "name": "Backend Wallet Balance Event", - "eventType": "backend_wallet_balance" - } - }, - "example8": { - "value": { - "url": "https://example.com/auth", - "name": "Auth Check", - "eventType": "auth" - } - } - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "url": { "type": "string" }, - "name": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "secret": { "type": "string" }, - "eventType": { "type": "string" }, - "active": { "type": "boolean" }, - "createdAt": { "type": "string" }, - "id": { "type": "number" } - }, - "required": [ - "url", - "name", - "eventType", - "active", - "createdAt", - "id" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/webhooks/revoke": { - "post": { - "operationId": "revoke", - "summary": "Revoke webhook", - "tags": ["Webhooks"], - "description": "Revoke a Webhook", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "id": { "type": "number" } }, - "required": ["id"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/webhooks/event-types": { - "get": { - "operationId": "getEventTypes", - "summary": "Get webhooks event types", - "tags": ["Webhooks"], - "description": "Get the all the webhooks event types", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "anyOf": [ - { "type": "string", "enum": ["queued_transaction"] }, - { "type": "string", "enum": ["sent_transaction"] }, - { "type": "string", "enum": ["mined_transaction"] }, - { "type": "string", "enum": ["errored_transaction"] }, - { - "type": "string", - "enum": ["cancelled_transaction"] - }, - { "type": "string", "enum": ["all_transactions"] }, - { - "type": "string", - "enum": ["backend_wallet_balance"] - }, - { "type": "string", "enum": ["auth"] }, - { - "type": "string", - "enum": ["contract_subscription"] - } - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/permissions/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all permissions", - "tags": ["Permissions"], - "description": "Get all users with their corresponding permissions", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "permissions": { "type": "string" }, - "label": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - } - }, - "required": ["walletAddress", "permissions", "label"] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/permissions/grant": { - "post": { - "operationId": "grant", - "summary": "Grant permissions to user", - "tags": ["Permissions"], - "description": "Grant permissions to a user", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "permissions": { - "anyOf": [ - { "type": "string", "enum": ["ADMIN"] }, - { "type": "string", "enum": ["OWNER"] } - ] - }, - "label": { "type": "string" } - }, - "required": ["walletAddress", "permissions"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/permissions/revoke": { - "post": { - "operationId": "revoke", - "summary": "Revoke permissions from user", - "tags": ["Permissions"], - "description": "Revoke a user's permissions", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - }, - "required": ["walletAddress"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/access-tokens/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all access tokens", - "tags": ["Access Tokens"], - "description": "Get all access tokens", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "tokenMask": { "type": "string" }, - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "createdAt": { "type": "string" }, - "expiresAt": { "type": "string" }, - "label": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - } - }, - "required": [ - "id", - "tokenMask", - "walletAddress", - "createdAt", - "expiresAt", - "label" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/access-tokens/create": { - "post": { - "operationId": "create", - "summary": "Create a new access token", - "tags": ["Access Tokens"], - "description": "Create a new access token", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "label": { "type": "string" } } - } - } - } - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "tokenMask": { "type": "string" }, - "walletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "createdAt": { "type": "string" }, - "expiresAt": { "type": "string" }, - "label": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "accessToken": { "type": "string" } - }, - "required": [ - "id", - "tokenMask", - "walletAddress", - "createdAt", - "expiresAt", - "label", - "accessToken" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/access-tokens/revoke": { - "post": { - "operationId": "revoke", - "summary": "Revoke an access token", - "tags": ["Access Tokens"], - "description": "Revoke an access token", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "id": { "type": "string" } }, - "required": ["id"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/access-tokens/update": { - "post": { - "operationId": "update", - "summary": "Update an access token", - "tags": ["Access Tokens"], - "description": "Update an access token", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "label": { "type": "string" } - }, - "required": ["id"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/keypair/get-all": { - "get": { - "operationId": "list", - "summary": "List public keys", - "tags": ["Keypair"], - "description": "List the public keys configured with Engine", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "hash": { - "description": "A unique identifier for the keypair", - "type": "string" - }, - "publicKey": { - "description": "The public key", - "type": "string" - }, - "algorithm": { - "description": "The keypair algorithm.", - "type": "string" - }, - "label": { - "description": "A description for the keypair.", - "type": "string" - }, - "createdAt": { - "type": "string", - "format": "date", - "description": "When the keypair was added" - }, - "updatedAt": { - "type": "string", - "format": "date", - "description": "When the keypair was updated" - } - }, - "required": [ - "hash", - "publicKey", - "algorithm", - "createdAt", - "updatedAt" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/keypair/add": { - "post": { - "operationId": "add", - "summary": "Add public key", - "tags": ["Keypair"], - "description": "Add the public key for a keypair", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "publicKey": { - "description": "The public key of your keypair beginning with '-----BEGIN PUBLIC KEY-----'.", - "type": "string" - }, - "algorithm": { - "anyOf": [ - { "type": "string", "enum": ["RS256"] }, - { "type": "string", "enum": ["RS384"] }, - { "type": "string", "enum": ["RS512"] }, - { "type": "string", "enum": ["ES256"] }, - { "type": "string", "enum": ["ES384"] }, - { "type": "string", "enum": ["ES512"] }, - { "type": "string", "enum": ["PS256"] }, - { "type": "string", "enum": ["PS384"] }, - { "type": "string", "enum": ["PS512"] } - ] - }, - "label": { "type": "string" } - }, - "required": ["publicKey", "algorithm"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "keypair": { - "type": "object", - "properties": { - "hash": { - "description": "A unique identifier for the keypair", - "type": "string" - }, - "publicKey": { - "description": "The public key", - "type": "string" - }, - "algorithm": { - "description": "The keypair algorithm.", - "type": "string" - }, - "label": { - "description": "A description for the keypair.", - "type": "string" - }, - "createdAt": { - "type": "string", - "format": "date", - "description": "When the keypair was added" - }, - "updatedAt": { - "type": "string", - "format": "date", - "description": "When the keypair was updated" - } - }, - "required": [ - "hash", - "publicKey", - "algorithm", - "createdAt", - "updatedAt" - ] - } - }, - "required": ["keypair"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/auth/keypair/remove": { - "post": { - "operationId": "remove", - "summary": "Remove public key", - "tags": ["Keypair"], - "description": "Remove the public key for a keypair", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "hash": { "type": "string" } }, - "required": ["hash"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/chain/get": { - "get": { - "operationId": "get", - "summary": "Get chain details", - "tags": ["Chain"], - "description": "Get details about a chain.", - "parameters": [ - { - "schema": { "type": "string" }, - "examples": { - "1": { "value": "1" }, - "ethereum": { "value": "ethereum" } - }, - "in": "query", - "name": "chain", - "required": true, - "description": "Chain name or ID" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "name": { - "description": "Chain name", - "type": "string" - }, - "chain": { - "description": "Chain name", - "type": "string" - }, - "rpc": { - "type": "array", - "items": { - "description": "RPC URL", - "type": "string" - } - }, - "nativeCurrency": { - "type": "object", - "properties": { - "name": { - "description": "Native currency name", - "type": "string" - }, - "symbol": { - "description": "Native currency symbol", - "type": "string" - }, - "decimals": { - "description": "Native currency decimals", - "type": "number" - } - }, - "required": ["name", "symbol", "decimals"] - }, - "shortName": { - "description": "Chain short name", - "type": "string" - }, - "chainId": { - "description": "Chain ID", - "type": "number" - }, - "testnet": { - "description": "Is testnet", - "type": "boolean" - }, - "slug": { - "description": "Chain slug", - "type": "string" - } - } - } - }, - "required": ["result"] - }, - "example": { - "result": { - "name": "Polygon Amoy Testnet", - "chain": "Polygon", - "rpc": [ - "https://80002.rpc.thirdweb.com/$%7BTHIRDWEB_API_SECRET_KEY%7D" - ], - "nativeCurrency": { - "name": "MATIC", - "symbol": "MATIC", - "decimals": 18 - }, - "shortName": "amoy", - "chainId": 80002, - "testnet": true, - "slug": "polygon-amoy-testnet" - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/chain/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all chain details", - "tags": ["Chain"], - "description": "Get details about all supported chains.", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "description": "Chain name", - "type": "string" - }, - "chain": { - "description": "Chain name", - "type": "string" - }, - "rpc": { - "type": "array", - "items": { - "description": "RPC URL", - "type": "string" - } - }, - "nativeCurrency": { - "type": "object", - "properties": { - "name": { - "description": "Native currency name", - "type": "string" - }, - "symbol": { - "description": "Native currency symbol", - "type": "string" - }, - "decimals": { - "description": "Native currency decimals", - "type": "number" - } - }, - "required": ["name", "symbol", "decimals"] - }, - "shortName": { - "description": "Chain short name", - "type": "string" - }, - "chainId": { - "description": "Chain ID", - "type": "number" - }, - "testnet": { - "description": "Is testnet", - "type": "boolean" - }, - "slug": { - "description": "Chain slug", - "type": "string" - } - } - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "name": "Ethereum Mainnet", - "chain": "ETH", - "rpc": [ - "https://ethereum.rpc.thirdweb.com/$%7BTHIRDWEB_API_SECRET_KEY%7D" - ], - "nativeCurrency": { - "name": "Ether", - "symbol": "ETH", - "decimals": 18 - }, - "shortName": "eth", - "chainId": 1, - "testnet": false, - "slug": "ethereum" - }, - { - "name": "Ropsten", - "chain": "ETH", - "rpc": [ - "https://ropsten.rpc.thirdweb.com/$%7BTHIRDWEB_API_SECRET_KEY%7D" - ], - "nativeCurrency": { - "name": "Ropsten Ether", - "symbol": "ETH", - "decimals": 18 - }, - "shortName": "rop", - "chainId": 3, - "testnet": true, - "slug": "ropsten" - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/relayer/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all meta-transaction relayers", - "tags": ["Relayer"], - "description": "Get all meta-transaction relayers", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "name": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "chainId": { "type": "string" }, - "backendWalletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "allowedContracts": { - "anyOf": [ - { - "type": "array", - "items": { "type": "string" } - }, - { "type": "null" } - ] - }, - "allowedForwarders": { - "anyOf": [ - { - "type": "array", - "items": { "type": "string" } - }, - { "type": "null" } - ] - } - }, - "required": [ - "id", - "name", - "chainId", - "backendWalletAddress", - "allowedContracts", - "allowedForwarders" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/relayer/create": { - "post": { - "operationId": "create", - "summary": "Create a new meta-transaction relayer", - "tags": ["Relayer"], - "description": "Create a new meta-transaction relayer", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "chain": { "type": "string" }, - "backendWalletAddress": { - "description": "The address of the backend wallet to use for relaying transactions.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "allowedContracts": { - "type": "array", - "items": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - }, - "allowedForwarders": { - "type": "array", - "items": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - }, - "required": ["chain", "backendWalletAddress"] - }, - "example": { - "name": "My relayer", - "chain": "mainnet", - "backendWalletAddress": "0", - "allowedContracts": ["0x1234...."], - "allowedForwarders": ["0x1234..."] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "relayerId": { "type": "string" } }, - "required": ["relayerId"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/relayer/revoke": { - "post": { - "operationId": "revoke", - "summary": "Revoke a relayer", - "tags": ["Relayer"], - "description": "Revoke a relayer", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "id": { "type": "string" } }, - "required": ["id"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/relayer/update": { - "post": { - "operationId": "update", - "summary": "Update a relayer", - "tags": ["Relayer"], - "description": "Update a relayer", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "name": { "type": "string" }, - "chain": { "type": "string" }, - "backendWalletAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "allowedContracts": { - "type": "array", - "items": { "type": "string" } - }, - "allowedForwarders": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["id"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "success": { "type": "boolean" } }, - "required": ["success"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/relayer/{relayerId}": { - "post": { - "operationId": "relay", - "summary": "Relay a meta-transaction", - "tags": ["Relayer"], - "description": "Relay an EIP-2771 meta-transaction", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["forward"] }, - "request": { - "type": "object", - "properties": { - "from": { "type": "string" }, - "to": { "type": "string" }, - "value": { "type": "string" }, - "gas": { "type": "string" }, - "nonce": { "type": "string" }, - "data": { "type": "string" }, - "chainid": { "type": "string" } - }, - "required": [ - "from", - "to", - "value", - "gas", - "nonce", - "data" - ] - }, - "signature": { "type": "string" }, - "forwarderAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - } - }, - "required": [ - "type", - "request", - "signature", - "forwarderAddress" - ] - }, - { - "type": "object", - "properties": { - "type": { "type": "string", "enum": ["permit"] }, - "request": { - "type": "object", - "properties": { - "to": { "type": "string" }, - "owner": { "type": "string" }, - "spender": { "type": "string" }, - "value": { "type": "string" }, - "nonce": { "type": "string" }, - "deadline": { "type": "string" } - }, - "required": [ - "to", - "owner", - "spender", - "value", - "nonce", - "deadline" - ] - }, - "signature": { "type": "string" } - }, - "required": ["type", "request", "signature"] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["execute-meta-transaction"] - }, - "request": { - "type": "object", - "properties": { - "from": { "type": "string" }, - "to": { "type": "string" }, - "data": { "type": "string" } - }, - "required": ["from", "to", "data"] - }, - "signature": { "type": "string" } - }, - "required": ["type", "request", "signature"] - } - ] - } - } - } - }, - "parameters": [ - { - "schema": { "type": "string" }, - "in": "path", - "name": "relayerId", - "required": true - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/read": { - "get": { - "operationId": "read", - "summary": "Read from contract", - "tags": ["Contract"], - "description": "Call a read function on a contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "balanceOf", - "in": "query", - "name": "functionName", - "required": true, - "description": "Name of the function to call on Contract" - }, - { - "schema": { "type": "string" }, - "example": "", - "in": "query", - "name": "args", - "required": false, - "description": "Arguments for the function. Comma Separated" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": {} }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/write": { - "post": { - "operationId": "write", - "summary": "Write to contract", - "tags": ["Contract"], - "description": "Call a write function on a contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "functionName": { - "description": "The function to call on the contract", - "type": "string" - }, - "args": { - "description": "The arguments to call on the function", - "type": "array", - "items": {} - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - }, - "abi": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "inputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "outputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "stateMutability": { "type": "string" } - }, - "required": ["type"] - } - } - }, - "required": ["functionName", "args"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/events/get-all": { - "get": { - "operationId": "getAllEvents", - "summary": "Get all events", - "tags": ["Contract-Events"], - "description": "Get a list of all blockchain events for this contract.", - "parameters": [ - { - "schema": { - "default": "0", - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "in": "query", - "name": "fromBlock", - "required": false - }, - { - "schema": { - "default": "latest", - "anyOf": [ - { "default": 0, "type": "number" }, - { "default": "0", "type": "string" } - ] - }, - "in": "query", - "name": "toBlock", - "required": false - }, - { - "schema": { - "default": "desc", - "anyOf": [ - { "type": "string", "enum": ["asc"] }, - { "type": "string", "enum": ["desc"] } - ] - }, - "in": "query", - "name": "order", - "required": false - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { "type": "object", "additionalProperties": {} } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "eventName": "Transfer", - "data": { - "from": "0x0000000000000000000000000000000000000000", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "tokenId": { "type": "BigNumber", "hex": "0x01" } - }, - "transaction": { - "blockNumber": 35439713, - "blockHash": "0x0413d9c88a664f46b54cd47d66073f47114fa3b0183ca5f713d4567d345de4a1", - "transactionIndex": 6, - "removed": false, - "address": "0xc8be6265C06aC376876b4F62670adB3c4d72EABA", - "data": "0x", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000001946267d81fb8adeeea28e6b98bcd446c8248473", - "0x0000000000000000000000000000000000000000000000000000000000000001" - ], - "transactionHash": "0x6ee82341f1e09511e9502eea45e0ca9e52dd0295a515401834d0d05a5e802da5", - "logIndex": 13, - "event": "Transfer", - "eventSignature": "Transfer(address,address,uint256)" - } - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/events/get": { - "post": { - "operationId": "getEvents", - "summary": "Get events", - "tags": ["Contract-Events"], - "description": "Get a list of specific blockchain events emitted from this contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "description": "Specify the from and to block numbers to get events for, defaults to all blocks", - "type": "object", - "properties": { - "eventName": { "type": "string", "example": "Transfer" }, - "fromBlock": { - "default": "0", - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "toBlock": { - "default": "latest", - "anyOf": [ - { "default": 0, "type": "number" }, - { "default": "0", "type": "string" } - ] - }, - "order": { - "default": "desc", - "anyOf": [ - { "type": "string", "enum": ["asc"] }, - { "type": "string", "enum": ["desc"] } - ] - }, - "filters": { "type": "object", "properties": {} } - }, - "required": ["eventName"] - } - } - }, - "required": true, - "description": "Specify the from and to block numbers to get events for, defaults to all blocks" - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { "type": "object", "additionalProperties": {} } - } - }, - "required": ["result"], - "example": { - "result": { - "eventName": "ApprovalForAll", - "data": { - "owner": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "operator": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "approved": true - }, - "transaction": { - "blockNumber": 36010321, - "blockHash": "0x2c388fe429215b6c2934746410a52a3416b7a1725cea6885eaf220f05f50a6ec", - "transactionIndex": 19, - "removed": false, - "address": "0xc8be6265C06aC376876b4F62670adB3c4d72EABA", - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "topics": [ - "0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31", - "0x000000000000000000000000e79ee09bd47f4f5381dbbacacff2040f2fbc5803", - "0x0000000000000000000000003ecdbf3b911d0e9052b64850693888b008e18373" - ], - "transactionHash": "0xa4143253005103e5203554f4e17e90a517591cd2d5e3b3dceabfbfb8fbdca5f9", - "logIndex": 55, - "event": "ApprovalForAll", - "eventSignature": "ApprovalForAll(address,address,bool)" - } - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/metadata/abi": { - "get": { - "operationId": "getAbi", - "summary": "Get ABI", - "tags": ["Contract-Metadata"], - "description": "Get the ABI of a contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "inputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "outputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "stateMutability": { "type": "string" } - }, - "required": ["type"] - } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "type": "function", - "name": "transferFrom", - "inputs": [ - { "type": "address", "name": "from" }, - { "type": "address", "name": "to" }, - { "type": "uint256", "name": "tokenId" } - ] - }, - { - "type": "event", - "name": "Transfer", - "inputs": [ - { "type": "address", "name": "from" }, - { "type": "address", "name": "to" }, - { "type": "uint256", "name": "tokenId" } - ] - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/metadata/events": { - "get": { - "operationId": "getEvents", - "summary": "Get events", - "tags": ["Contract-Metadata"], - "description": "Get details of all events implemented by a contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "inputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "outputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "comment": { "type": "string" } - }, - "required": ["name", "inputs", "outputs"] - } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "name": "Approval", - "inputs": [ - { "type": "address", "name": "owner" }, - { "type": "address", "name": "approved" }, - { "type": "uint256", "name": "tokenId" } - ], - "outputs": [] - }, - { - "name": "ApprovalForAll", - "inputs": [ - { "type": "address", "name": "owner" }, - { "type": "address", "name": "operator" }, - { "type": "bool", "name": "approved" } - ], - "outputs": [] - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/metadata/extensions": { - "get": { - "operationId": "getExtensions", - "summary": "Get extensions", - "tags": ["Contract-Metadata"], - "description": "Get all detected extensions for a contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "Array of detected extension names", - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["result"], - "example": { - "result": [ - "ERC721", - "ERC721Burnable", - "ERC721Supply", - "ERC721LazyMintable", - "ERC721Revealable", - "ERC721ClaimPhasesV2", - "Royalty", - "PlatformFee", - "PrimarySale", - "Permissions", - "PermissionsEnumerable", - "ContractMetadata", - "Ownable", - "Gasless" - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/metadata/functions": { - "get": { - "operationId": "getFunctions", - "summary": "Get functions", - "tags": ["Contract-Metadata"], - "description": "Get details of all functions implemented by the contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "inputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "outputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" }, - "stateMutability": { "type": "string" }, - "components": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "internalType": { "type": "string" } - } - } - } - } - } - }, - "comment": { "type": "string" }, - "signature": { "type": "string" }, - "stateMutability": { "type": "string" } - }, - "required": [ - "name", - "inputs", - "outputs", - "signature", - "stateMutability" - ] - } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "name": "balanceOf", - "inputs": [{ "type": "address", "name": "owner" }], - "outputs": [{ "type": "uint256", "name": "" }], - "comment": "See {IERC721-balanceOf}.", - "signature": "contract.call(\"balanceOf\", owner: string): Promise\u003CBigNumber\u003E", - "stateMutability": "view" - }, - { - "name": "burn", - "inputs": [{ "type": "uint256", "name": "tokenId" }], - "outputs": [], - "comment": "Burns `tokenId`. See {ERC721-_burn}.", - "signature": "contract.call(\"burn\", tokenId: BigNumberish): Promise\u003CTransactionResult\u003E", - "stateMutability": "nonpayable" - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/roles/get": { - "get": { - "operationId": "getRole", - "summary": "Get wallets for role", - "tags": ["Contract-Roles"], - "description": "Get all wallets with a specific role for a contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "role", - "required": true, - "description": "The role to list wallet members" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - }, - "example": { - "result": ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/roles/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get wallets for all roles", - "tags": ["Contract-Roles"], - "description": "Get all wallets in each role for a contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "admin": { - "type": "array", - "items": { "type": "string" } - }, - "transfer": { - "type": "array", - "items": { "type": "string" } - }, - "minter": { - "type": "array", - "items": { "type": "string" } - }, - "pauser": { - "type": "array", - "items": { "type": "string" } - }, - "lister": { - "type": "array", - "items": { "type": "string" } - }, - "asset": { - "type": "array", - "items": { "type": "string" } - }, - "unwrap": { - "type": "array", - "items": { "type": "string" } - }, - "factory": { - "type": "array", - "items": { "type": "string" } - }, - "signer": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "admin", - "transfer", - "minter", - "pauser", - "lister", - "asset", - "unwrap", - "factory", - "signer" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/roles/grant": { - "post": { - "operationId": "grant", - "summary": "Grant role", - "tags": ["Contract-Roles"], - "description": "Grant a role to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "description": "The role to grant", - "type": "string" - }, - "address": { - "description": "The address to grant the role to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["role", "address"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/roles/revoke": { - "post": { - "operationId": "revoke", - "summary": "Revoke role", - "tags": ["Contract-Roles"], - "description": "Revoke a role from a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "role": { - "description": "The role to revoke", - "type": "string" - }, - "address": { - "description": "The address to revoke the role from", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["role", "address"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/royalties/get-default-royalty-info": { - "get": { - "operationId": "getDefaultRoyaltyInfo", - "summary": "Get royalty details", - "tags": ["Contract-Royalties"], - "description": "Gets the royalty recipient and BPS (basis points) of the smart contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "seller_fee_basis_points": { - "description": "The royalty fee in BPS (basis points). 100 = 1%.", - "type": "number" - }, - "fee_recipient": { - "description": "The wallet address that will receive the royalty fees.", - "type": "string" - } - }, - "required": ["seller_fee_basis_points", "fee_recipient"] - } - }, - "required": ["result"] - }, - "example": { - "result": { - "fee_recipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "seller_fee_basis_points": 100 - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/royalties/get-token-royalty-info/{token_id}": { - "get": { - "operationId": "getTokenRoyaltyInfo", - "summary": "Get token royalty details", - "tags": ["Contract-Royalties"], - "description": "Gets the royalty recipient and BPS (basis points) of a particular token in the contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "path", - "name": "tokenId", - "required": true - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "seller_fee_basis_points": { - "description": "The royalty fee in BPS (basis points). 100 = 1%.", - "type": "number" - }, - "fee_recipient": { - "description": "The wallet address that will receive the royalty fees.", - "type": "string" - } - }, - "required": ["seller_fee_basis_points", "fee_recipient"] - } - }, - "required": ["result"] - }, - "example": { - "result": { - "fee_recipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "seller_fee_basis_points": 100 - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/royalties/set-default-royalty-info": { - "post": { - "operationId": "setDefaultRoyaltyInfo", - "summary": "Set royalty details", - "tags": ["Contract-Royalties"], - "description": "Set the royalty recipient and fee for the smart contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "seller_fee_basis_points": { - "description": "The royalty fee in BPS (basis points). 100 = 1%.", - "type": "number" - }, - "fee_recipient": { - "description": "The wallet address that will receive the royalty fees.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["seller_fee_basis_points", "fee_recipient"] - }, - "example": { - "fee_recipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "seller_fee_basis_points": 100 - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/royalties/set-token-royalty-info": { - "post": { - "operationId": "setTokenRoyaltyInfo", - "summary": "Set token royalty details", - "tags": ["Contract-Royalties"], - "description": "Set the royalty recipient and fee for a particular token in the contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "seller_fee_basis_points": { - "description": "The royalty fee in BPS (basis points). 100 = 1%.", - "type": "number" - }, - "fee_recipient": { - "description": "The wallet address that will receive the royalty fees.", - "type": "string" - }, - "token_id": { - "description": "The token ID to set the royalty info for.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": [ - "seller_fee_basis_points", - "fee_recipient", - "token_id" - ] - }, - "example": { - "fee_recipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "seller_fee_basis_points": 100, - "token_id": "0" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/edition": { - "post": { - "operationId": "deployEdition", - "summary": "Deploy Edition", - "tags": ["Deploy"], - "description": "Deploy an Edition contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My Edition", - "symbol": "ED", - "primary_sale_recipient": "\u003Cyour-wallet-address\u003E" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/edition-drop": { - "post": { - "operationId": "deployEditionDrop", - "summary": "Deploy Edition Drop", - "tags": ["Deploy"], - "description": "Deploy an Edition Drop contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "merkle": { - "type": "object", - "additionalProperties": { "type": "string" } - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My Edition Drop", - "symbol": "EDD", - "primary_sale_recipient": "\u003Cyour-wallet-address\u003E" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/marketplace-v3": { - "post": { - "operationId": "deployMarketplaceV3", - "summary": "Deploy Marketplace", - "tags": ["Deploy"], - "description": "Deploy a Marketplace contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { "contractMetadata": { "name": "My Marketplace" } } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/multiwrap": { - "post": { - "operationId": "deployMultiwrap", - "summary": "Deploy Multiwrap", - "tags": ["Deploy"], - "description": "Deploy a Multiwrap contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "symbol": { "default": "", "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { "name": "My Multiwrap", "symbol": "Mw" } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/nft-collection": { - "post": { - "operationId": "deployNFTCollection", - "summary": "Deploy NFT Collection", - "tags": ["Deploy"], - "description": "Deploy an NFT Collection contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My NFT Collection", - "symbol": "NFT" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/nft-drop": { - "post": { - "operationId": "deployNFTDrop", - "summary": "Deploy NFT Drop", - "tags": ["Deploy"], - "description": "Deploy an NFT Drop contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "merkle": { - "type": "object", - "additionalProperties": { "type": "string" } - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My NFT Drop", - "symbol": "NFTD", - "primary_sale_recipient": "\u003Cyour-wallet-address\u003E" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/pack": { - "post": { - "operationId": "deployPack", - "summary": "Deploy Pack", - "tags": ["Deploy"], - "description": "Deploy a Pack contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { "name": "My Pack", "symbol": "PACK" } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/signature-drop": { - "post": { - "operationId": "deploySignatureDrop", - "summary": "Deploy Signature Drop", - "tags": ["Deploy"], - "description": "Deploy a Signature Drop contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "seller_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "merkle": { - "type": "object", - "additionalProperties": { "type": "string" } - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "seller_fee_basis_points", - "fee_recipient", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My NFT Drop", - "symbol": "NFTD", - "primary_sale_recipient": "\u003Cyour-wallet-address\u003E" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/split": { - "post": { - "operationId": "deploySplit", - "summary": "Deploy Split", - "tags": ["Deploy"], - "description": "Deploy a Split contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "recipients": { - "type": "array", - "items": { - "type": "object", - "properties": { - "address": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "sharesBps": { - "exclusiveMinimum": 0, - "maximum": 10000, - "type": "number" - } - }, - "required": ["address", "sharesBps"] - } - }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["name", "recipients", "trusted_forwarders"] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My Split", - "recipients": [ - { - "recipient": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "percent": 50 - }, - { - "recipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "percent": 50 - } - ] - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/token": { - "post": { - "operationId": "deployToken", - "summary": "Deploy Token", - "tags": ["Deploy"], - "description": "Deploy a Token contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My Token", - "symbol": "TKN", - "primary_sale_recipient": "\u003Cyour-wallet-address\u003E" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/token-drop": { - "post": { - "operationId": "deployTokenDrop", - "summary": "Deploy Token Drop", - "tags": ["Deploy"], - "description": "Deploy a Token Drop contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "merkle": { - "type": "object", - "additionalProperties": { "type": "string" } - }, - "symbol": { "default": "", "type": "string" }, - "platform_fee_basis_points": { - "maximum": 10000, - "minimum": 0, - "default": 0, - "type": "number" - }, - "platform_fee_recipient": { - "default": "0x0000000000000000000000000000000000000000", - "type": "string" - }, - "primary_sale_recipient": { "type": "string" }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "symbol", - "platform_fee_basis_points", - "platform_fee_recipient", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { - "contractMetadata": { - "name": "My Signature Drop", - "symbol": "SIGD", - "primary_sale_recipient": "\u003Cyour-wallet-address\u003E" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/prebuilts/vote": { - "post": { - "operationId": "deployVote", - "summary": "Deploy Vote", - "tags": ["Deploy"], - "description": "Deploy a Vote contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "image": { "type": "string" }, - "external_link": { "type": "string" }, - "app_uri": { "type": "string" }, - "defaultAdmin": { "type": "string" }, - "voting_delay_in_blocks": { - "minimum": 0, - "default": 0, - "type": "number" - }, - "voting_period_in_blocks": { - "minimum": 1, - "default": 1, - "type": "number" - }, - "voting_token_address": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "voting_quorum_fraction": { - "maximum": 100, - "minimum": 0, - "default": 0, - "type": "number" - }, - "proposal_token_threshold": { - "default": "0", - "type": "string" - }, - "trusted_forwarders": { - "default": [], - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "name", - "voting_delay_in_blocks", - "voting_period_in_blocks", - "voting_token_address", - "voting_quorum_fraction", - "proposal_token_threshold", - "trusted_forwarders" - ] - }, - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["contractMetadata"] - }, - "example": { "contractMetadata": { "name": "My Vote" } } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/{chain}/{publisher}/{contractName}": { - "post": { - "operationId": "deployPublished", - "summary": "Deploy published contract", - "tags": ["Deploy"], - "description": "Deploy a published contract to the blockchain.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "version": { - "description": "Version of the contract to deploy. Defaults to latest.", - "type": "string" - }, - "forceDirectDeploy": { "type": "boolean" }, - "saltForProxyDeploy": { "type": "string" }, - "compilerOptions": { - "type": "object", - "properties": { - "compilerType": { - "type": "string", - "anyOf": [ - { "type": "string", "enum": ["solc"] }, - { "type": "string", "enum": ["string"] } - ], - "enum": ["zksolc"] - }, - "compilerVersion": { "type": "string" }, - "evmVersion": { "type": "string" } - }, - "required": ["compilerType"] - }, - "constructorParams": { - "description": "Constructor arguments for the deployment.", - "type": "array", - "items": {} - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["constructorParams"] - }, - "example": { - "constructorParams": [ - "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473" - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string" }, - "example": "deployer.thirdweb.eth", - "in": "path", - "name": "publisher", - "required": true, - "description": "Address or ENS of the publisher of the contract" - }, - { - "schema": { "type": "string" }, - "example": "AirdropERC20", - "in": "path", - "name": "contractName", - "required": true, - "description": "Name of the published contract to deploy" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "Not all contracts return a deployed address.", - "type": "string" - }, - "message": { "type": "string" } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/deploy/contract-types": { - "get": { - "operationId": "contractTypes", - "summary": "Get contract types", - "tags": ["Deploy"], - "description": "Get all prebuilt contract types.", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { "type": "array", "items": { "type": "string" } } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all transactions", - "tags": ["Transaction"], - "description": "Get all transaction requests.", - "parameters": [ - { - "schema": { "default": 1, "minimum": 1, "type": "integer" }, - "example": 1, - "in": "query", - "name": "page", - "required": true, - "description": "Specify the page number." - }, - { - "schema": { "default": 100, "type": "integer" }, - "example": 100, - "in": "query", - "name": "limit", - "required": true, - "description": "Specify the number of results to return per page." - }, - { - "schema": { - "default": "queued", - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["cancelled"] }, - { "type": "string", "enum": ["errored"] } - ] - }, - "in": "query", - "name": "status", - "required": true, - "description": "The status to query: 'queued', 'mined', 'errored', or 'cancelled'. Default: 'queued'" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "transactions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "queueId": { - "anyOf": [ - { - "description": "An identifier for an enqueued blockchain write call", - "type": "string" - }, - { "type": "null" } - ] - }, - "status": { - "description": "The current state of the transaction.", - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["sent"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["errored"] }, - { "type": "string", "enum": ["cancelled"] } - ], - "example": "queued" - }, - "chainId": { - "anyOf": [ - { - "description": "The chain ID for the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "fromAddress": { - "anyOf": [ - { - "description": "The backend wallet submitting the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "toAddress": { - "anyOf": [ - { - "description": "The contract address to be called", - "type": "string" - }, - { "type": "null" } - ] - }, - "data": { - "anyOf": [ - { - "description": "Encoded calldata", - "type": "string" - }, - { "type": "null" } - ] - }, - "extension": { - "anyOf": [ - { - "description": "The extension detected by thirdweb", - "type": "string" - }, - { "type": "null" } - ] - }, - "value": { - "anyOf": [ - { - "description": "The amount of native currency to send", - "type": "string" - }, - { "type": "null" } - ] - }, - "nonce": { - "anyOf": [ - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "number" - }, - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasLimit": { - "anyOf": [ - { - "description": "The max gas unit limit", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasPrice": { - "anyOf": [ - { - "description": "The gas price used", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "transactionType": { - "anyOf": [ - { - "description": "The type of transaction", - "type": "number" - }, - { "type": "null" } - ] - }, - "transactionHash": { - "anyOf": [ - { - "description": "The transaction hash (may not be mined)", - "type": "string" - }, - { "type": "null" } - ] - }, - "queuedAt": { - "anyOf": [ - { - "description": "When the transaction is enqueued", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAt": { - "anyOf": [ - { - "description": "When the transaction is submitted to mempool", - "type": "string" - }, - { "type": "null" } - ] - }, - "minedAt": { - "anyOf": [ - { - "description": "When the transaction is mined onchain", - "type": "string" - }, - { "type": "null" } - ] - }, - "cancelledAt": { - "anyOf": [ - { - "description": "When the transactino is cancelled", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractAddress": { - "anyOf": [ - { - "description": "The address for a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractType": { - "anyOf": [ - { - "description": "The type of a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "errorMessage": { - "anyOf": [ - { - "description": "The error that occurred", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAtBlockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is submitted to mempool", - "type": "number" - }, - { "type": "null" } - ] - }, - "blockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is mined", - "type": "number" - }, - { "type": "null" } - ] - }, - "retryCount": { - "description": "The number of retry attempts", - "type": "number" - }, - "retryGasValues": { - "anyOf": [ - { - "description": "Whether to replace gas values on the next retry", - "type": "boolean" - }, - { "type": "null" } - ] - }, - "retryMaxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "retryMaxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "signerAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "accountAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "target": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "sender": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "initCode": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "verificationGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "preVerificationGas": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "paymasterAndData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "userOpHash": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionName": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionArgs": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "onChainTxStatus": { - "anyOf": [ - { "type": "number" }, - { "type": "null" } - ] - }, - "onchainStatus": { - "anyOf": [ - { "type": "string", "enum": ["success"] }, - { "type": "string", "enum": ["reverted"] }, - { "type": "null" } - ] - }, - "effectiveGasPrice": { - "anyOf": [ - { - "description": "Effective Gas Price", - "type": "string" - }, - { "type": "null" } - ] - }, - "cumulativeGasUsed": { - "anyOf": [ - { - "description": "Cumulative Gas Used", - "type": "string" - }, - { "type": "null" } - ] - } - }, - "required": [ - "queueId", - "status", - "chainId", - "fromAddress", - "toAddress", - "data", - "extension", - "value", - "nonce", - "gasLimit", - "gasPrice", - "maxFeePerGas", - "maxPriorityFeePerGas", - "transactionType", - "transactionHash", - "queuedAt", - "sentAt", - "minedAt", - "cancelledAt", - "deployedContractAddress", - "deployedContractType", - "errorMessage", - "sentAtBlockNumber", - "blockNumber", - "retryCount", - "retryGasValues", - "retryMaxFeePerGas", - "retryMaxPriorityFeePerGas", - "signerAddress", - "accountAddress", - "target", - "sender", - "initCode", - "callData", - "callGasLimit", - "verificationGasLimit", - "preVerificationGas", - "paymasterAndData", - "userOpHash", - "functionName", - "functionArgs", - "onChainTxStatus", - "onchainStatus", - "effectiveGasPrice", - "cumulativeGasUsed" - ] - } - }, - "totalCount": { "type": "number" } - }, - "required": ["transactions", "totalCount"] - } - }, - "required": ["result"], - "example": { - "result": { - "transactions": [ - { - "queueId": "3bb66998-4c99-436c-9753-9dc931214a9b", - "chainId": "80001", - "fromAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373", - "toAddress": "0x365b83d67d5539c6583b9c0266a548926bf216f4", - "data": "0xa9059cbb0000000000000000000000003ecdbf3b911d0e9052b64850693888b008e183730000000000000000000000000000000000000000000000000000000000000064", - "extension": "none", - "value": "0x00", - "nonce": 1758, - "gasLimit": "39580", - "gasPrice": "2008818932", - "maxFeePerGas": "2209700838", - "maxPriorityFeePerGas": "2008818916", - "transactionType": 2, - "transactionHash": "0xf11ca950299c9e72b8d6cac8a03623c6e5a43af1d1b0d45b3fd804c129b573f8", - "queuedAt": "2023-09-29T18:17:36.929Z", - "sentAt": "2023-09-29T18:17:40.832Z", - "minedAt": "2023-09-29T18:17:44.000Z", - "cancelledAt": null, - "deployedContractAddress": null, - "deployedContractType": null, - "errorMessage": null, - "sentAtBlockNumber": 40653754, - "blockNumber": 40653756, - "status": "mined", - "retryCount": 0, - "retryGasValues": false, - "retryMaxFeePerGas": null, - "retryMaxPriorityFeePerGas": null, - "signerAddress": null, - "accountAddress": null, - "target": null, - "sender": null, - "initCode": null, - "callData": null, - "callGasLimit": null, - "verificationGasLimit": null, - "preVerificationGas": null, - "paymasterAndData": null, - "userOpHash": null, - "functionName": "transfer", - "functionArgs": "0x3ecdbf3b911d0e9052b64850693888b008e18373,100" - } - ], - "totalCount": 1 - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/status/{queueId}": { - "get": { - "operationId": "status", - "summary": "Get transaction status", - "tags": ["Transaction"], - "description": "Get the status for a transaction request.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "in": "path", - "name": "queueId", - "required": true, - "description": "Transaction queue ID" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "anyOf": [ - { - "description": "An identifier for an enqueued blockchain write call", - "type": "string" - }, - { "type": "null" } - ] - }, - "status": { - "description": "The current state of the transaction.", - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["sent"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["errored"] }, - { "type": "string", "enum": ["cancelled"] } - ], - "example": "queued" - }, - "chainId": { - "anyOf": [ - { - "description": "The chain ID for the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "fromAddress": { - "anyOf": [ - { - "description": "The backend wallet submitting the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "toAddress": { - "anyOf": [ - { - "description": "The contract address to be called", - "type": "string" - }, - { "type": "null" } - ] - }, - "data": { - "anyOf": [ - { - "description": "Encoded calldata", - "type": "string" - }, - { "type": "null" } - ] - }, - "extension": { - "anyOf": [ - { - "description": "The extension detected by thirdweb", - "type": "string" - }, - { "type": "null" } - ] - }, - "value": { - "anyOf": [ - { - "description": "The amount of native currency to send", - "type": "string" - }, - { "type": "null" } - ] - }, - "nonce": { - "anyOf": [ - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "number" - }, - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasLimit": { - "anyOf": [ - { - "description": "The max gas unit limit", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasPrice": { - "anyOf": [ - { - "description": "The gas price used", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "transactionType": { - "anyOf": [ - { - "description": "The type of transaction", - "type": "number" - }, - { "type": "null" } - ] - }, - "transactionHash": { - "anyOf": [ - { - "description": "The transaction hash (may not be mined)", - "type": "string" - }, - { "type": "null" } - ] - }, - "queuedAt": { - "anyOf": [ - { - "description": "When the transaction is enqueued", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAt": { - "anyOf": [ - { - "description": "When the transaction is submitted to mempool", - "type": "string" - }, - { "type": "null" } - ] - }, - "minedAt": { - "anyOf": [ - { - "description": "When the transaction is mined onchain", - "type": "string" - }, - { "type": "null" } - ] - }, - "cancelledAt": { - "anyOf": [ - { - "description": "When the transactino is cancelled", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractAddress": { - "anyOf": [ - { - "description": "The address for a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractType": { - "anyOf": [ - { - "description": "The type of a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "errorMessage": { - "anyOf": [ - { - "description": "The error that occurred", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAtBlockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is submitted to mempool", - "type": "number" - }, - { "type": "null" } - ] - }, - "blockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is mined", - "type": "number" - }, - { "type": "null" } - ] - }, - "retryCount": { - "description": "The number of retry attempts", - "type": "number" - }, - "retryGasValues": { - "anyOf": [ - { - "description": "Whether to replace gas values on the next retry", - "type": "boolean" - }, - { "type": "null" } - ] - }, - "retryMaxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "retryMaxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "signerAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "accountAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "target": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "sender": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "initCode": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "callData": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "callGasLimit": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "verificationGasLimit": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "preVerificationGas": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "paymasterAndData": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "userOpHash": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "functionName": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "functionArgs": { - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "onChainTxStatus": { - "anyOf": [{ "type": "number" }, { "type": "null" }] - }, - "onchainStatus": { - "anyOf": [ - { "type": "string", "enum": ["success"] }, - { "type": "string", "enum": ["reverted"] }, - { "type": "null" } - ] - }, - "effectiveGasPrice": { - "anyOf": [ - { - "description": "Effective Gas Price", - "type": "string" - }, - { "type": "null" } - ] - }, - "cumulativeGasUsed": { - "anyOf": [ - { - "description": "Cumulative Gas Used", - "type": "string" - }, - { "type": "null" } - ] - } - }, - "required": [ - "queueId", - "status", - "chainId", - "fromAddress", - "toAddress", - "data", - "extension", - "value", - "nonce", - "gasLimit", - "gasPrice", - "maxFeePerGas", - "maxPriorityFeePerGas", - "transactionType", - "transactionHash", - "queuedAt", - "sentAt", - "minedAt", - "cancelledAt", - "deployedContractAddress", - "deployedContractType", - "errorMessage", - "sentAtBlockNumber", - "blockNumber", - "retryCount", - "retryGasValues", - "retryMaxFeePerGas", - "retryMaxPriorityFeePerGas", - "signerAddress", - "accountAddress", - "target", - "sender", - "initCode", - "callData", - "callGasLimit", - "verificationGasLimit", - "preVerificationGas", - "paymasterAndData", - "userOpHash", - "functionName", - "functionArgs", - "onChainTxStatus", - "onchainStatus", - "effectiveGasPrice", - "cumulativeGasUsed" - ] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "a20ed4ce-301d-4251-a7af-86bd88f6c015", - "walletAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373", - "contractAddress": "0x365b83d67d5539c6583b9c0266a548926bf216f4", - "chainId": "80001", - "extension": "non-extension", - "status": "mined", - "encodedInputData": "0xa9059cbb0000000000000000000000001946267d81fb8adeeea28e6b98bcd446c824847300000000000000000000000000000000000000000000000000000000000186a0", - "txType": 2, - "gasPrice": "1500000017", - "gasLimit": "46512", - "maxPriorityFeePerGas": "1500000000", - "maxFeePerGas": "1500000034", - "txHash": "0x6de86da898fa4beb13d965c42bf331ad46cfa061cadf75f69791f31c9d8a4f66", - "submittedTxNonce": 698, - "createdTimestamp": "2023-08-25T22:42:26.910Z", - "txProcessedTimestamp": "2023-08-25T22:42:27.302Z", - "txSubmittedTimestamp": "2023-08-25T22:42:28.743Z", - "deployedContractAddress": "", - "contractType": "", - "errorMessage": "", - "txMinedTimestamp": "2023-08-25T22:42:33.000Z", - "blockNumber": 39398545, - "onChainTxStatus": 1 - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/get-all-deployed-contracts": { - "get": { - "operationId": "getAllDeployedContracts", - "summary": "Get all deployment transactions", - "tags": ["Transaction"], - "description": "Get all transaction requests to deploy contracts.", - "parameters": [ - { - "schema": { "default": 1, "minimum": 1, "type": "integer" }, - "example": 1, - "in": "query", - "name": "page", - "required": true, - "description": "Specify the page number for pagination." - }, - { - "schema": { "default": 10, "minimum": 1, "type": "integer" }, - "example": 10, - "in": "query", - "name": "limit", - "required": true, - "description": "Specify the number of transactions to return per page." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "transactions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "queueId": { - "anyOf": [ - { - "description": "An identifier for an enqueued blockchain write call", - "type": "string" - }, - { "type": "null" } - ] - }, - "status": { - "description": "The current state of the transaction.", - "anyOf": [ - { "type": "string", "enum": ["queued"] }, - { "type": "string", "enum": ["sent"] }, - { "type": "string", "enum": ["mined"] }, - { "type": "string", "enum": ["errored"] }, - { "type": "string", "enum": ["cancelled"] } - ], - "example": "queued" - }, - "chainId": { - "anyOf": [ - { - "description": "The chain ID for the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "fromAddress": { - "anyOf": [ - { - "description": "The backend wallet submitting the transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "toAddress": { - "anyOf": [ - { - "description": "The contract address to be called", - "type": "string" - }, - { "type": "null" } - ] - }, - "data": { - "anyOf": [ - { - "description": "Encoded calldata", - "type": "string" - }, - { "type": "null" } - ] - }, - "extension": { - "anyOf": [ - { - "description": "The extension detected by thirdweb", - "type": "string" - }, - { "type": "null" } - ] - }, - "value": { - "anyOf": [ - { - "description": "The amount of native currency to send", - "type": "string" - }, - { "type": "null" } - ] - }, - "nonce": { - "anyOf": [ - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "number" - }, - { - "description": "The nonce used by the backend wallet for this transaction", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasLimit": { - "anyOf": [ - { - "description": "The max gas unit limit", - "type": "string" - }, - { "type": "null" } - ] - }, - "gasPrice": { - "anyOf": [ - { - "description": "The gas price used", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "maxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas (EIP-1559)", - "type": "string" - }, - { "type": "null" } - ] - }, - "transactionType": { - "anyOf": [ - { - "description": "The type of transaction", - "type": "number" - }, - { "type": "null" } - ] - }, - "transactionHash": { - "anyOf": [ - { - "description": "The transaction hash (may not be mined)", - "type": "string" - }, - { "type": "null" } - ] - }, - "queuedAt": { - "anyOf": [ - { - "description": "When the transaction is enqueued", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAt": { - "anyOf": [ - { - "description": "When the transaction is submitted to mempool", - "type": "string" - }, - { "type": "null" } - ] - }, - "minedAt": { - "anyOf": [ - { - "description": "When the transaction is mined onchain", - "type": "string" - }, - { "type": "null" } - ] - }, - "cancelledAt": { - "anyOf": [ - { - "description": "When the transactino is cancelled", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractAddress": { - "anyOf": [ - { - "description": "The address for a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "deployedContractType": { - "anyOf": [ - { - "description": "The type of a deployed contract", - "type": "string" - }, - { "type": "null" } - ] - }, - "errorMessage": { - "anyOf": [ - { - "description": "The error that occurred", - "type": "string" - }, - { "type": "null" } - ] - }, - "sentAtBlockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is submitted to mempool", - "type": "number" - }, - { "type": "null" } - ] - }, - "blockNumber": { - "anyOf": [ - { - "description": "The block number when the transaction is mined", - "type": "number" - }, - { "type": "null" } - ] - }, - "retryCount": { - "description": "The number of retry attempts", - "type": "number" - }, - "retryGasValues": { - "anyOf": [ - { - "description": "Whether to replace gas values on the next retry", - "type": "boolean" - }, - { "type": "null" } - ] - }, - "retryMaxFeePerGas": { - "anyOf": [ - { - "description": "The max fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "retryMaxPriorityFeePerGas": { - "anyOf": [ - { - "description": "The max priority fee per gas to use on retry", - "type": "string" - }, - { "type": "null" } - ] - }, - "signerAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "accountAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "target": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "sender": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "initCode": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "callGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "verificationGasLimit": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "preVerificationGas": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "paymasterAndData": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "userOpHash": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionName": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "functionArgs": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "onChainTxStatus": { - "anyOf": [ - { "type": "number" }, - { "type": "null" } - ] - }, - "onchainStatus": { - "anyOf": [ - { "type": "string", "enum": ["success"] }, - { "type": "string", "enum": ["reverted"] }, - { "type": "null" } - ] - }, - "effectiveGasPrice": { - "anyOf": [ - { - "description": "Effective Gas Price", - "type": "string" - }, - { "type": "null" } - ] - }, - "cumulativeGasUsed": { - "anyOf": [ - { - "description": "Cumulative Gas Used", - "type": "string" - }, - { "type": "null" } - ] - } - }, - "required": [ - "queueId", - "status", - "chainId", - "fromAddress", - "toAddress", - "data", - "extension", - "value", - "nonce", - "gasLimit", - "gasPrice", - "maxFeePerGas", - "maxPriorityFeePerGas", - "transactionType", - "transactionHash", - "queuedAt", - "sentAt", - "minedAt", - "cancelledAt", - "deployedContractAddress", - "deployedContractType", - "errorMessage", - "sentAtBlockNumber", - "blockNumber", - "retryCount", - "retryGasValues", - "retryMaxFeePerGas", - "retryMaxPriorityFeePerGas", - "signerAddress", - "accountAddress", - "target", - "sender", - "initCode", - "callData", - "callGasLimit", - "verificationGasLimit", - "preVerificationGas", - "paymasterAndData", - "userOpHash", - "functionName", - "functionArgs", - "onChainTxStatus", - "onchainStatus", - "effectiveGasPrice", - "cumulativeGasUsed" - ] - } - }, - "totalCount": { "type": "number" } - }, - "required": ["transactions", "totalCount"] - } - }, - "required": ["result"], - "example": { - "result": { - "transactions": [ - { - "queueId": "8fe7d546-2b8b-465e-b0d2-f1cb5d3d0db3", - "walletAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373", - "contractAddress": "0x5dbc7b840baa9dabcbe9d2492e45d7244b54a2a0", - "chainId": "80001", - "extension": "deploy_prebuilt", - "status": "submitted", - "encodedInputData": "0x11b804ab0000000000000000000000004fa15bae96f5816c268f3b473cf67e223644d536000000000000000000000000000000000000000000000000000000000000006033373131393539310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000284e15916340000000000000000000000003ecdbf3b911d0e9052b64850693888b008e183730000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000003ecdbf3b911d0e9052b64850693888b008e18373000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034949490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000349494900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037697066733a2f2f516d5553734471664a4879686375686f504e653650374566336547717864466e78516977526d37585a434234724b2f300000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c82bbe41f2cf04e3a8efa18f7032bdd7f6d98a810000000000000000000000009399bb24dbb5c4b782c70c2969f58716ebbd6a3b00000000000000000000000000000000000000000000000000000000", - "txType": 2, - "gasPrice": "", - "gasLimit": "925188", - "maxPriorityFeePerGas": "1500000000", - "maxFeePerGas": "1500000032", - "txHash": "0x383b0ef55b76f1848f81c1016580f83faf3cde9f6affd66f789e741e39861f30", - "submittedTxNonce": 111, - "createdTimestamp": "2023-06-21T18:05:18.979Z", - "txSubmittedTimestamp": "2023-06-21T18:05:21.823Z", - "txProcessedTimestamp": "2023-06-21T18:05:21.823Z", - "deployedContractAddress": "0x8dE0E40e8a5108Da3e0D65cFc908269fE083DfE7", - "contractType": "edition" - } - ], - "totalCount": 1 - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/sync-retry": { - "post": { - "operationId": "syncRetry", - "summary": "Retry transaction (synchronous)", - "tags": ["Transaction"], - "description": "Retry a transaction with updated gas settings. Blocks until the transaction is mined or errors.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "queueId": { - "description": "Transaction queue ID", - "type": "string", - "example": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - }, - "maxFeePerGas": { "type": "string" }, - "maxPriorityFeePerGas": { "type": "string" } - }, - "required": ["queueId"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "transactionHash": { "type": "string" } }, - "required": ["transactionHash"] - } - }, - "required": ["result"], - "example": { - "result": { - "transactionHash": "0xc3b437073c164c33f95065fb325e9bc419f306cb39ae8b4ca233f33efaa74ead" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/retry-failed": { - "post": { - "operationId": "retryFailed", - "summary": "Retry failed transaction", - "tags": ["Transaction"], - "description": "Retry a failed transaction", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "queueId": { - "description": "Transaction queue ID", - "type": "string", - "example": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - }, - "required": ["queueId"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "status": { "type": "string" } - }, - "required": ["message", "status"] - } - }, - "required": ["result"], - "example": { - "result": { - "message": "Transaction queued for retry with queueId: a20ed4ce-301d-4251-a7af-86bd88f6c015", - "status": "success" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/cancel": { - "post": { - "operationId": "cancel", - "summary": "Cancel transaction", - "tags": ["Transaction"], - "description": "Attempt to cancel a transaction by sending a null transaction with a higher gas setting. This transaction is not guaranteed to be cancelled.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "queueId": { - "description": "Transaction queue ID", - "type": "string", - "example": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - }, - "required": ["queueId"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Transaction queue ID", - "type": "string", - "example": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - }, - "status": { - "description": "Response status", - "type": "string", - "example": "success, error" - }, - "message": { - "description": "Response message", - "type": "string", - "example": "Transaction cancelled on-chain successfully" - }, - "transactionHash": { - "description": "Transaction hash of the on-chain cancel transaction", - "type": "string", - "example": "0x0514076b5b7e3062c8dc17e10f7c0befe88e6efb7e97f16e3c14afb36c296467" - } - }, - "required": ["queueId", "status", "message"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "a20ed4ce-301d-4251-a7af-86bd88f6c015", - "status": "success" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/{chain}/send-signed-transaction": { - "post": { - "operationId": "sendRawTransaction", - "summary": "Send a signed transaction", - "tags": ["Transaction"], - "description": "Send a signed transaction", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "signedTransaction": { "type": "string" } }, - "required": ["signedTransaction"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "transactionHash": { "type": "string" } }, - "required": ["transactionHash"] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/{chain}/send-signed-user-op": { - "post": { - "operationId": "sendSignedUserOp", - "summary": "Send a signed user operation", - "tags": ["Transaction"], - "description": "Send a signed user operation", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "signedUserOp": {} }, - "required": ["signedUserOp"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "userOpHash": { "type": "string" } }, - "required": ["userOpHash"] - } - }, - "required": ["result"] - }, - { - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { "message": { "type": "string" } }, - "required": ["message"] - } - }, - "required": ["error"] - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/{chain}/tx-hash/{txHash}": { - "get": { - "operationId": "txHashReceipt", - "summary": "Get transaction receipt from transaction hash", - "tags": ["Transaction"], - "description": "Get the transaction receipt from a transaction hash.", - "parameters": [ - { - "schema": { "pattern": "^0x([A-Fa-f0-9]{64})$", "type": "string" }, - "example": "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - "in": "path", - "name": "txHash", - "required": true, - "description": "Transaction hash" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "object", - "properties": { - "to": { "type": "string" }, - "from": { "type": "string" }, - "contractAddress": { - "anyOf": [ - { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - { "type": "null" } - ] - }, - "transactionIndex": { "type": "number" }, - "root": { "type": "string" }, - "gasUsed": { "type": "string" }, - "logsBloom": { "type": "string" }, - "blockHash": { "type": "string" }, - "transactionHash": { "type": "string" }, - "logs": { "type": "array", "items": {} }, - "blockNumber": { "type": "number" }, - "confirmations": { "type": "number" }, - "cumulativeGasUsed": { "type": "string" }, - "effectiveGasPrice": { "type": "string" }, - "byzantium": { "type": "boolean" }, - "type": { "type": "number" }, - "status": { "type": "number" } - } - }, - { "type": "null" } - ] - } - }, - "required": ["result"], - "example": { - "result": { - "to": "0xd7419703c2D5737646525A8660906eCb612875BD", - "from": "0x9783Eb2a93A58b24CFeC56F94b30aB6e29fF4b38", - "contractAddress": null, - "transactionIndex": 69, - "gasUsed": "21000", - "logsBloom": "0x00000000000200000000000000000000000000000000000000000000000000000000000000000000000000100002000000008000000000000000000000002000000000000000000000000000000000800000000000000000000100000000040000000000000000000000000000000000008000000000000080000000000000000000000000000000000000000000000000000000000000040000000000000000200000000000004000800000000000000000000000000000000000000000004000000000000000000001000000000000000000000000800000108000000000000000000000000000000000000000000000000000000000000000008000100000", - "blockHash": "0x9be85de9e6a0717ed2e7c9035f7bd748a4b20bc9d6e04a6875fa69311421d971", - "transactionHash": "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - "logs": [ - { - "transactionIndex": 69, - "blockNumber": 51048531, - "transactionHash": "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - "address": "0x0000000000000000000000000000000000001010", - "topics": [ - "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x0000000000000000000000009783eb2a93a58b24cfec56f94b30ab6e29ff4b38", - "0x000000000000000000000000d7419703c2d5737646525a8660906ecb612875bd" - ], - "data": "0x00000000000000000000000000000000000000000000000006a4d6a25acff49800000000000000000000000000000000000000000000000006b787e1bb9f06f80000000000000000000000000000000000000000000000051ac78aecb02246820000000000000000000000000000000000000000000000000012b13f60cf1260000000000000000000000000000000000000000000000005216c618f0af23b1a", - "logIndex": 181, - "blockHash": "0x9be85de9e6a0717ed2e7c9035f7bd748a4b20bc9d6e04a6875fa69311421d971" - }, - { - "transactionIndex": 69, - "blockNumber": 51048531, - "transactionHash": "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - "address": "0x0000000000000000000000000000000000001010", - "topics": [ - "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x0000000000000000000000009783eb2a93a58b24cfec56f94b30ab6e29ff4b38", - "0x000000000000000000000000a8b52f02108aa5f4b675bdcc973760022d7c6020" - ], - "data": "0x00000000000000000000000000000000000000000000000000046a2c9f9fd11800000000000000000000000000000000000000000000000006ce8dc1a70476680000000000000000000000000000000000000000000006df390338516c1391c300000000000000000000000000000000000000000000000006ca23950764a5500000000000000000000000000000000000000000000006df3907a27e0bb362db", - "logIndex": 182, - "blockHash": "0x9be85de9e6a0717ed2e7c9035f7bd748a4b20bc9d6e04a6875fa69311421d971" - } - ], - "blockNumber": 51048531, - "confirmations": 3232643, - "cumulativeGasUsed": "5751865", - "effectiveGasPrice": "257158085297", - "status": 1, - "type": 2, - "byzantium": true - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/{chain}/userop-hash/{userOpHash}": { - "get": { - "operationId": "useropHashReceipt", - "summary": "Get transaction receipt from user-op hash", - "tags": ["Transaction"], - "description": "Get the transaction receipt from a user-op hash.", - "parameters": [ - { - "schema": { "pattern": "^0x([A-Fa-f0-9]{64})$", "type": "string" }, - "example": "0xa5a579c6fd86c2d8a4d27f5bb22796614d3a31bbccaba8f3019ec001e001b95f", - "in": "path", - "name": "userOpHash", - "required": true, - "description": "User operation hash" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": {} }, - "required": ["result"], - "example": { - "result": { - "userOpHash": "0xa5a579c6fd86c2d8a4d27f5bb22796614d3a31bbccaba8f3019ec001e001b95f", - "sender": "0x8C6bdb488F664EB98E12cB2671fE2389Cc227D33", - "nonce": "0x18554d9a95404c5e8ac591f8608a18f80000000000000000", - "actualGasCost": "0x4b3b147f788710", - "actualGasUsed": "0x7f550", - "success": true, - "paymaster": "0xe3dc822D77f8cA7ac74c30B0dfFEA9FcDCAAA321", - "logs": [], - "receipt": { - "type": "eip1559", - "status": "success", - "cumulativeGasUsed": "0x4724c3", - "logsBloom": "0x010004000800020000000040000000000000040000000000000010000004000000080000001000000212841100000000041080000000000020000240000000000800000022001000400000080000028000040000000000200001000010000000000000000a0000000000000000800800000000004110004080800110282000000000000002000000000000000000000000000200000400000000000000240040200002000000000000400000000002000140000000000000000002200000004000000002000000000021000000000000000000000000800080108020000020000000080000000000000000000000000000000000000000000108000000102000", - "logs": [], - "transactionHash": "0x57465d20d634421008a167cfcfcde94847dba9d6b5d3652b071d4b84e5ce74ff", - "from": "0x43370996a3aff7b66b3ac7676dd973d01ecec039", - "to": "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789", - "contractAddress": null, - "gasUsed": "0x7ff5a", - "effectiveGasPrice": "0x89b098f46", - "blockHash": "0xeaeec1eff4095bdcae44d86574cf1bf08b14b26be571b7c2290f32f9f250c103", - "blockNumber": "0x31de70e", - "transactionIndex": 32, - "blobGasUsed": "0x0" - } - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/transaction/logs": { - "get": { - "operationId": "getTransactionLogs", - "summary": "Get transaction logs", - "tags": ["Transaction"], - "description": "Get transaction logs for a mined transaction. A tranasction queue ID or hash must be provided. Set `parseLogs` to parse the event logs.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "query", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "queueId", - "required": false, - "description": "The queue ID for a mined transaction." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{64}$" }, - "example": "0x1f31b57601a6f90312fd5e57a2924bc8333477de579ee37b197a0681ab438431", - "in": "query", - "name": "transactionHash", - "required": false, - "description": "The transaction hash for a mined transaction." - }, - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "parseLogs", - "required": false, - "description": "If true, parse the raw logs as events defined in the contract ABI. (Default: true)" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "object", - "properties": { - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "topics": { - "type": "array", - "items": { "type": "string" } - }, - "data": { "type": "string" }, - "blockNumber": { "type": "string" }, - "transactionHash": { - "description": "A transaction hash", - "examples": [ - "0x1f31b57601a6f90312fd5e57a2924bc8333477de579ee37b197a0681ab438431" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{64}$" - }, - "transactionIndex": { "type": "number" }, - "blockHash": { "type": "string" }, - "logIndex": { "type": "number" }, - "removed": { "type": "boolean" }, - "eventName": { "type": "string" }, - "args": { - "description": "Event arguments.", - "examples": [ - { - "from": "0xdeadbeeefdeadbeeefdeadbeeefdeadbeeefdead", - "to": "0xdeadbeeefdeadbeeefdeadbeeefdeadbeeefdead", - "value": "1000000000000000000n" - } - ] - } - }, - "required": [ - "address", - "topics", - "data", - "blockNumber", - "transactionHash", - "transactionIndex", - "blockHash", - "logIndex", - "removed", - "eventName", - "args" - ] - } - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "topics": { - "type": "array", - "items": { "type": "string" } - }, - "data": { "type": "string" }, - "blockNumber": { "type": "string" }, - "transactionHash": { - "description": "A transaction hash", - "examples": [ - "0x1f31b57601a6f90312fd5e57a2924bc8333477de579ee37b197a0681ab438431" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{64}$" - }, - "transactionIndex": { "type": "number" }, - "blockHash": { "type": "string" }, - "logIndex": { "type": "number" }, - "removed": { "type": "boolean" } - }, - "required": [ - "address", - "topics", - "data", - "blockNumber", - "transactionHash", - "transactionIndex", - "blockHash", - "logIndex", - "removed" - ] - } - } - ] - } - }, - "required": ["result"], - "example": { - "result": [ - { - "eventName": "Transfer", - "args": { - "from": "0x0000000000000000000000000000000000000000", - "to": "0x71B6267b5b2b0B64EE058C3D27D58e4E14e7327f", - "value": "1000000000000000000n" - }, - "address": "0x71b6267b5b2b0b64ee058c3d27d58e4e14e7327f", - "topics": [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000071b6267b5b2b0b64ee058c3d27d58e4e14e7327f" - ], - "data": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - "blockNumber": "79326434", - "transactionHash": "0x568eb49d738f7c02ebb24aa329efcf10883d951b1e13aa000b0e073d54a0246e", - "transactionIndex": 1, - "blockHash": "0xaffbcf3232a76152206de5f6999c549404efc76060a34f8826b90c95993464c3", - "logIndex": 0, - "removed": false - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account-factory/get-all-accounts": { - "get": { - "operationId": "getAllAccounts", - "summary": "Get all smart accounts", - "tags": ["Account Factory"], - "description": "Get all the smart accounts for this account factory.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "The account addresses of all the accounts in this factory", - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account-factory/get-associated-accounts": { - "get": { - "operationId": "getAssociatedAccounts", - "summary": "Get associated smart accounts", - "tags": ["Account Factory"], - "description": "Get all the smart accounts for this account factory associated with the specific admin wallet.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "signerAddress", - "required": true, - "description": "The address of the signer to get associated accounts from" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "The account addresses of all the accounts with a specific signer in this factory", - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account-factory/is-account-deployed": { - "get": { - "operationId": "isAccountDeployed", - "summary": "Check if deployed", - "tags": ["Account Factory"], - "description": "Check if a smart account has been deployed to the blockchain.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "adminAddress", - "required": true, - "description": "The address of the admin to check if the account address is deployed" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "extraData", - "required": false, - "description": "Extra data to use in predicting the account address" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "Whether or not the account has been deployed", - "type": "boolean" - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account-factory/predict-account-address": { - "get": { - "operationId": "predictAccountAddress", - "summary": "Predict smart account address", - "tags": ["Account Factory"], - "description": "Get the counterfactual address of a smart account.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "adminAddress", - "required": true, - "description": "The address of the admin to predict the account address for" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "extraData", - "required": false, - "description": "Extra data to add to use in predicting the account address" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "New account counter-factual address.", - "type": "string" - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account-factory/create-account": { - "post": { - "operationId": "createAccount", - "summary": "Create smart account", - "tags": ["Account Factory"], - "description": "Create a smart account for this account factory.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "adminAddress": { - "description": "The admin address to create an account for", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "extraData": { - "description": "Extra data to add to use in creating the account address", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["adminAddress"] - }, - "example": { - "adminAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { "type": "string" }, - "deployedAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/admins/get-all": { - "get": { - "operationId": "getAllAdmins", - "summary": "Get all admins", - "tags": ["Account"], - "description": "Get all admins for a smart account.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "The address of the admins on this account", - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/sessions/get-all": { - "get": { - "operationId": "getAllSessions", - "summary": "Get all session keys", - "tags": ["Account"], - "description": "Get all session keys for a smart account.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "signerAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "startDate": { "type": "string" }, - "expirationDate": { "type": "string" }, - "nativeTokenLimitPerTransaction": { - "type": "string" - }, - "approvedCallTargets": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": [ - "signerAddress", - "startDate", - "expirationDate", - "nativeTokenLimitPerTransaction", - "approvedCallTargets" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/admins/grant": { - "post": { - "operationId": "grantAdmin", - "summary": "Grant admin", - "tags": ["Account"], - "description": "Grant a smart account's admin permission.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "signerAddress": { - "description": "Address to grant admin permissions to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["signerAddress"] - }, - "example": { - "signerAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/admins/revoke": { - "post": { - "operationId": "revokeAdmin", - "summary": "Revoke admin", - "tags": ["Account"], - "description": "Revoke a smart account's admin permission.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "walletAddress": { - "description": "Address to revoke admin permissions from", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["walletAddress"] - }, - "example": { - "walletAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/sessions/create": { - "post": { - "operationId": "grantSession", - "summary": "Create session key", - "tags": ["Account"], - "description": "Create a session key for a smart account.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "signerAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "startDate": { "type": "string" }, - "expirationDate": { "type": "string" }, - "nativeTokenLimitPerTransaction": { "type": "string" }, - "approvedCallTargets": { - "type": "array", - "items": { "type": "string" } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": [ - "signerAddress", - "startDate", - "expirationDate", - "nativeTokenLimitPerTransaction", - "approvedCallTargets" - ] - }, - "example": { - "signerAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373", - "startDate": "2021-01-01T00:00:00.000Z", - "expirationDate": "2022-01-01T00:10:00.000Z", - "nativeTokenLimitPerTransaction": "1000000000000000000", - "approvedCallTargets": [ - "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473" - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/sessions/revoke": { - "post": { - "operationId": "revokeSession", - "summary": "Revoke session key", - "tags": ["Account"], - "description": "Revoke a session key for a smart account.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "walletAddress": { - "description": "Address to revoke session from", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["walletAddress"] - }, - "example": { - "walletAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/account/sessions/update": { - "post": { - "operationId": "updateSession", - "summary": "Update session key", - "tags": ["Account"], - "description": "Update a session key for a smart account.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "signerAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "approvedCallTargets": { - "type": "array", - "items": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - } - }, - "startDate": { "type": "string" }, - "expirationDate": { "type": "string" }, - "nativeTokenLimitPerTransaction": { "type": "string" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["signerAddress", "approvedCallTargets"] - }, - "example": { - "signerAddress": "0x3ecdbf3b911d0e9052b64850693888b008e18373", - "approvedCallTargets": [ - "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473" - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/allowance-of": { - "get": { - "operationId": "allowanceOf", - "summary": "Get token allowance", - "tags": ["ERC20"], - "description": "Get the allowance of a specific wallet for an ERC-20 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "in": "query", - "name": "ownerWallet", - "required": true, - "description": "Address of the wallet who owns the funds" - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "spenderWallet", - "required": true, - "description": "Address of the wallet to check token allowance" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "string" }, - "value": { - "description": "Value in wei", - "type": "string" - }, - "displayValue": { - "description": "Value in tokens", - "type": "string" - } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ] - } - }, - "required": ["result"], - "example": { - "result": { - "name": "ERC20", - "symbol": "", - "decimals": "18", - "value": "0", - "displayValue": "0.0" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/balance-of": { - "get": { - "operationId": "balanceOf", - "summary": "Get token balance", - "tags": ["ERC20"], - "description": "Get the balance of a specific wallet address for this ERC-20 contract.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "wallet_address", - "required": true, - "description": "Address of the wallet to check token balance" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "string" }, - "value": { - "description": "Value in wei", - "type": "string" - }, - "displayValue": { - "description": "Value in tokens", - "type": "string" - } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ] - } - }, - "required": ["result"], - "example": [ - { - "result": { - "name": "ERC20", - "symbol": "", - "decimals": "18", - "value": "7799999999615999974", - "displayValue": "7.799999999615999974" - } - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/get": { - "get": { - "operationId": "get", - "summary": "Get token details", - "tags": ["ERC20"], - "description": "Get details for this ERC-20 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "string" } - }, - "required": ["name", "symbol", "decimals"] - } - }, - "required": ["result"], - "example": { - "result": { - "name": "ERC20", - "symbol": "", - "decimals": "18" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/total-supply": { - "get": { - "operationId": "totalSupply", - "summary": "Get total supply", - "tags": ["ERC20"], - "description": "Get the total supply in circulation for this ERC-20 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "string" }, - "value": { - "description": "Value in wei", - "type": "string" - }, - "displayValue": { - "description": "Value in tokens", - "type": "string" - } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ] - } - }, - "required": ["result"], - "example": [ - { - "result": { - "name": "Mumba20", - "symbol": "", - "decimals": "18", - "value": "10000000000000000000", - "displayValue": "10.0" - } - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/signature/generate": { - "post": { - "operationId": "signatureGenerate", - "summary": "Generate signature", - "tags": ["ERC20"], - "description": "Generate a signature granting access for another wallet to mint tokens from this ERC-20 contract. This method is typically called by the token contract owner.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "type": "string" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "anyOf": [ - { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "string" - }, - { "type": "number" } - ] - }, - "mintEndTime": { - "anyOf": [ - { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "string" - }, - { "type": "number" } - ] - } - }, - "required": ["to", "quantity"], - "examples": [ - { - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "quantity": "1", - "mintStartTime": "2023-06-07T21:51:33.386Z", - "mintEndTime": "2023-07-07T21:51:33.386Z" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "to": { "type": "string" }, - "primarySaleRecipient": { "type": "string" }, - "price": { "type": "string" }, - "priceInWei": { "type": "string" }, - "currency": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": ["to", "validityStartTimestamp"] - }, - { - "anyOf": [ - { - "type": "object", - "properties": { "quantity": { "type": "string" } }, - "required": ["quantity"] - }, - { - "type": "object", - "properties": { - "quantityWei": { "type": "string" } - }, - "required": ["quantityWei"] - } - ] - } - ] - } - ] - } - } - } - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": false, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-thirdweb-sdk-version", - "required": false, - "description": "Override the thirdweb sdk version used. Example: \"5\" for v5 SDK compatibility." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "description": "The time from which the signature can be used to mint tokens. Defaults to now.", - "default": 1728953485972, - "type": "number" - }, - "mintEndTime": { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "default": 2044313485972, - "type": "number" - } - }, - "required": [ - "to", - "quantity", - "primarySaleRecipient", - "uid", - "currencyAddress", - "price", - "mintStartTime", - "mintEndTime" - ], - "examples": [ - { - "payload": { - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "quantity": "1", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3834383133343631326235613434363261623532623264643462336239373634", - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686174693, - "mintEndTime": 1688766693 - }, - "signature": "0xe16697bf7ede4ff4918f0dbc84953b964a84fed70cb3a0b0afb3ee9a55c9ff4d14e029bce8d8c74e71c1de32889c4eff529a9f7d45402455b8d15c7e6993c1c91b" - } - ] - }, - "signature": { "type": "string" } - }, - "required": ["payload", "signature"] - }, - { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "to": { "type": "string" }, - "primarySaleRecipient": { "type": "string" }, - "quantity": { "type": "string" }, - "price": { "type": "string" }, - "currency": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": [ - "to", - "primarySaleRecipient", - "quantity", - "price", - "currency", - "validityStartTimestamp", - "validityEndTimestamp", - "uid" - ] - }, - "signature": { "type": "string" } - }, - "required": ["payload", "signature"] - } - ] - } - }, - "required": ["result"], - "example": { "result": "1" } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/can-claim": { - "get": { - "operationId": "canClaim", - "summary": "Check if tokens are available for claiming", - "tags": ["ERC20"], - "description": "Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "quantity", - "required": true, - "description": "The amount of tokens to claim." - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "addressToCheck", - "required": false, - "description": "The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-active": { - "get": { - "operationId": "getActiveClaimConditions", - "summary": "Retrieve the currently active claim phase, if any.", - "tags": ["ERC20"], - "description": "Retrieve the currently active claim phase, if any.", - "parameters": [ - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "withAllowList", - "required": false, - "description": "Provide a boolean value to include the allowlist in the response." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "format": "date-time", - "type": "string" - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "availableSupply": { "type": "string" }, - "currentMintSupply": { "type": "string" }, - "currencyMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "null" }, - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - } - ] - } - }, - "required": [ - "startTime", - "merkleRootHash", - "availableSupply", - "currentMintSupply", - "currencyMetadata" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-all": { - "get": { - "operationId": "getAllClaimConditions", - "summary": "Get all the claim phases configured.", - "tags": ["ERC20"], - "description": "Get all the claim phases configured on the drop contract.", - "parameters": [ - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "withAllowList", - "required": false, - "description": "Provide a boolean value to include the allowlist in the response." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "startTime": { - "format": "date-time", - "type": "string" - }, - "price": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "waitInSeconds": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "availableSupply": { "type": "string" }, - "currentMintSupply": { "type": "string" }, - "currencyMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "null" }, - { - "type": "array", - "items": { "type": "string" } - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - } - ] - } - }, - "required": [ - "startTime", - "merkleRootHash", - "availableSupply", - "currentMintSupply", - "currencyMetadata" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-claim-ineligibility-reasons": { - "get": { - "operationId": "claimConditionsGetClaimIneligibilityReasons", - "summary": "Get claim ineligibility reasons", - "tags": ["ERC20"], - "description": "Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "quantity", - "required": true, - "description": "The amount of tokens to claim." - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "addressToCheck", - "required": false, - "description": "The wallet address to check if it can claim tokens." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "anyOf": [ - { "type": "string" }, - { - "anyOf": [ - { - "type": "string", - "enum": ["There is not enough supply to claim."] - }, - { - "type": "string", - "enum": [ - "This address is not on the allowlist." - ] - }, - { - "type": "string", - "enum": [ - "Not enough time since last claim transaction. Please wait." - ] - }, - { - "type": "string", - "enum": ["Claim phase has not started yet."] - }, - { - "type": "string", - "enum": ["You have already claimed the token."] - }, - { - "type": "string", - "enum": ["Incorrect price or currency."] - }, - { - "type": "string", - "enum": [ - "Cannot claim more than maximum allowed quantity." - ] - }, - { - "type": "string", - "enum": [ - "There are not enough tokens in the wallet to pay for the claim." - ] - }, - { - "type": "string", - "enum": [ - "There is no active claim phase at the moment. Please check back in later." - ] - }, - { - "type": "string", - "enum": ["There is no claim condition set."] - }, - { - "type": "string", - "enum": ["No wallet connected."] - }, - { - "type": "string", - "enum": ["No claim conditions found."] - } - ] - } - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-claimer-proofs": { - "post": { - "operationId": "claimConditionsGetClaimerProofs", - "summary": "Get claimer proofs", - "tags": ["ERC20"], - "description": "Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "The wallet address to get the merkle proofs for." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { "type": "null" }, - { - "type": "object", - "properties": { - "price": { "type": "string" }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { "type": "string" }, - "proof": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["address", "maxClaimable", "proof"] - } - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/set-allowance": { - "post": { - "operationId": "setAllowance", - "summary": "Set allowance", - "tags": ["ERC20"], - "description": "Grant a specific wallet address to transfer ERC-20 tokens from the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "spenderAddress": { - "description": "Address of the wallet to allow transfers from", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "amount": { - "description": "The number of tokens to give as allowance", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["spenderAddress", "amount"] - }, - "example": { - "spenderAddress": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "amount": "100" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/transfer": { - "post": { - "operationId": "transfer", - "summary": "Transfer tokens", - "tags": ["ERC20"], - "description": "Transfer ERC-20 tokens from the caller wallet to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "toAddress": { - "description": "Address of the wallet you want to send the tokens to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "amount": { - "description": "The amount of tokens you want to send", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["toAddress", "amount"] - }, - "example": { - "toAddress": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "amount": "0.1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/transfer-from": { - "post": { - "operationId": "transferFrom", - "summary": "Transfer tokens from wallet", - "tags": ["ERC20"], - "description": "Transfer ERC-20 tokens from the connected wallet to another wallet. Requires allowance.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "fromAddress": { - "description": "Address of the wallet sending the tokens", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "toAddress": { - "description": "Address of the wallet you want to send the tokens to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "amount": { - "description": "The amount of tokens you want to send", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["fromAddress", "toAddress", "amount"] - }, - "example": { - "fromAddress": "0x....", - "toAddress": "0x...", - "amount": "0.1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/burn": { - "post": { - "operationId": "burn", - "summary": "Burn token", - "tags": ["ERC20"], - "description": "Burn ERC-20 tokens in the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "amount": { - "description": "The amount of tokens you want to burn", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["amount"] - }, - "example": { "amount": "0.1" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/burn-from": { - "post": { - "operationId": "burnFrom", - "summary": "Burn token from wallet", - "tags": ["ERC20"], - "description": "Burn ERC-20 tokens in a specific wallet. Requires allowance.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "holderAddress": { - "description": "Address of the wallet sending the tokens", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "amount": { - "description": "The amount of this token you want to burn", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["holderAddress", "amount"] - }, - "example": { - "holderAddress": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "amount": "0.1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-to": { - "post": { - "operationId": "claimTo", - "summary": "Claim tokens to wallet", - "tags": ["ERC20"], - "description": "Claim ERC-20 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "recipient": { - "description": "The wallet address to receive the claimed tokens.", - "type": "string" - }, - "amount": { - "description": "The amount of tokens to claim.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["recipient", "amount"] - }, - "example": { - "recipient": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "amount": "0.1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/mint-batch-to": { - "post": { - "operationId": "mintBatchTo", - "summary": "Mint tokens (batch)", - "tags": ["ERC20"], - "description": "Mint ERC-20 tokens to multiple wallets in one transaction.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "type": "object", - "properties": { - "toAddress": { - "description": "The address to mint tokens to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "amount": { - "description": "The number of tokens to mint to the specific address.", - "type": "string" - } - }, - "required": ["toAddress", "amount"] - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["data"] - }, - "example": { - "data": [ - { - "toAddress": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "amount": "0.1" - }, - { - "toAddress": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "amount": "0.1" - } - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/mint-to": { - "post": { - "operationId": "mintTo", - "summary": "Mint tokens", - "tags": ["ERC20"], - "description": "Mint ERC-20 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "toAddress": { - "description": "Address of the wallet to mint tokens to", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "amount": { - "description": "The amount of tokens you want to send", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["toAddress", "amount"] - }, - "example": { - "toAddress": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "amount": "0.1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x365b83D67D5539C6583b9c0266A548926Bf216F4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC20 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/signature/mint": { - "post": { - "operationId": "signatureMint", - "summary": "Signature mint", - "tags": ["ERC20"], - "description": "Mint ERC-20 tokens from a generated signature.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "description": "The time from which the signature can be used to mint tokens. Defaults to now.", - "default": 1728953485972, - "type": "number" - }, - "mintEndTime": { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "default": 2044313485972, - "type": "number" - } - }, - "required": [ - "to", - "quantity", - "primarySaleRecipient", - "uid", - "currencyAddress", - "price", - "mintStartTime", - "mintEndTime" - ], - "example": { - "payload": { - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "quantity": "1", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3834383133343631326235613434363261623532623264643462336239373634", - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686174693, - "mintEndTime": 1688766693 - }, - "signature": "0xe16697bf7ede4ff4918f0dbc84953b964a84fed70cb3a0b0afb3ee9a55c9ff4d14e029bce8d8c74e71c1de32889c4eff529a9f7d45402455b8d15c7e6993c1c91b" - } - }, - "signature": { "type": "string" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["payload", "signature"] - }, - "example": { "payload": {}, "signature": "" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/set": { - "post": { - "operationId": "setClaimConditions", - "summary": "Overwrite the claim conditions for the drop.", - "tags": ["ERC20"], - "description": "Overwrite the claim conditions for the drop. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "claimConditionInputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - } - }, - "resetClaimEligibilityForAll": { "type": "boolean" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["claimConditionInputs"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc20/claim-conditions/update": { - "post": { - "operationId": "updateClaimConditions", - "summary": "Update a single claim phase.", - "tags": ["ERC20"], - "description": "Update a single claim phase, by providing the index of the claim phase and the new phase configuration. The index is the position of the phase in the list of phases you have made, starting from zero. e.g. if you have two phases, the first phase has an index of 0 and the second phase has an index of 1. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "claimConditionInput": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - }, - "index": { - "description": "Index of the claim condition to update", - "type": "number" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["claimConditionInput", "index"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/get": { - "get": { - "operationId": "get", - "summary": "Get details", - "tags": ["ERC721"], - "description": "Get the details for a token in an ERC-721 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "0", - "in": "query", - "name": "tokenId", - "required": true, - "description": "The tokenId of the NFT to retrieve" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "metadata": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "owner": { "type": "string" }, - "type": { - "anyOf": [ - { "type": "string", "enum": ["ERC1155"] }, - { "type": "string", "enum": ["ERC721"] }, - { "type": "string", "enum": ["metaplex"] } - ] - }, - "supply": { "type": "string" }, - "quantityOwned": { "type": "string" } - }, - "required": ["metadata", "owner", "type", "supply"] - } - }, - "required": ["result"], - "example": [ - { - "result": { - "metadata": { - "id": "2", - "uri": "ipfs://QmWDdRcLqVMzFeawADAPr2EFCzdqCzx373VpWK3Kfx25GJ/0", - "name": "My NFT", - "description": "My NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "type": "ERC721", - "supply": "1" - } - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all details", - "tags": ["ERC721"], - "description": "Get details for all tokens in an ERC-721 contract.", - "parameters": [ - { - "schema": { "type": "number" }, - "example": "0", - "in": "query", - "name": "start", - "required": false, - "description": "The start token id for paginated results. Defaults to 0." - }, - { - "schema": { "type": "number" }, - "example": "20", - "in": "query", - "name": "count", - "required": false, - "description": "The page count for paginated results. Defaults to 100." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "metadata": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "owner": { "type": "string" }, - "type": { - "anyOf": [ - { "type": "string", "enum": ["ERC1155"] }, - { "type": "string", "enum": ["ERC721"] }, - { "type": "string", "enum": ["metaplex"] } - ] - }, - "supply": { "type": "string" }, - "quantityOwned": { "type": "string" } - }, - "required": ["metadata", "owner", "type", "supply"] - } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "metadata": { - "id": "2", - "uri": "ipfs://QmWDdRcLqVMzFeawADAPr2EFCzdqCzx373VpWK3Kfx25GJ/0", - "name": "My NFT", - "description": "My NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "type": "ERC721", - "supply": "1" - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/get-owned": { - "get": { - "operationId": "getOwned", - "summary": "Get owned tokens", - "tags": ["ERC721"], - "description": "Get all tokens in an ERC-721 contract owned by a specific wallet.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "Address of the wallet to get NFTs for" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "metadata": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "owner": { "type": "string" }, - "type": { - "anyOf": [ - { "type": "string", "enum": ["ERC1155"] }, - { "type": "string", "enum": ["ERC721"] }, - { "type": "string", "enum": ["metaplex"] } - ] - }, - "supply": { "type": "string" }, - "quantityOwned": { "type": "string" } - }, - "required": ["metadata", "owner", "type", "supply"] - } - } - }, - "required": ["result"], - "example": [ - { - "result": [ - { - "metadata": { - "id": "2", - "uri": "ipfs://QmWDdRcLqVMzFeawADAPr2EFCzdqCzx373VpWK3Kfx25GJ/0", - "name": "My NFT", - "description": "My NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "type": "ERC721", - "supply": "1" - } - ] - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/balance-of": { - "get": { - "operationId": "balanceOf", - "summary": "Get token balance", - "tags": ["ERC721"], - "description": "Get the balance of a specific wallet address for this ERC-721 contract.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "Address of the wallet to check NFT balance" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC721 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "example": { "result": "1" } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/is-approved": { - "get": { - "operationId": "isApproved", - "summary": "Check if approved transfers", - "tags": ["ERC721"], - "description": "Check if the specific wallet has approved transfers from a specific operator wallet.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "in": "query", - "name": "ownerWallet", - "required": true, - "description": "Address of the wallet who owns the NFT" - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "operator", - "required": true, - "description": "Address of the operator to check approval on" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "example": { "result": false } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/total-count": { - "get": { - "operationId": "totalCount", - "summary": "Get total supply", - "tags": ["ERC721"], - "description": "Get the total supply in circulation for this ERC-721 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "example": [{ "result": "1" }] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/total-claimed-supply": { - "get": { - "operationId": "totalClaimedSupply", - "summary": "Get claimed supply", - "tags": ["ERC721"], - "description": "Get the claimed supply for this ERC-721 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/total-unclaimed-supply": { - "get": { - "operationId": "totalUnclaimedSupply", - "summary": "Get unclaimed supply", - "tags": ["ERC721"], - "description": "Get the unclaimed supply for this ERC-721 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/can-claim": { - "get": { - "operationId": "canClaim", - "summary": "Check if tokens are available for claiming", - "tags": ["ERC721"], - "description": "Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "quantity", - "required": true, - "description": "The amount of tokens to claim." - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "addressToCheck", - "required": false, - "description": "The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-active": { - "get": { - "operationId": "getActiveClaimConditions", - "summary": "Retrieve the currently active claim phase, if any.", - "tags": ["ERC721"], - "description": "Retrieve the currently active claim phase, if any.", - "parameters": [ - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "withAllowList", - "required": false, - "description": "Provide a boolean value to include the allowlist in the response." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "format": "date-time", - "type": "string" - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "availableSupply": { "type": "string" }, - "currentMintSupply": { "type": "string" }, - "currencyMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "null" }, - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - } - ] - } - }, - "required": [ - "startTime", - "merkleRootHash", - "availableSupply", - "currentMintSupply", - "currencyMetadata" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-all": { - "get": { - "operationId": "getAllClaimConditions", - "summary": "Get all the claim phases configured for the drop.", - "tags": ["ERC721"], - "description": "Get all the claim phases configured for the drop.", - "parameters": [ - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "withAllowList", - "required": false, - "description": "Provide a boolean value to include the allowlist in the response." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "startTime": { - "format": "date-time", - "type": "string" - }, - "price": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "waitInSeconds": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "availableSupply": { "type": "string" }, - "currentMintSupply": { "type": "string" }, - "currencyMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "null" }, - { - "type": "array", - "items": { "type": "string" } - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - } - ] - } - }, - "required": [ - "startTime", - "merkleRootHash", - "availableSupply", - "currentMintSupply", - "currencyMetadata" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-claim-ineligibility-reasons": { - "get": { - "operationId": "getClaimIneligibilityReasons", - "summary": "Get claim ineligibility reasons", - "tags": ["ERC721"], - "description": "Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "quantity", - "required": true, - "description": "The amount of tokens to claim." - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "addressToCheck", - "required": false, - "description": "The wallet address to check if it can claim tokens." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "anyOf": [ - { "type": "string" }, - { - "anyOf": [ - { - "type": "string", - "enum": ["There is not enough supply to claim."] - }, - { - "type": "string", - "enum": [ - "This address is not on the allowlist." - ] - }, - { - "type": "string", - "enum": [ - "Not enough time since last claim transaction. Please wait." - ] - }, - { - "type": "string", - "enum": ["Claim phase has not started yet."] - }, - { - "type": "string", - "enum": ["You have already claimed the token."] - }, - { - "type": "string", - "enum": ["Incorrect price or currency."] - }, - { - "type": "string", - "enum": [ - "Cannot claim more than maximum allowed quantity." - ] - }, - { - "type": "string", - "enum": [ - "There are not enough tokens in the wallet to pay for the claim." - ] - }, - { - "type": "string", - "enum": [ - "There is no active claim phase at the moment. Please check back in later." - ] - }, - { - "type": "string", - "enum": ["There is no claim condition set."] - }, - { - "type": "string", - "enum": ["No wallet connected."] - }, - { - "type": "string", - "enum": ["No claim conditions found."] - } - ] - } - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-claimer-proofs": { - "get": { - "operationId": "getClaimerProofs", - "summary": "Get claimer proofs", - "tags": ["ERC721"], - "description": "Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "The wallet address to get the merkle proofs for." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { "type": "null" }, - { - "type": "object", - "properties": { - "price": { "type": "string" }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { "type": "string" }, - "proof": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["address", "maxClaimable", "proof"] - } - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/set-approval-for-all": { - "post": { - "operationId": "setApprovalForAll", - "summary": "Set approval for all", - "tags": ["ERC721"], - "description": "Approve or remove operator as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "operator": { - "description": "Address of the operator to give approval to", - "type": "string" - }, - "approved": { - "description": "whether to approve or revoke approval", - "type": "boolean" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["operator", "approved"] - }, - "example": { - "operator": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "approved": "true" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/set-approval-for-token": { - "post": { - "operationId": "setApprovalForToken", - "summary": "Set approval for token", - "tags": ["ERC721"], - "description": "Approve an operator for the NFT owner. Operators can call transferFrom or safeTransferFrom for the specific token.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "operator": { - "description": "Address of the operator to give approval to", - "type": "string" - }, - "tokenId": { - "description": "the tokenId to give approval for", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["operator", "tokenId"] - }, - "example": { - "operator": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "0" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/transfer": { - "post": { - "operationId": "transfer", - "summary": "Transfer token", - "tags": ["ERC721"], - "description": "Transfer an ERC-721 token from the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "to": { - "description": "Address of the wallet to transfer to", - "type": "string" - }, - "tokenId": { - "description": "The tokenId to transfer", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["to", "tokenId"] - }, - "example": { - "to": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "0" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/transfer-from": { - "post": { - "operationId": "transferFrom", - "summary": "Transfer token from wallet", - "tags": ["ERC721"], - "description": "Transfer an ERC-721 token from the connected wallet to another wallet. Requires allowance.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "from": { - "description": "Address of the token owner", - "type": "string" - }, - "to": { - "description": "Address of the wallet to transferFrom to", - "type": "string" - }, - "tokenId": { - "description": "the tokenId to transferFrom", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["from", "to", "tokenId"] - }, - "example": { - "from": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "to": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "0" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/mint-to": { - "post": { - "operationId": "mintTo", - "summary": "Mint tokens", - "tags": ["ERC721"], - "description": "Mint ERC-721 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to mint the NFT to", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "image": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "metadata"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "metadata": { - "name": "My NFT", - "description": "My NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/mint-batch-to": { - "post": { - "operationId": "mintBatchTo", - "summary": "Mint tokens (batch)", - "tags": ["ERC721"], - "description": "Mint ERC-721 tokens to multiple wallets in one transaction.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to mint the NFT to", - "type": "string" - }, - "metadatas": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "metadatas"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "metadata": [ - { - "name": "My NFT #1", - "description": "My NFT #1 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - { - "name": "My NFT #2", - "description": "My NFT #2 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - } - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/burn": { - "post": { - "operationId": "burn", - "summary": "Burn token", - "tags": ["ERC721"], - "description": "Burn ERC-721 tokens in the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "The token ID to burn", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId"] - }, - "example": { "tokenId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/lazy-mint": { - "post": { - "operationId": "lazyMint", - "summary": "Lazy mint", - "tags": ["ERC721"], - "description": "Lazy mint ERC-721 tokens to be claimed in the future.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "metadatas": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["metadatas"] - }, - "example": { - "metadatas": [ - { - "name": "My NFT #1", - "description": "My NFT #1 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - { - "name": "My NFT #2", - "description": "My NFT #2 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - } - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-to": { - "post": { - "operationId": "claimTo", - "summary": "Claim tokens to wallet", - "tags": ["ERC721"], - "description": "Claim ERC-721 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to claim the NFT to", - "type": "string" - }, - "quantity": { - "description": "Quantity of NFTs to mint", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "quantity"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "quantity": "1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/signature/generate": { - "post": { - "operationId": "signatureGenerate", - "summary": "Generate signature", - "tags": ["ERC721"], - "description": "Generate a signature granting access for another wallet to mint tokens from this ERC-721 contract. This method is typically called by the token contract owner.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - "type": "number" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "type": "string" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "anyOf": [ - { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "string" - }, - { "type": "number" } - ] - }, - "mintEndTime": { - "anyOf": [ - { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "string" - }, - { "type": "number" } - ] - } - }, - "required": ["to", "metadata"], - "examples": [ - { - "to": "0x...", - "quantity": "1", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "mintStartTime": "2023-06-07T21:51:33.386Z", - "mintEndTime": "2023-07-07T21:51:33.386Z" - } - ] - }, - { - "type": "object", - "properties": { - "metadata": { - "anyOf": [ - { "type": "string" }, - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "type": "string" - }, - "description": { - "description": "The description of the NFT", - "type": "string" - }, - "image": { - "description": "The image of the NFT", - "type": "string" - }, - "animation_url": { - "description": "The animation url of the NFT", - "type": "string" - }, - "external_url": { - "description": "The external url of the NFT", - "type": "string" - }, - "background_color": { - "description": "The background color of the NFT", - "type": "string" - }, - "properties": { - "description": "(not recommended - use \"attributes\") The properties of the NFT." - }, - "attributes": { - "description": "Arbitrary metadata for this item.", - "type": "array", - "items": { - "type": "object", - "properties": { - "trait_type": { "type": "string" }, - "value": { "type": "string" } - }, - "required": ["trait_type", "value"] - } - } - } - } - ] - }, - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "price": { - "description": "The amount of the \"currency\" token this token costs. Example: \"0.1\"", - "type": "string" - }, - "priceInWei": { - "description": "The amount of the \"currency\" token this token costs in wei. Remember to use the correct decimals amount for the currency. Example: \"100000000000000000\" = 0.1 ETH (18 decimals)", - "type": "string" - }, - "currency": { - "description": "The currency address to pay for minting the tokens. Defaults to the chain's native token.", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "primarySaleRecipient": { - "description": "If a price is specified, funds will be sent to the \"primarySaleRecipient\" address. Defaults to the \"primarySaleRecipient\" address of the contract.", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the \"royaltyRecipient\" address of the contract.", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the \"royaltyBps\" of the contract.", - "type": "integer" - }, - "validityStartTimestamp": { - "description": "The start time (in Unix seconds) when the signature can be used to mint. Default: now", - "type": "integer" - }, - "validityEndTimestamp": { - "description": "The end time (in Unix seconds) when the signature can be used to mint. Default: 10 years", - "type": "integer" - }, - "uid": { - "description": "The uid is a unique identifier hashed in the payload to prevent replay attacks, ensuring it's only used once on-chain.", - "type": "string" - } - }, - "required": ["metadata", "to"] - } - ] - } - } - } - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC721 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": false, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-thirdweb-sdk-version", - "required": false, - "description": "Override the thirdweb sdk version used. Example: \"5\" for v5 SDK compatibility." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "description": "The time from which the signature can be used to mint tokens. Defaults to now.", - "type": "number" - }, - "mintEndTime": { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "number" - } - }, - "required": [ - "uri", - "to", - "royaltyRecipient", - "quantity", - "royaltyBps", - "primarySaleRecipient", - "uid", - "metadata", - "currencyAddress", - "mintStartTime", - "mintEndTime" - ], - "examples": [ - { - "payload": { - "uri": "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "royaltyRecipient": "0x0000000000000000000000000000000000000000", - "quantity": "1", - "royaltyBps": "0", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3862386334363135326230303461303939626136653361643131343836373563", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686169938, - "mintEndTime": 2001529938 - }, - "signature": "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b" - } - ] - }, - "signature": { "type": "string" } - }, - "required": ["payload", "signature"] - }, - { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "to": { "type": "string" }, - "price": { "type": "string" }, - "currency": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "primarySaleRecipient": { "type": "string" }, - "royaltyRecipient": { "type": "string" }, - "royaltyBps": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": [ - "uri", - "to", - "price", - "currency", - "primarySaleRecipient", - "royaltyRecipient", - "royaltyBps", - "validityStartTimestamp", - "validityEndTimestamp", - "uid" - ] - }, - "signature": { "type": "string" } - }, - "required": ["payload", "signature"] - } - ] - } - }, - "required": ["result"], - "example": { - "result": { - "payload": { - "uri": "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "royaltyRecipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "quantity": "1", - "royaltyBps": "0", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3862386334363135326230303461303939626136653361643131343836373563", - "metadata": { - "name": "test token", - "description": "test token" - }, - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686169938, - "mintEndTime": 2001529938 - }, - "signature": "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/signature/mint": { - "post": { - "operationId": "signatureMint", - "summary": "Signature mint", - "tags": ["ERC721"], - "description": "Mint ERC-721 tokens from a generated signature.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "payload": { - "anyOf": [ - { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "description": "The time from which the signature can be used to mint tokens. Defaults to now.", - "type": "number" - }, - "mintEndTime": { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "number" - } - }, - "required": [ - "uri", - "to", - "royaltyRecipient", - "quantity", - "royaltyBps", - "primarySaleRecipient", - "uid", - "metadata", - "currencyAddress", - "mintStartTime", - "mintEndTime" - ], - "examples": [ - { - "payload": { - "uri": "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "royaltyRecipient": "0x0000000000000000000000000000000000000000", - "quantity": "1", - "royaltyBps": "0", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3862386334363135326230303461303939626136653361643131343836373563", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686169938, - "mintEndTime": 2001529938 - }, - "signature": "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b" - } - ] - }, - { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "to": { "type": "string" }, - "price": { "type": "string" }, - "currency": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "primarySaleRecipient": { "type": "string" }, - "royaltyRecipient": { "type": "string" }, - "royaltyBps": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": [ - "uri", - "to", - "price", - "currency", - "primarySaleRecipient", - "royaltyRecipient", - "royaltyBps", - "validityStartTimestamp", - "validityEndTimestamp", - "uid" - ] - } - ] - }, - "signature": { "type": "string" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["payload", "signature"] - }, - "example": { - "payload": { - "uri": "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "royaltyRecipient": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "quantity": "1", - "royaltyBps": "0", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3862386334363135326230303461303939626136653361643131343836373563", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686169938, - "mintEndTime": 2001529938 - }, - "signature": "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/set": { - "post": { - "operationId": "setClaimConditions", - "summary": "Overwrite the claim conditions for the drop.", - "tags": ["ERC721"], - "description": "Overwrite the claim conditions for the drop. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "claimConditionInputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - } - }, - "resetClaimEligibilityForAll": { "type": "boolean" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["claimConditionInputs"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/claim-conditions/update": { - "post": { - "operationId": "updateClaimConditions", - "summary": "Update a single claim phase.", - "tags": ["ERC721"], - "description": "Update a single claim phase, by providing the index of the claim phase and the new phase configuration. The index is the position of the phase in the list of phases you have made, starting from zero. e.g. if you have two phases, the first phase has an index of 0 and the second phase has an index of 1. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "claimConditionInput": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - }, - "index": { - "description": "Index of the claim condition to update", - "type": "number" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["claimConditionInput", "index"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/signature/prepare": { - "post": { - "operationId": "signaturePrepare", - "summary": "Prepare signature", - "tags": ["ERC721"], - "description": "Prepares a payload for a wallet to generate a signature.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "metadata": { - "anyOf": [ - { "type": "string" }, - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "type": "string" - }, - "description": { - "description": "The description of the NFT", - "type": "string" - }, - "image": { - "description": "The image of the NFT", - "type": "string" - }, - "animation_url": { - "description": "The animation url of the NFT", - "type": "string" - }, - "external_url": { - "description": "The external url of the NFT", - "type": "string" - }, - "background_color": { - "description": "The background color of the NFT", - "type": "string" - }, - "properties": { - "description": "(not recommended - use \"attributes\") The properties of the NFT." - }, - "attributes": { - "description": "Arbitrary metadata for this item.", - "type": "array", - "items": { - "type": "object", - "properties": { - "trait_type": { "type": "string" }, - "value": { "type": "string" } - }, - "required": ["trait_type", "value"] - } - } - } - } - ] - }, - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "price": { - "description": "The amount of the \"currency\" token this token costs. Example: \"0.1\"", - "type": "string" - }, - "priceInWei": { - "description": "The amount of the \"currency\" token this token costs in wei. Remember to use the correct decimals amount for the currency. Example: \"100000000000000000\" = 0.1 ETH (18 decimals)", - "type": "string" - }, - "currency": { - "description": "The currency address to pay for minting the tokens. Defaults to the chain's native token.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "primarySaleRecipient": { - "description": "If a price is specified, funds will be sent to the \"primarySaleRecipient\" address. Defaults to the \"primarySaleRecipient\" address of the contract.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the \"royaltyRecipient\" address of the contract.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the \"royaltyBps\" of the contract.", - "type": "integer" - }, - "validityStartTimestamp": { - "description": "The start time (in Unix seconds) when the signature can be used to mint. Default: now", - "type": "integer" - }, - "validityEndTimestamp": { - "description": "The end time (in Unix seconds) when the signature can be used to mint. Default: 10 years", - "type": "integer" - }, - "uid": { - "description": "The uid is a unique identifier hashed in the payload to prevent replay attacks, ensuring it's only used once on-chain.", - "type": "string" - } - }, - "required": ["metadata", "to"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC721 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "mintPayload": { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "to": { "type": "string" }, - "price": { "type": "string" }, - "currency": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "primarySaleRecipient": { "type": "string" }, - "royaltyRecipient": { "type": "string" }, - "royaltyBps": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": [ - "uri", - "to", - "price", - "currency", - "primarySaleRecipient", - "royaltyRecipient", - "royaltyBps", - "validityStartTimestamp", - "validityEndTimestamp", - "uid" - ] - }, - "typedDataPayload": { - "description": "The payload to sign with a wallet's `signTypedData` method.", - "type": "object", - "properties": { - "domain": { - "description": "Specifies the contextual information used to prevent signature reuse across different contexts.", - "type": "object", - "properties": { - "name": { "type": "string" }, - "version": { "type": "string" }, - "chainId": { "type": "number" }, - "verifyingContract": { "type": "string" } - }, - "required": [ - "name", - "version", - "chainId", - "verifyingContract" - ] - }, - "types": { - "description": "Defines the structure of the data types used in the message.", - "type": "object", - "properties": { - "EIP712Domain": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "type": { "type": "string" } - }, - "required": ["name", "type"] - } - }, - "MintRequest": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "type": { "type": "string" } - }, - "required": ["name", "type"] - } - } - }, - "required": ["EIP712Domain", "MintRequest"] - }, - "message": { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "to": { "type": "string" }, - "price": { "type": "string" }, - "currency": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "primarySaleRecipient": { "type": "string" }, - "royaltyRecipient": { "type": "string" }, - "royaltyBps": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": [ - "uri", - "to", - "price", - "currency", - "primarySaleRecipient", - "royaltyRecipient", - "royaltyBps", - "validityStartTimestamp", - "validityEndTimestamp", - "uid" - ], - "description": "The structured data to be signed." - }, - "primaryType": { - "description": "The main type of the data in the message corresponding to a defined type in the `types` field.", - "type": "string", - "enum": ["MintRequest"] - } - }, - "required": [ - "domain", - "types", - "message", - "primaryType" - ] - } - }, - "required": ["mintPayload", "typedDataPayload"] - } - }, - "required": ["result"], - "example": { - "result": { - "result": { - "mintPayload": { - "uri": "ipfs://...", - "currency": "0x0000000000000000000000000000000000000000", - "uid": "0x3862386334363135326230303461303939626136653361643131343836373563", - "to": "0x...", - "royaltyRecipient": "0x...", - "primarySaleRecipient": "0x..." - }, - "typedDataPayload": { - "domain": { - "name": "TokenERC721", - "version": "1", - "chainId": 84532, - "verifyingContract": "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4" - }, - "types": { - "MintRequest": [ - { "name": "to", "type": "address" }, - { "name": "royaltyRecipient", "type": "address" }, - { "name": "royaltyBps", "type": "uint256" }, - { - "name": "primarySaleRecipient", - "type": "address" - }, - { "name": "uri", "type": "string" }, - { "name": "price", "type": "uint256" }, - { "name": "currency", "type": "address" }, - { - "name": "validityStartTimestamp", - "type": "uint128" - }, - { - "name": "validityEndTimestamp", - "type": "uint128" - }, - { "name": "uid", "type": "bytes32" } - ] - }, - "message": { - "uri": "ipfs://test", - "currency": "0x0000000000000000000000000000000000000000", - "uid": "0xmyuid", - "to": "0x4Ff9aa707AE1eAeb40E581DF2cf4e14AffcC553d", - "royaltyRecipient": "0x4Ff9aa707AE1eAeb40E581DF2cf4e14AffcC553d", - "primarySaleRecipient": "0x4Ff9aa707AE1eAeb40E581DF2cf4e14AffcC553d" - }, - "primaryType": "MintRequest" - } - } - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc721/token/update": { - "post": { - "operationId": "updateTokenMetadata", - "summary": "Update token metadata", - "tags": ["ERC721"], - "description": "Update the metadata for an ERC721 token.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "Token ID to update metadata", - "type": "string" - }, - "metadata": { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "image": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The background color of the NFT" - } - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId", "metadata"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/get": { - "get": { - "operationId": "get", - "summary": "Get details", - "tags": ["ERC1155"], - "description": "Get the details for a token in an ERC-1155 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "0", - "in": "query", - "name": "tokenId", - "required": true, - "description": "The tokenId of the NFT to retrieve" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "metadata": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "owner": { "type": "string" }, - "type": { - "anyOf": [ - { "type": "string", "enum": ["ERC1155"] }, - { "type": "string", "enum": ["ERC721"] }, - { "type": "string", "enum": ["metaplex"] } - ] - }, - "supply": { "type": "string" }, - "quantityOwned": { "type": "string" } - }, - "required": ["metadata", "owner", "type", "supply"] - } - }, - "required": ["result"] - }, - "example": { - "result": { - "metadata": { - "id": "0", - "uri": "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - "name": "My Edition NFT", - "description": "My Edition NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "type": "ERC1155", - "supply": "100", - "quantityOwned": "100" - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all details", - "tags": ["ERC1155"], - "description": "Get details for all tokens in an ERC-1155 contract.", - "parameters": [ - { - "schema": { "type": "number" }, - "example": "0", - "in": "query", - "name": "start", - "required": false, - "description": "The start token ID for paginated results. Defaults to 0." - }, - { - "schema": { "type": "number" }, - "example": "20", - "in": "query", - "name": "count", - "required": false, - "description": "The page count for paginated results. Defaults to 100." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "metadata": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "owner": { "type": "string" }, - "type": { - "anyOf": [ - { "type": "string", "enum": ["ERC1155"] }, - { "type": "string", "enum": ["ERC721"] }, - { "type": "string", "enum": ["metaplex"] } - ] - }, - "supply": { "type": "string" }, - "quantityOwned": { "type": "string" } - }, - "required": ["metadata", "owner", "type", "supply"] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "metadata": { - "id": "0", - "uri": "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - "name": "My Edition NFT", - "description": "My Edition NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "type": "ERC1155", - "supply": "100", - "quantityOwned": "100" - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/get-owned": { - "get": { - "operationId": "getOwned", - "summary": "Get owned tokens", - "tags": ["ERC1155"], - "description": "Get all tokens in an ERC-1155 contract owned by a specific wallet.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "Address of the wallet to get NFTs for" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "metadata": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "owner": { "type": "string" }, - "type": { - "anyOf": [ - { "type": "string", "enum": ["ERC1155"] }, - { "type": "string", "enum": ["ERC721"] }, - { "type": "string", "enum": ["metaplex"] } - ] - }, - "supply": { "type": "string" }, - "quantityOwned": { "type": "string" } - }, - "required": ["metadata", "owner", "type", "supply"] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "metadata": { - "id": "0", - "uri": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [{ "trait_type": "Mode", "value": "GOD" }] - }, - "owner": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "type": "ERC1155", - "supply": "600000150000000000000000000000000000000000009000000000000000000000712", - "quantityOwned": "9000000000000000000000000" - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/balance-of": { - "get": { - "operationId": "balanceOf", - "summary": "Get balance", - "tags": ["ERC1155"], - "description": "Get the balance of a specific wallet address for this ERC-1155 contract.", - "parameters": [ - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "Address of the wallet to check NFT balance" - }, - { - "schema": { "type": "string" }, - "example": "0", - "in": "query", - "name": "tokenId", - "required": true, - "description": "The tokenId of the NFT to check balance of" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } } - }, - "example": { "result": "1" } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/is-approved": { - "get": { - "operationId": "isApproved", - "summary": "Check if approved transfers", - "tags": ["ERC1155"], - "description": "Check if the specific wallet has approved transfers from a specific operator wallet.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "in": "query", - "name": "ownerWallet", - "required": true, - "description": "Address of the wallet who owns the NFT" - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "operator", - "required": true, - "description": "Address of the operator to check approval on" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } } - }, - "example": { "result": true } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/total-count": { - "get": { - "operationId": "totalCount", - "summary": "Get total supply", - "tags": ["ERC1155"], - "description": "Get the total supply in circulation for this ERC-1155 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "example": { "result": "1" } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/total-supply": { - "get": { - "operationId": "totalSupply", - "summary": "Get total supply", - "tags": ["ERC1155"], - "description": "Get the total supply in circulation for this ERC-1155 contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "0", - "in": "query", - "name": "tokenId", - "required": true, - "description": "The tokenId of the NFT to retrieve" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "example": [{ "result": "100000000" }] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/signature/generate": { - "post": { - "operationId": "signatureGenerate", - "summary": "Generate signature", - "tags": ["ERC1155"], - "description": "Generate a signature granting access for another wallet to mint tokens from this ERC-1155 contract. This method is typically called by the token contract owner.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "anyOf": [ - { - "type": "object", - "properties": { - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - "type": "string" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - "type": "number" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "type": "string" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "type": "string" - }, - "mintStartTime": { - "anyOf": [ - { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "string" - }, - { "type": "number" } - ] - }, - "mintEndTime": { - "anyOf": [ - { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "string" - }, - { "type": "number" } - ] - } - }, - "required": ["to", "quantity", "metadata"], - "examples": [ - { - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "quantity": "1", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "mintStartTime": "2023-06-07T21:51:33.386Z", - "mintEndTime": "2023-07-07T21:51:33.386Z" - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "contractType": { - "anyOf": [ - { "type": "string", "enum": ["TokenERC1155"] }, - { - "type": "string", - "enum": ["SignatureMintERC1155"] - } - ] - }, - "to": { "type": "string" }, - "quantity": { "type": "string" }, - "royaltyRecipient": { "type": "string" }, - "royaltyBps": { "type": "number" }, - "primarySaleRecipient": { "type": "string" }, - "pricePerToken": { "type": "string" }, - "pricePerTokenWei": { "type": "string" }, - "currency": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": ["to", "quantity", "validityStartTimestamp"] - }, - { - "anyOf": [ - { - "type": "object", - "properties": { - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "type": "string" - }, - "description": { - "description": "The description of the NFT", - "type": "string" - }, - "image": { - "description": "The image of the NFT", - "type": "string" - }, - "animation_url": { - "description": "The animation url of the NFT", - "type": "string" - }, - "external_url": { - "description": "The external url of the NFT", - "type": "string" - }, - "background_color": { - "description": "The background color of the NFT", - "type": "string" - }, - "properties": { - "description": "(not recommended - use \"attributes\") The properties of the NFT." - }, - "attributes": { - "description": "Arbitrary metadata for this item.", - "type": "array", - "items": { - "type": "object", - "properties": { - "trait_type": { "type": "string" }, - "value": { "type": "string" } - }, - "required": ["trait_type", "value"] - } - } - } - }, - { "type": "string" } - ] - } - }, - "required": ["metadata"] - }, - { - "type": "object", - "properties": { "tokenId": { "type": "string" } }, - "required": ["tokenId"] - } - ] - } - ] - } - ] - } - } - } - }, - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": false, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-thirdweb-sdk-version", - "required": false, - "description": "Override the thirdweb sdk version used. Example: \"5\" for v5 SDK compatibility." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "tokenId": { "type": "string" }, - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "default": "0", - "type": "string" - }, - "mintStartTime": { - "description": "The time from which the signature can be used to mint tokens. Defaults to now if value not provided.", - "type": "number" - }, - "mintEndTime": { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "number" - } - }, - "required": [ - "uri", - "tokenId", - "to", - "royaltyRecipient", - "quantity", - "royaltyBps", - "primarySaleRecipient", - "uid", - "metadata", - "currencyAddress", - "price", - "mintStartTime", - "mintEndTime" - ], - "examples": [ - { - "payload": { - "uri": "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - "tokenId": "115792089237316195423570985008687907853269984665640564039457584007913129639935", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "royaltyRecipient": "0x0000000000000000000000000000000000000000", - "quantity": "1", - "royaltyBps": "0", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3462396330333131353033363433336439343162303033363933373333396232", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686174693, - "mintEndTime": 1688766693 - }, - "signature": "0x674414eb46d1be3fb8f703b51049aa857b27c70c72293f054ed211be0efb843841bcd86b1245c321b20e50e2a9bebb555e70246d84778d5e76668db2f102c6401b" - } - ] - }, - "signature": { "type": "string" } - }, - "required": ["payload", "signature"] - }, - { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "to": { "type": "string" }, - "royaltyRecipient": { "type": "string" }, - "royaltyBps": { "type": "string" }, - "primarySaleRecipient": { "type": "string" }, - "tokenId": { "type": "string" }, - "uri": { "type": "string" }, - "quantity": { "type": "string" }, - "pricePerToken": { "type": "string" }, - "currency": { "type": "string" }, - "validityStartTimestamp": { "type": "integer" }, - "validityEndTimestamp": { "type": "integer" }, - "uid": { "type": "string" } - }, - "required": [ - "to", - "royaltyRecipient", - "royaltyBps", - "primarySaleRecipient", - "tokenId", - "uri", - "quantity", - "pricePerToken", - "currency", - "validityStartTimestamp", - "validityEndTimestamp", - "uid" - ] - }, - "signature": { "type": "string" } - }, - "required": ["payload", "signature"] - } - ] - } - }, - "required": ["result"], - "example": { "result": "1" } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/can-claim": { - "get": { - "operationId": "canClaim", - "summary": "Check if tokens are available for claiming", - "tags": ["ERC1155"], - "description": "Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "quantity", - "required": true, - "description": "The amount of tokens to claim." - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": true, - "description": "The token ID of the NFT you want to claim." - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "addressToCheck", - "required": false, - "description": "The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-active": { - "get": { - "operationId": "getActiveClaimConditions", - "summary": "Get currently active claim phase for a specific token ID.", - "tags": ["ERC1155"], - "description": "Retrieve the currently active claim phase for a specific token ID, if any.", - "parameters": [ - { - "schema": { "anyOf": [{ "type": "string" }, { "type": "number" }] }, - "in": "query", - "name": "tokenId", - "required": true, - "description": "The token ID of the NFT you want to claim." - }, - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "withAllowList", - "required": false, - "description": "Provide a boolean value to include the allowlist in the response." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "format": "date-time", - "type": "string" - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "availableSupply": { "type": "string" }, - "currentMintSupply": { "type": "string" }, - "currencyMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "null" }, - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - } - ] - } - }, - "required": [ - "startTime", - "merkleRootHash", - "availableSupply", - "currentMintSupply", - "currencyMetadata" - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-all": { - "get": { - "operationId": "getAllClaimConditions", - "summary": "Get all the claim phases configured for a specific token ID.", - "tags": ["ERC1155"], - "description": "Get all the claim phases configured for a specific token ID.", - "parameters": [ - { - "schema": { "anyOf": [{ "type": "string" }, { "type": "number" }] }, - "in": "query", - "name": "tokenId", - "required": true, - "description": "The token ID of the NFT you want to get the claim conditions for." - }, - { - "schema": { "type": "boolean" }, - "in": "query", - "name": "withAllowList", - "required": false, - "description": "Provide a boolean value to include the allowlist in the response." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "startTime": { - "format": "date-time", - "type": "string" - }, - "price": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "waitInSeconds": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "availableSupply": { "type": "string" }, - "currentMintSupply": { "type": "string" }, - "currencyMetadata": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "null" }, - { - "type": "array", - "items": { "type": "string" } - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - } - ] - } - }, - "required": [ - "startTime", - "merkleRootHash", - "availableSupply", - "currentMintSupply", - "currencyMetadata" - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-claimer-proofs": { - "get": { - "operationId": "getClaimerProofs", - "summary": "Get claimer proofs", - "tags": ["ERC1155"], - "description": "Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address.", - "parameters": [ - { - "schema": { "anyOf": [{ "type": "string" }, { "type": "number" }] }, - "in": "query", - "name": "tokenId", - "required": true, - "description": "The token ID of the NFT you want to get the claimer proofs for." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "The wallet address to get the merkle proofs for." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "anyOf": [ - { "type": "null" }, - { - "type": "object", - "properties": { - "price": { "type": "string" }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { "type": "string" }, - "proof": { - "type": "array", - "items": { "type": "string" } - } - }, - "required": ["address", "maxClaimable", "proof"] - } - ] - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-claim-ineligibility-reasons": { - "post": { - "operationId": "getClaimIneligibilityReasons", - "summary": "Get claim ineligibility reasons", - "tags": ["ERC1155"], - "description": "Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any.", - "parameters": [ - { - "schema": { "anyOf": [{ "type": "string" }, { "type": "number" }] }, - "in": "query", - "name": "tokenId", - "required": true, - "description": "The token ID of the NFT you want to check if the wallet address can claim." - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "quantity", - "required": true, - "description": "The amount of tokens to claim." - }, - { - "schema": { "type": "string" }, - "example": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "in": "query", - "name": "addressToCheck", - "required": false, - "description": "The wallet address to check if it can claim tokens." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "anyOf": [ - { "type": "string" }, - { - "anyOf": [ - { - "type": "string", - "enum": ["There is not enough supply to claim."] - }, - { - "type": "string", - "enum": [ - "This address is not on the allowlist." - ] - }, - { - "type": "string", - "enum": [ - "Not enough time since last claim transaction. Please wait." - ] - }, - { - "type": "string", - "enum": ["Claim phase has not started yet."] - }, - { - "type": "string", - "enum": ["You have already claimed the token."] - }, - { - "type": "string", - "enum": ["Incorrect price or currency."] - }, - { - "type": "string", - "enum": [ - "Cannot claim more than maximum allowed quantity." - ] - }, - { - "type": "string", - "enum": [ - "There are not enough tokens in the wallet to pay for the claim." - ] - }, - { - "type": "string", - "enum": [ - "There is no active claim phase at the moment. Please check back in later." - ] - }, - { - "type": "string", - "enum": ["There is no claim condition set."] - }, - { - "type": "string", - "enum": ["No wallet connected."] - }, - { - "type": "string", - "enum": ["No claim conditions found."] - } - ] - } - ] - } - } - }, - "required": ["result"] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/airdrop": { - "post": { - "operationId": "airdrop", - "summary": "Airdrop tokens", - "tags": ["ERC1155"], - "description": "Airdrop ERC-1155 tokens to specific wallets.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "Token ID of the NFT to airdrop", - "type": "string" - }, - "addresses": { - "description": "Addresses and quantities to airdrop to", - "type": "array", - "items": { - "type": "object", - "properties": { - "address": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "quantity": { "default": "1", "type": "string" } - }, - "required": ["address", "quantity"] - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId", "addresses"] - }, - "example": { - "tokenId": "0", - "addresses": [ - { - "address": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "quantity": "1" - }, - { - "address": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "quantity": "1" - } - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/burn": { - "post": { - "operationId": "burn", - "summary": "Burn token", - "tags": ["ERC1155"], - "description": "Burn ERC-1155 tokens in the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "The token ID to burn", - "type": "string" - }, - "amount": { - "description": "The amount of tokens to burn", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId", "amount"] - }, - "example": { "tokenId": "0", "amount": "1" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/burn-batch": { - "post": { - "operationId": "burnBatch", - "summary": "Burn tokens (batch)", - "tags": ["ERC1155"], - "description": "Burn a batch of ERC-1155 tokens in the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenIds": { - "type": "array", - "items": { - "description": "The token IDs to burn", - "type": "string" - } - }, - "amounts": { - "type": "array", - "items": { - "description": "The amounts of tokens to burn", - "type": "string" - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenIds", "amounts"] - }, - "example": { "tokenIds": ["0", "1"], "amounts": ["1", "1"] } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-to": { - "post": { - "operationId": "claimTo", - "summary": "Claim tokens to wallet", - "tags": ["ERC1155"], - "description": "Claim ERC-1155 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to claim the NFT to", - "type": "string" - }, - "tokenId": { - "description": "Token ID of the NFT to claim", - "type": "string" - }, - "quantity": { - "description": "Quantity of NFTs to mint", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "tokenId", "quantity"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "0", - "quantity": "1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/lazy-mint": { - "post": { - "operationId": "lazyMint", - "summary": "Lazy mint", - "tags": ["ERC1155"], - "description": "Lazy mint ERC-1155 tokens to be claimed in the future.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "metadatas": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["metadatas"] - }, - "example": { - "metadatas": [ - { - "name": "My NFT #1", - "description": "My NFT #1 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - { - "name": "My NFT #2", - "description": "My NFT #2 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - } - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/mint-additional-supply-to": { - "post": { - "operationId": "mintAdditionalSupplyTo", - "summary": "Mint additional supply", - "tags": ["ERC1155"], - "description": "Mint additional supply of ERC-1155 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to mint the NFT to", - "type": "string" - }, - "tokenId": { - "description": "Token ID to mint additional supply to", - "type": "string" - }, - "additionalSupply": { - "description": "The amount of supply to mint", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "tokenId", "additionalSupply"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "1", - "additionalSupply": "10" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/mint-batch-to": { - "post": { - "operationId": "mintBatchTo", - "summary": "Mint tokens (batch)", - "tags": ["ERC1155"], - "description": "Mint ERC-1155 tokens to multiple wallets in one transaction.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to mint the NFT to", - "type": "string" - }, - "metadataWithSupply": { - "type": "array", - "items": { - "type": "object", - "properties": { - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "supply": { "type": "string" } - }, - "required": ["metadata", "supply"] - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "metadataWithSupply"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "metadataWithSupply": [ - { - "metadata": { - "name": "My NFT #1", - "description": "My NFT #1 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "supply": "10" - }, - { - "metadata": { - "name": "My NFT #2", - "description": "My NFT #2 description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "supply": "5" - } - ] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/mint-to": { - "post": { - "operationId": "mintTo", - "summary": "Mint tokens", - "tags": ["ERC1155"], - "description": "Mint ERC-1155 tokens to a specific wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "receiver": { - "description": "Address of the wallet to mint the NFT to", - "type": "string" - }, - "metadataWithSupply": { - "type": "object", - "properties": { - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "supply": { "type": "string" } - }, - "required": ["metadata", "supply"] - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["receiver", "metadataWithSupply"] - }, - "example": { - "receiver": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "metadataWithSupply": { - "metadata": { - "name": "My NFT", - "description": "My NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "supply": "100" - } - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/set-approval-for-all": { - "post": { - "operationId": "setApprovalForAll", - "summary": "Set approval for all", - "tags": ["ERC1155"], - "description": "Approve or remove operator as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "operator": { - "description": "Address of the operator to give approval to", - "type": "string" - }, - "approved": { - "description": "whether to approve or revoke approval", - "type": "boolean" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["operator", "approved"] - }, - "example": { - "operator": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "approved": "true" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/transfer": { - "post": { - "operationId": "transfer", - "summary": "Transfer token", - "tags": ["ERC1155"], - "description": "Transfer an ERC-1155 token from the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "to": { - "description": "Address of the wallet to transfer to", - "type": "string" - }, - "tokenId": { - "description": "the tokenId to transfer", - "type": "string" - }, - "amount": { - "description": "the amount of tokens to transfer", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["to", "tokenId", "amount"] - }, - "example": { - "to": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "0", - "amount": "1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/transfer-from": { - "post": { - "operationId": "transferFrom", - "summary": "Transfer token from wallet", - "tags": ["ERC1155"], - "description": "Transfer an ERC-1155 token from the connected wallet to another wallet. Requires allowance.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "from": { - "description": "Address of the token owner", - "type": "string" - }, - "to": { - "description": "Address of the wallet to transferFrom to", - "type": "string" - }, - "tokenId": { - "description": "the tokenId to transferFrom", - "type": "string" - }, - "amount": { - "description": "the amount of tokens to transfer", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["from", "to", "tokenId", "amount"] - }, - "example": { - "from": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "to": "0x3EcDBF3B911d0e9052b64850693888b008e18373", - "tokenId": "0", - "amount": "1" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "ERC1155 contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/signature/mint": { - "post": { - "operationId": "signatureMint", - "summary": "Signature mint", - "tags": ["ERC1155"], - "description": "Mint ERC-1155 tokens from a generated signature.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "payload": { - "type": "object", - "properties": { - "uri": { "type": "string" }, - "tokenId": { "type": "string" }, - "to": { - "description": "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - "type": "string" - }, - "royaltyRecipient": { - "description": "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens this signature can be used to mint.", - "type": "string" - }, - "royaltyBps": { - "description": "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - "type": "string" - }, - "primarySaleRecipient": { - "description": "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - "type": "string" - }, - "uid": { - "description": "A unique identifier for the payload, used to prevent replay attacks and other types of exploits.\n Note that the input value gets hashed in the actual payload that gets generated. \n The smart contract enforces on-chain that no uid gets used more than once, \n which means you can deterministically generate the uid to prevent specific exploits.", - "type": "string" - }, - "metadata": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ], - "description": "The background color of the NFT" - } - } - }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "price": { - "description": "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - "default": "0", - "type": "string" - }, - "mintStartTime": { - "description": "The time from which the signature can be used to mint tokens. Defaults to now if value not provided.", - "type": "number" - }, - "mintEndTime": { - "description": "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - "type": "number" - } - }, - "required": [ - "uri", - "tokenId", - "to", - "royaltyRecipient", - "quantity", - "royaltyBps", - "primarySaleRecipient", - "uid", - "metadata", - "currencyAddress", - "price", - "mintStartTime", - "mintEndTime" - ], - "example": { - "payload": { - "uri": "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - "tokenId": "115792089237316195423570985008687907853269984665640564039457584007913129639935", - "to": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "royaltyRecipient": "0x0000000000000000000000000000000000000000", - "quantity": "1", - "royaltyBps": "0", - "primarySaleRecipient": "0x0000000000000000000000000000000000000000", - "uid": "0x3462396330333131353033363433336439343162303033363933373333396232", - "metadata": { - "name": "test tokenII", - "description": "test token" - }, - "currencyAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "price": "0", - "mintStartTime": 1686174693, - "mintEndTime": 1688766693 - }, - "signature": "0x674414eb46d1be3fb8f703b51049aa857b27c70c72293f054ed211be0efb843841bcd86b1245c321b20e50e2a9bebb555e70246d84778d5e76668db2f102c6401b" - } - }, - "signature": { "type": "string" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["payload", "signature"] - }, - "example": { "payload": {}, "signature": "" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/set": { - "post": { - "operationId": "setClaimConditions", - "summary": "Overwrite the claim conditions for a specific token ID..", - "tags": ["ERC1155"], - "description": "Overwrite the claim conditions for a specific token ID. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "ID of the token to set the claim conditions for", - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "claimConditionInputs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - } - }, - "resetClaimEligibilityForAll": { "type": "boolean" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId", "claimConditionInputs"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/set-batch": { - "post": { - "operationId": "claimConditionsUpdate", - "summary": "Overwrite the claim conditions for a specific token ID..", - "tags": ["ERC1155"], - "description": "Allows you to set claim conditions for multiple token IDs in a single transaction.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "claimConditionsForToken": { - "type": "array", - "items": { - "type": "object", - "properties": { - "tokenId": { - "description": "ID of the token to set the claim conditions for", - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "claimConditions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "waitInSeconds": { - "anyOf": [ - { "type": "number" }, - { "type": "string" } - ] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { - "type": "array", - "items": { "type": "number" } - } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { - "type": "array", - "items": { "type": "string" } - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - } - } - }, - "required": ["tokenId", "claimConditions"] - } - }, - "resetClaimEligibilityForAll": { "type": "boolean" }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["claimConditionsForToken"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/claim-conditions/update": { - "post": { - "operationId": "updateClaimConditions", - "summary": "Update a single claim phase.", - "tags": ["ERC1155"], - "description": "Update a single claim phase on a specific token ID, by providing the index of the claim phase and the new phase configuration.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "Token ID to update claim phase for", - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "claimConditionInput": { - "type": "object", - "properties": { - "maxClaimableSupply": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "startTime": { - "anyOf": [ - { "format": "date-time", "type": "string" }, - { "type": "number" } - ] - }, - "price": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "maxClaimablePerWallet": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "waitInSeconds": { - "anyOf": [{ "type": "number" }, { "type": "string" }] - }, - "merkleRootHash": { - "anyOf": [ - { "type": "string" }, - { "type": "array", "items": { "type": "number" } } - ] - }, - "metadata": { - "type": "object", - "properties": { "name": { "type": "string" } } - }, - "snapshot": { - "anyOf": [ - { "type": "array", "items": { "type": "string" } }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "price": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - }, - "currencyAddress": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "address": { - "description": "A contract or wallet address", - "examples": [ - "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - ], - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$" - }, - "maxClaimable": { - "anyOf": [ - { "type": "string" }, - { "type": "number" } - ] - } - }, - "required": ["address"] - } - }, - { "type": "null" } - ] - } - } - }, - "index": { - "description": "Index of the claim condition to update", - "type": "number" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId", "claimConditionInput", "index"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/erc1155/token/update": { - "post": { - "operationId": "updateTokenMetadata", - "summary": "Update token metadata", - "tags": ["ERC1155"], - "description": "Update the metadata for an ERC1155 token.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "tokenId": { - "description": "Token ID to update metadata", - "type": "string" - }, - "metadata": { - "type": "object", - "properties": { - "name": { - "description": "The name of the NFT", - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "description": "The description of the NFT", - "anyOf": [{ "type": "string" }, { "type": "null" }] - }, - "image": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The image of the NFT" - }, - "external_url": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The external url of the NFT" - }, - "animation_url": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The animation url of the NFT" - }, - "properties": { - "description": "The properties of the NFT" - }, - "attributes": { - "description": "The attributes of the NFT" - }, - "background_color": { - "anyOf": [{ "type": "string" }, { "type": "null" }], - "description": "The background color of the NFT" - } - } - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["tokenId", "metadata"] - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all listings", - "tags": ["Marketplace-DirectListings"], - "description": "Get all direct listings for this marketplace contract.", - "parameters": [ - { - "schema": { "type": "number" }, - "in": "query", - "name": "count", - "required": false, - "description": "Number of listings to fetch" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "seller", - "required": false, - "description": "Being sold by this Address" - }, - { - "schema": { "type": "number" }, - "in": "query", - "name": "start", - "required": false, - "description": "Satrt from this index (pagination)" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenContract", - "required": false, - "description": "Token contract address to show NFTs from" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": false, - "description": "Only show NFTs with this ID" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "pricePerToken": { - "description": "The price to pay per unit of NFTs listed.", - "type": "string" - }, - "isReservedListing": { - "description": "Whether the listing is reserved to be bought from a specific set of buyers.", - "type": "boolean" - }, - "id": { - "description": "The listing ID.", - "type": "string" - }, - "currencyValuePerToken": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - }, - "startTimeInSeconds": { - "description": "The start time of the listing. If not set, defaults to now.", - "type": "number" - }, - "endTimeInSeconds": { - "description": "The end time of the listing. If not set, defaults to 7 days from now.", - "type": "number" - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "pricePerToken", - "id" - ] - } - } - }, - "required": ["result"], - "example": [ - { - "result": [ - { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "currencyContractAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "quantity": "1", - "pricePerToken": "10000000000", - "isReservedListing": false, - "id": "0", - "currencyValuePerToken": { - "name": "MATIC", - "symbol": "MATIC", - "decimals": 18, - "value": "10000000000", - "displayValue": "0.00000001" - }, - "asset": { - "id": "0", - "uri": "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [ - { "trait_type": "Mode", "value": "GOD" } - ] - }, - "status": 1, - "startTimeInSeconds": 1686006043, - "endTimeInSeconds": 1686610889 - } - ] - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/get-all-valid": { - "get": { - "operationId": "getAllValid", - "summary": "Get all valid listings", - "tags": ["Marketplace-DirectListings"], - "description": "Get all the valid direct listings for this marketplace contract. A valid listing is where the listing is active, and the creator still owns & has approved Marketplace to transfer the listed NFTs.", - "parameters": [ - { - "schema": { "type": "number" }, - "in": "query", - "name": "count", - "required": false, - "description": "Number of listings to fetch" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "seller", - "required": false, - "description": "Being sold by this Address" - }, - { - "schema": { "type": "number" }, - "in": "query", - "name": "start", - "required": false, - "description": "Satrt from this index (pagination)" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenContract", - "required": false, - "description": "Token contract address to show NFTs from" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": false, - "description": "Only show NFTs with this ID" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "pricePerToken": { - "description": "The price to pay per unit of NFTs listed.", - "type": "string" - }, - "isReservedListing": { - "description": "Whether the listing is reserved to be bought from a specific set of buyers.", - "type": "boolean" - }, - "id": { - "description": "The listing ID.", - "type": "string" - }, - "currencyValuePerToken": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - }, - "startTimeInSeconds": { - "description": "The start time of the listing. If not set, defaults to now.", - "type": "number" - }, - "endTimeInSeconds": { - "description": "The end time of the listing. If not set, defaults to 7 days from now.", - "type": "number" - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "pricePerToken", - "id" - ] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "currencyContractAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "quantity": "1", - "pricePerToken": "10000000000", - "isReservedListing": false, - "id": "0", - "currencyValuePerToken": { - "name": "MATIC", - "symbol": "MATIC", - "decimals": 18, - "value": "10000000000", - "displayValue": "0.00000001" - }, - "asset": { - "id": "0", - "uri": "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [{ "trait_type": "Mode", "value": "GOD" }] - }, - "status": 1, - "startTimeInSeconds": 1686006043, - "endTimeInSeconds": 1686610889 - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/get-listing": { - "get": { - "operationId": "getListing", - "summary": "Get direct listing", - "tags": ["Marketplace-DirectListings"], - "description": "Gets a direct listing on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The id of the listing to retrieve." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "pricePerToken": { - "description": "The price to pay per unit of NFTs listed.", - "type": "string" - }, - "isReservedListing": { - "description": "Whether the listing is reserved to be bought from a specific set of buyers.", - "type": "boolean" - }, - "id": { - "description": "The listing ID.", - "type": "string" - }, - "currencyValuePerToken": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - }, - "startTimeInSeconds": { - "description": "The start time of the listing. If not set, defaults to now.", - "type": "number" - }, - "endTimeInSeconds": { - "description": "The end time of the listing. If not set, defaults to 7 days from now.", - "type": "number" - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "pricePerToken", - "id" - ] - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "metadata": { - "id": "0", - "uri": "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - "name": "My Edition NFT", - "description": "My Edition NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "type": "ERC1155", - "supply": "100", - "quantityOwned": "100" - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/is-buyer-approved-for-listing": { - "get": { - "operationId": "isBuyerApprovedForListing", - "summary": "Check approved buyer", - "tags": ["Marketplace-DirectListings"], - "description": "Check if a buyer is approved to purchase a specific direct listing.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The id of the listing to retrieve." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "walletAddress", - "required": true, - "description": "The wallet address of the buyer to check." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "required": ["result"] - }, - "example": { "result": true } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/is-currency-approved-for-listing": { - "get": { - "operationId": "isCurrencyApprovedForListing", - "summary": "Check approved currency", - "tags": ["Marketplace-DirectListings"], - "description": "Check if a currency is approved for a specific direct listing.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The id of the listing to retrieve." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "query", - "name": "currencyContractAddress", - "required": true, - "description": "The smart contract address of the ERC20 token to check." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "required": ["result"] - }, - "example": { "result": true } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/get-total-count": { - "get": { - "operationId": "getTotalCount", - "summary": "Transfer token from wallet", - "tags": ["Marketplace-DirectListings"], - "description": "Get the total number of direct listings on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - }, - "example": { "result": "1" } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all English auctions", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get all English auction listings on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "number" }, - "in": "query", - "name": "count", - "required": false, - "description": "Number of listings to fetch" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "seller", - "required": false, - "description": "Being sold by this Address" - }, - { - "schema": { "type": "number" }, - "in": "query", - "name": "start", - "required": false, - "description": "Satrt from this index (pagination)" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenContract", - "required": false, - "description": "Token contract address to show NFTs from" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": false, - "description": "Only show NFTs with this ID" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "id": { - "description": "The listing ID.", - "type": "string" - }, - "minimumBidAmount": { - "description": "The minimum price that a bid must be in order to be accepted.", - "type": "string" - }, - "buyoutBidAmount": { - "description": "The buyout price of the auction.", - "type": "string" - }, - "buyoutCurrencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "timeBufferInSeconds": { - "description": "This is a buffer e.g. x seconds.", - "type": "number" - }, - "bidBufferBps": { - "description": "To be considered as a new winning bid, a bid must be at least x% greater than the previous bid.", - "type": "number" - }, - "startTimeInSeconds": { - "description": "The start time of the auction.", - "type": "number" - }, - "endTimeInSeconds": { - "description": "The end time of the auction.", - "type": "number" - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "id", - "buyoutBidAmount", - "buyoutCurrencyValue", - "timeBufferInSeconds", - "bidBufferBps", - "startTimeInSeconds", - "endTimeInSeconds" - ] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "currencyContractAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "quantity": "1", - "id": "0", - "minimumBidAmount": "10000000000", - "buyoutBidAmount": "10000000000", - "buyoutCurrencyValue": { - "name": "MATIC", - "symbol": "MATIC", - "decimals": 18, - "value": "10000000000", - "displayValue": "0.00000001" - }, - "timeBufferInSeconds": 600, - "bidBufferBps": 100, - "startTimeInSeconds": 1686006043, - "endTimeInSeconds": 1686610889, - "asset": { - "id": "0", - "uri": "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [{ "trait_type": "Mode", "value": "GOD" }] - }, - "status": 1 - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-all-valid": { - "get": { - "operationId": "getAllValid", - "summary": "Get all valid English auctions", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get all valid English auction listings on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "number" }, - "in": "query", - "name": "count", - "required": false, - "description": "Number of listings to fetch" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "seller", - "required": false, - "description": "Being sold by this Address" - }, - { - "schema": { "type": "number" }, - "in": "query", - "name": "start", - "required": false, - "description": "Satrt from this index (pagination)" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenContract", - "required": false, - "description": "Token contract address to show NFTs from" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": false, - "description": "Only show NFTs with this ID" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "id": { - "description": "The listing ID.", - "type": "string" - }, - "minimumBidAmount": { - "description": "The minimum price that a bid must be in order to be accepted.", - "type": "string" - }, - "buyoutBidAmount": { - "description": "The buyout price of the auction.", - "type": "string" - }, - "buyoutCurrencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "timeBufferInSeconds": { - "description": "This is a buffer e.g. x seconds.", - "type": "number" - }, - "bidBufferBps": { - "description": "To be considered as a new winning bid, a bid must be at least x% greater than the previous bid.", - "type": "number" - }, - "startTimeInSeconds": { - "description": "The start time of the auction.", - "type": "number" - }, - "endTimeInSeconds": { - "description": "The end time of the auction.", - "type": "number" - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "id", - "buyoutBidAmount", - "buyoutCurrencyValue", - "timeBufferInSeconds", - "bidBufferBps", - "startTimeInSeconds", - "endTimeInSeconds" - ] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "currencyContractAddress": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "quantity": "1", - "id": "0", - "minimumBidAmount": "10000000000", - "buyoutBidAmount": "10000000000", - "buyoutCurrencyValue": { - "name": "MATIC", - "symbol": "MATIC", - "decimals": 18, - "value": "10000000000", - "displayValue": "0.00000001" - }, - "timeBufferInSeconds": 600, - "bidBufferBps": 100, - "startTimeInSeconds": 1686006043, - "endTimeInSeconds": 1686610889, - "asset": { - "id": "0", - "uri": "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [{ "trait_type": "Mode", "value": "GOD" }] - }, - "status": 1 - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-auction": { - "get": { - "operationId": "getAuction", - "summary": "Get English auction", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get a specific English auction listing on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The id of the listing to retrieve." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "id": { - "description": "The listing ID.", - "type": "string" - }, - "minimumBidAmount": { - "description": "The minimum price that a bid must be in order to be accepted.", - "type": "string" - }, - "buyoutBidAmount": { - "description": "The buyout price of the auction.", - "type": "string" - }, - "buyoutCurrencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "timeBufferInSeconds": { - "description": "This is a buffer e.g. x seconds.", - "type": "number" - }, - "bidBufferBps": { - "description": "To be considered as a new winning bid, a bid must be at least x% greater than the previous bid.", - "type": "number" - }, - "startTimeInSeconds": { - "description": "The start time of the auction.", - "type": "number" - }, - "endTimeInSeconds": { - "description": "The end time of the auction.", - "type": "number" - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "id", - "buyoutBidAmount", - "buyoutCurrencyValue", - "timeBufferInSeconds", - "bidBufferBps", - "startTimeInSeconds", - "endTimeInSeconds" - ] - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "metadata": { - "id": "0", - "uri": "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - "name": "My Edition NFT", - "description": "My Edition NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "type": "ERC1155", - "supply": "100", - "quantityOwned": "100" - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-bid-buffer-bps": { - "get": { - "operationId": "getBidBufferBps", - "summary": "Get bid buffer BPS", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get the basis points of the bid buffer. \nThis is the percentage higher that a new bid must be than the current highest bid in order to be placed. \nIf there is no current bid, the bid must be at least the minimum bid amount.\nReturns the value in percentage format, e.g. 100 = 1%.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The id of the listing to retrieve." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "description": "Returns a number representing the basis points of the bid buffer.", - "type": "number" - } - }, - "required": ["result"] - }, - "example": { "result": "1" } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-minimum-next-bid": { - "get": { - "operationId": "getMinimumNextBid", - "summary": "Get minimum next bid", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Helper function to calculate the value that the next bid must be in order to be accepted. \nIf there is no current bid, the bid must be at least the minimum bid amount.\nIf there is a current bid, the bid must be at least the current bid amount + the bid buffer.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The id of the listing to retrieve." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - } - }, - "required": ["result"] - }, - "example": { "result": "1" } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-winning-bid": { - "get": { - "operationId": "getWinningBid", - "summary": "Get winning bid", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get the current highest bid of an active auction.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The ID of the listing to retrieve the winner for." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "auctionId": { - "description": "The id of the auction.", - "type": "string" - }, - "bidderAddress": { - "description": "The address of the buyer who made the offer.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The currency contract address of the offer token.", - "type": "string" - }, - "bidAmount": { - "description": "The amount of coins offered per token.", - "type": "string" - }, - "bidAmountCurrencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - } - } - } - } - }, - "example": { "result": "0x..." } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-total-count": { - "get": { - "operationId": "getTotalCount", - "summary": "Get total listings", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get the count of English auction listings on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - }, - "example": { "result": "1" } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/is-winning-bid": { - "get": { - "operationId": "isWinningBid", - "summary": "Check winning bid", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Check if a bid is or will be the winning bid for an auction.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The ID of the listing to retrieve the winner for." - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "bidAmount", - "required": true, - "description": "The amount of the bid to check if it is the winning bid." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "boolean" } }, - "required": ["result"] - }, - "example": { "result": true } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/get-winner": { - "get": { - "operationId": "getWinner", - "summary": "Get winner", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Get the winner of an English auction. Can only be called after the auction has ended.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "listingId", - "required": true, - "description": "The ID of the listing to retrieve the winner for." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - }, - "example": { "result": "0x..." } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/get-all": { - "get": { - "operationId": "getAll", - "summary": "Get all offers", - "tags": ["Marketplace-Offers"], - "description": "Get all offers on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "number" }, - "in": "query", - "name": "count", - "required": false, - "description": "Number of listings to fetch" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "offeror", - "required": false, - "description": "has offers from this Address" - }, - { - "schema": { "type": "number" }, - "in": "query", - "name": "start", - "required": false, - "description": "Satrt from this index (pagination)" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenContract", - "required": false, - "description": "Token contract address to show NFTs from" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": false, - "description": "Only show NFTs with this ID" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "id": { - "description": "The id of the offer.", - "type": "string" - }, - "offerorAddress": { - "description": "The address of the creator of offer.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "currencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "totalPrice": { - "description": "The total offer amount for the NFTs.", - "type": "string" - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "endTimeInSeconds": { - "description": "The end time of the auction.", - "type": "number" - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "id", - "offerorAddress", - "totalPrice" - ] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "currencyContractAddress": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", - "quantity": "1", - "id": "0", - "offerorAddress": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "currencyValue": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "value": "10000000000", - "displayValue": "0.00000001" - }, - "totalPrice": "10000000000", - "asset": { - "id": "0", - "uri": "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [{ "trait_type": "Mode", "value": "GOD" }] - }, - "endTimeInSeconds": 1686610889, - "status": 4 - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/get-all-valid": { - "get": { - "operationId": "getAllValid", - "summary": "Get all valid offers", - "tags": ["Marketplace-Offers"], - "description": "Get all valid offers on this marketplace contract. Valid offers are offers that have not expired, been canceled, or been accepted.", - "parameters": [ - { - "schema": { "type": "number" }, - "in": "query", - "name": "count", - "required": false, - "description": "Number of listings to fetch" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "offeror", - "required": false, - "description": "has offers from this Address" - }, - { - "schema": { "type": "number" }, - "in": "query", - "name": "start", - "required": false, - "description": "Satrt from this index (pagination)" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenContract", - "required": false, - "description": "Token contract address to show NFTs from" - }, - { - "schema": { "type": "string" }, - "in": "query", - "name": "tokenId", - "required": false, - "description": "Only show NFTs with this ID" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "id": { - "description": "The id of the offer.", - "type": "string" - }, - "offerorAddress": { - "description": "The address of the creator of offer.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "currencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "totalPrice": { - "description": "The total offer amount for the NFTs.", - "type": "string" - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "endTimeInSeconds": { - "description": "The end time of the auction.", - "type": "number" - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "id", - "offerorAddress", - "totalPrice" - ] - } - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "currencyContractAddress": "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", - "quantity": "1", - "id": "0", - "offerorAddress": "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "currencyValue": { - "name": "Wrapped Matic", - "symbol": "WMATIC", - "decimals": 18, - "value": "10000000000", - "displayValue": "0.00000001" - }, - "totalPrice": "10000000000", - "asset": { - "id": "0", - "uri": "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - "name": "TJ-Origin", - "description": "Origin", - "external_url": "", - "attributes": [{ "trait_type": "Mode", "value": "GOD" }] - }, - "endTimeInSeconds": 1686610889, - "status": 4 - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/get-offer": { - "get": { - "operationId": "getOffer", - "summary": "Get offer", - "tags": ["Marketplace-Offers"], - "description": "Get details about an offer.", - "parameters": [ - { - "schema": { "type": "string" }, - "in": "query", - "name": "offerId", - "required": true, - "description": "The ID of the offer to get information about." - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "id": { - "description": "The id of the offer.", - "type": "string" - }, - "offerorAddress": { - "description": "The address of the creator of offer.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "currencyValue": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "symbol": { "type": "string" }, - "decimals": { "type": "number" }, - "value": { "type": "string" }, - "displayValue": { "type": "string" } - }, - "required": [ - "name", - "symbol", - "decimals", - "value", - "displayValue" - ], - "description": "The `CurrencyValue` of the listing. Useful for displaying the price information." - }, - "totalPrice": { - "description": "The total offer amount for the NFTs.", - "type": "string" - }, - "asset": { - "additionalProperties": true, - "type": "object", - "properties": { - "id": { "type": "string" }, - "uri": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "number" }, - { "type": "null" } - ] - }, - "description": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "image": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "external_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "animation_url": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "properties": {}, - "attributes": {} - }, - "required": ["id", "uri"] - }, - "endTimeInSeconds": { - "description": "The end time of the auction.", - "type": "number" - }, - "status": { - "anyOf": [ - { "type": "number", "enum": [0] }, - { "type": "number", "enum": [1] }, - { "type": "number", "enum": [2] }, - { "type": "number", "enum": [3] }, - { "type": "number", "enum": [4] }, - { "type": "number", "enum": [5] } - ] - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "id", - "offerorAddress", - "totalPrice" - ] - } - }, - "required": ["result"] - }, - "example": { - "result": [ - { - "metadata": { - "id": "0", - "uri": "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - "name": "My Edition NFT", - "description": "My Edition NFT description", - "image": "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png" - }, - "owner": "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - "type": "ERC1155", - "supply": "100", - "quantityOwned": "100" - } - ] - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/get-total-count": { - "get": { - "operationId": "getTotalCount", - "summary": "Get total count", - "tags": ["Marketplace-Offers"], - "description": "Get the total number of offers on this marketplace contract.", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { "result": { "type": "string" } }, - "required": ["result"] - }, - "example": { "result": "1" } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/create-listing": { - "post": { - "operationId": "createListing", - "summary": "Create direct listing", - "tags": ["Marketplace-DirectListings"], - "description": "Create a direct listing on this marketplace contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "pricePerToken": { - "description": "The price to pay per unit of NFTs listed.", - "type": "string" - }, - "isReservedListing": { - "description": "Whether the listing is reserved to be bought from a specific set of buyers.", - "type": "boolean" - }, - "startTimestamp": { - "description": "The start time of the listing. If not set, defaults to now.", - "type": "number" - }, - "endTimestamp": { - "description": "The end time of the listing. If not set, defaults to 7 days from now.", - "type": "number" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["assetContractAddress", "tokenId", "pricePerToken"] - }, - "example": { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "pricePerToken": "0.00000001", - "isReservedListing": false, - "quantity": "1", - "startTimestamp": 1686006043038, - "endTimestamp": 1686610889058 - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/update-listing": { - "post": { - "operationId": "updateListing", - "summary": "Update direct listing", - "tags": ["Marketplace-DirectListings"], - "description": "Update a direct listing on this marketplace contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing you want to update.", - "type": "string" - }, - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "pricePerToken": { - "description": "The price to pay per unit of NFTs listed.", - "type": "string" - }, - "isReservedListing": { - "description": "Whether the listing is reserved to be bought from a specific set of buyers.", - "type": "boolean" - }, - "startTimestamp": { - "description": "The start time of the listing. If not set, defaults to now.", - "type": "number" - }, - "endTimestamp": { - "description": "The end time of the listing. If not set, defaults to 7 days from now.", - "type": "number" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": [ - "listingId", - "assetContractAddress", - "tokenId", - "pricePerToken" - ] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/buy-from-listing": { - "post": { - "operationId": "buyFromListing", - "summary": "Buy from direct listing", - "tags": ["Marketplace-DirectListings"], - "description": "Buy from a specific direct listing from this marketplace contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing you want to approve a buyer for.", - "type": "string" - }, - "quantity": { - "description": "The number of tokens to buy (default is 1 for ERC721 NFTs).", - "type": "string" - }, - "buyer": { - "description": "The wallet address of the buyer.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["listingId", "quantity", "buyer"] - }, - "example": { - "listingId": "0", - "quantity": "1", - "buyer": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/approve-buyer-for-reserved-listing": { - "post": { - "operationId": "approveBuyerForReservedListing", - "summary": "Approve buyer for reserved listing", - "tags": ["Marketplace-DirectListings"], - "description": "Approve a wallet address to buy from a reserved listing.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing you want to approve a buyer for.", - "type": "string" - }, - "buyer": { - "description": "The wallet address of the buyer to approve.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["listingId", "buyer"] - }, - "example": { - "listingId": "0", - "buyer": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/revoke-buyer-approval-for-reserved-listing": { - "post": { - "operationId": "revokeBuyerApprovalForReservedListing", - "summary": "Revoke approval for reserved listings", - "tags": ["Marketplace-DirectListings"], - "description": "Revoke approval for a buyer to purchase a reserved listing.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing you want to approve a buyer for.", - "type": "string" - }, - "buyerAddress": { - "description": "The wallet address of the buyer to approve.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["listingId", "buyerAddress"] - }, - "example": { - "listingId": "0", - "buyerAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/revoke-currency-approval-for-listing": { - "post": { - "operationId": "revokeCurrencyApprovalForListing", - "summary": "Revoke currency approval for reserved listing", - "tags": ["Marketplace-DirectListings"], - "description": "Revoke approval of a currency for a reserved listing.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing you want to approve a buyer for.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The wallet address of the buyer to approve.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["listingId", "currencyContractAddress"] - }, - "example": { - "listingId": "0", - "currencyContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/direct-listings/cancel-listing": { - "post": { - "operationId": "cancelListing", - "summary": "Cancel direct listing", - "tags": ["Marketplace-DirectListings"], - "description": "Cancel a direct listing from this marketplace contract. Only the creator of the listing can cancel it.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing you want to cancel.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["listingId"] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/buyout-auction": { - "post": { - "operationId": "buyoutAuction", - "summary": "Buyout English auction", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Buyout the listing for this auction.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing to buy NFT(s) from.", - "type": "string" - } - }, - "required": ["listingId"] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/cancel-auction": { - "post": { - "operationId": "cancelAuction", - "summary": "Cancel English auction", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Cancel an existing auction listing. Only the creator of the listing can cancel it. Auctions cannot be canceled once a bid has been made.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing to cancel auction.", - "type": "string" - } - }, - "required": ["listingId"] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/create-auction": { - "post": { - "operationId": "createAuction", - "summary": "Create English auction", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Create an English auction listing on this marketplace contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "startTimestamp": { - "description": "The start time of the listing. If not set, defaults to now.", - "type": "number" - }, - "endTimestamp": { - "description": "The end time of the listing. If not set, defaults to 7 days from now.", - "type": "number" - }, - "buyoutBidAmount": { - "description": "amount to buy the NFT and close the listing.", - "type": "string" - }, - "minimumBidAmount": { - "description": "Minimum amount that bids must be to placed", - "type": "string" - }, - "bidBufferBps": { - "description": "percentage the next bid must be higher than the current highest bid (default is contract-level bid buffer bps)", - "type": "string" - }, - "timeBufferInSeconds": { - "description": "time in seconds that are added to the end time when a bid is placed (default is contract-level time buffer in seconds)", - "type": "string" - } - }, - "required": [ - "assetContractAddress", - "tokenId", - "buyoutBidAmount", - "minimumBidAmount" - ] - }, - "example": { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "quantity": "1", - "startTimestamp": 1686006043038, - "endTimestamp": 1686610889058, - "buyoutBidAmount": "0.00000001", - "minimumBidAmount": "0.00000001", - "currencyContractAddress": "0x...", - "bidBufferBps": 100, - "timeBufferInSeconds": 600 - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/close-auction-for-bidder": { - "post": { - "operationId": "closeAuctionForBidder", - "summary": "Close English auction for bidder", - "tags": ["Marketplace-EnglishAuctions"], - "description": "After an auction has concluded (and a buyout did not occur),\nexecute the sale for the buyer, meaning the buyer receives the NFT(s). \nYou must also call closeAuctionForSeller to execute the sale for the seller,\nmeaning the seller receives the payment from the highest bid.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing to execute the sale for.", - "type": "string" - } - }, - "required": ["listingId"] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/close-auction-for-seller": { - "post": { - "operationId": "closeAuctionForSeller", - "summary": "Close English auction for seller", - "tags": ["Marketplace-EnglishAuctions"], - "description": "After an auction has concluded (and a buyout did not occur),\nexecute the sale for the seller, meaning the seller receives the payment from the highest bid.\nYou must also call closeAuctionForBidder to execute the sale for the buyer, meaning the buyer receives the NFT(s).", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing to execute the sale for.", - "type": "string" - } - }, - "required": ["listingId"] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/execute-sale": { - "post": { - "operationId": "executeSale", - "summary": "Execute sale", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Close the auction for both buyer and seller.\nThis means the NFT(s) will be transferred to the buyer and the seller will receive the funds.\nThis function can only be called after the auction has ended.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing to execute the sale for.", - "type": "string" - } - }, - "required": ["listingId"] - }, - "example": { "listingId": "0" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/english-auctions/make-bid": { - "post": { - "operationId": "makeBid", - "summary": "Make bid", - "tags": ["Marketplace-EnglishAuctions"], - "description": "Place a bid on an English auction listing.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "listingId": { - "description": "The ID of the listing to place a bid on.", - "type": "string" - }, - "bidAmount": { - "description": "The amount of the bid to place in the currency of the listing. Use getNextBidAmount to get the minimum amount for the next bid.", - "type": "string" - } - }, - "required": ["listingId", "bidAmount"] - }, - "example": { "listingId": "0", "bidAmount": "0.00000001" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/make-offer": { - "post": { - "operationId": "makeOffer", - "summary": "Make offer", - "tags": ["Marketplace-Offers"], - "description": "Make an offer on a token. A valid listing is not required.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "assetContractAddress": { - "description": "The address of the asset being listed.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "tokenId": { - "description": "The ID of the token to list.", - "type": "string" - }, - "currencyContractAddress": { - "description": "The address of the currency to accept for the listing.", - "type": "string" - }, - "quantity": { - "description": "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - "type": "string" - }, - "totalPrice": { - "description": "the price to offer in the currency specified", - "type": "string" - }, - "endTimestamp": { - "description": "Defaults to 10 years from now.", - "type": "number" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["assetContractAddress", "tokenId", "totalPrice"] - }, - "example": { - "assetContractAddress": "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - "tokenId": "0", - "quantity": "1", - "endTimestamp": 1686610889058, - "currencyContractAddress": "0x...", - "totalPrice": "0.00000001" - } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/cancel-offer": { - "post": { - "operationId": "cancelOffer", - "summary": "Cancel offer", - "tags": ["Marketplace-Offers"], - "description": "Cancel a valid offer made by the caller wallet.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "offerId": { - "description": "The ID of the offer to cancel. You can view all offers with getAll or getAllValid.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["offerId"] - }, - "example": { "offerId": "1" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/marketplace/{chain}/{contractAddress}/offers/accept-offer": { - "post": { - "operationId": "acceptOffer", - "summary": "Accept offer", - "tags": ["Marketplace-Offers"], - "description": "Accept a valid offer.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "offerId": { - "description": "The ID of the offer to accept. You can view all offers with getAll or getAllValid.", - "type": "string" - }, - "txOverrides": { - "type": "object", - "properties": { - "gas": { - "description": "Gas limit for the transaction", - "type": "string", - "example": "530000" - }, - "maxFeePerGas": { - "description": "Maximum fee per gas", - "type": "string", - "example": "1000000000" - }, - "maxPriorityFeePerGas": { - "description": "Maximum priority fee per gas", - "type": "string", - "example": "1000000000" - }, - "value": { - "description": "Amount of native currency to send", - "type": "string", - "example": "10000000000" - } - } - } - }, - "required": ["offerId"] - }, - "example": { "offerId": "1" } - } - }, - "required": true - }, - "parameters": [ - { - "schema": { "default": false, "type": "boolean" }, - "in": "query", - "name": "simulateTx", - "required": false, - "description": "Simulate the transaction on-chain without executing" - }, - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-backend-wallet-address", - "required": true, - "description": "Backend wallet address" - }, - { - "schema": { "type": "string" }, - "in": "header", - "name": "x-idempotency-key", - "required": false, - "description": "Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared." - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-address", - "required": false, - "description": "Smart account address" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "header", - "name": "x-account-factory-address", - "required": false, - "description": "Smart account factory address. If omitted, engine will try to resolve it from the chain." - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "queueId": { - "description": "Queue ID", - "type": "string" - } - }, - "required": ["queueId"] - } - }, - "required": ["result"], - "example": { - "result": { - "queueId": "9eb88b00-f04f-409b-9df7-7dcc9003bc35" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract-subscriptions/get-all": { - "get": { - "operationId": "getContractSubscriptions", - "summary": "Get contract subscriptions", - "tags": ["Contract-Subscriptions"], - "description": "Get all contract subscriptions.", - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "chainId": { "type": "number" }, - "contractAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "webhook": { - "type": "object", - "properties": { - "url": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "secret": { "type": "string" }, - "eventType": { "type": "string" }, - "active": { "type": "boolean" }, - "createdAt": { "type": "string" }, - "id": { "type": "number" } - }, - "required": [ - "url", - "name", - "eventType", - "active", - "createdAt", - "id" - ] - }, - "processEventLogs": { "type": "boolean" }, - "filterEvents": { - "type": "array", - "items": { "type": "string" } - }, - "processTransactionReceipts": { "type": "boolean" }, - "filterFunctions": { - "type": "array", - "items": { "type": "string" } - }, - "createdAt": { "type": "string", "format": "date" } - }, - "required": [ - "id", - "chainId", - "contractAddress", - "processEventLogs", - "filterEvents", - "processTransactionReceipts", - "filterFunctions", - "createdAt" - ] - } - } - }, - "required": ["result"], - "example": { - "result": [ - { - "chain": "ethereum", - "contractAddress": "0x....", - "webhook": { "url": "https://.../" } - } - ] - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract-subscriptions/add": { - "post": { - "operationId": "addContractSubscription", - "summary": "Add contract subscription", - "tags": ["Contract-Subscriptions"], - "description": "Subscribe to event logs and transaction receipts for a contract.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "chain": { - "description": "The chain for the contract.", - "type": "string" - }, - "contractAddress": { - "description": "The address for the contract.", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "webhookUrl": { - "description": "Webhook URL", - "type": "string", - "example": "https://example.com/webhook" - }, - "processEventLogs": { - "description": "If true, parse event logs for this contract.", - "type": "boolean" - }, - "filterEvents": { - "description": "A case-sensitive list of event names to filter event logs. Parses all event logs by default.", - "type": "array", - "items": { "type": "string" }, - "example": "Transfer" - }, - "processTransactionReceipts": { - "description": "If true, parse transaction receipts for this contract.", - "type": "boolean" - }, - "filterFunctions": { - "description": "A case-sensitive list of function names to filter transaction receipts. Parses all transaction receipts by default.", - "type": "array", - "items": { "type": "string" }, - "example": "mintTo" - } - }, - "required": [ - "chain", - "contractAddress", - "processEventLogs", - "processTransactionReceipts" - ] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "chainId": { "type": "number" }, - "contractAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "webhook": { - "type": "object", - "properties": { - "url": { "type": "string" }, - "name": { - "anyOf": [ - { "type": "string" }, - { "type": "null" } - ] - }, - "secret": { "type": "string" }, - "eventType": { "type": "string" }, - "active": { "type": "boolean" }, - "createdAt": { "type": "string" }, - "id": { "type": "number" } - }, - "required": [ - "url", - "name", - "eventType", - "active", - "createdAt", - "id" - ] - }, - "processEventLogs": { "type": "boolean" }, - "filterEvents": { - "type": "array", - "items": { "type": "string" } - }, - "processTransactionReceipts": { "type": "boolean" }, - "filterFunctions": { - "type": "array", - "items": { "type": "string" } - }, - "createdAt": { "type": "string", "format": "date" } - }, - "required": [ - "id", - "chainId", - "contractAddress", - "processEventLogs", - "filterEvents", - "processTransactionReceipts", - "filterFunctions", - "createdAt" - ] - } - }, - "required": ["result"], - "example": { - "result": { - "chain": 1, - "contractAddress": "0x....", - "status": "success" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract-subscriptions/remove": { - "post": { - "operationId": "removeContractSubscription", - "summary": "Remove contract subscription", - "tags": ["Contract-Subscriptions"], - "description": "Remove an existing contract subscription", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "contractSubscriptionId": { - "description": "The ID for an existing contract subscription.", - "type": "string" - } - }, - "required": ["contractSubscriptionId"] - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { "status": { "type": "string" } }, - "required": ["status"] - } - }, - "required": ["result"], - "example": { "result": { "status": "success" } } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract/{chain}/{contractAddress}/subscriptions/get-indexed-blocks": { - "get": { - "operationId": "getContractIndexedBlockRange", - "summary": "Get subscribed contract indexed block range", - "tags": ["Contract-Subscriptions"], - "description": "Gets the subscribed contract's indexed block range", - "parameters": [ - { - "schema": { "type": "string" }, - "example": "80002", - "in": "path", - "name": "chain", - "required": true, - "description": "Chain ID or name" - }, - { - "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$" }, - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", - "in": "path", - "name": "contractAddress", - "required": true, - "description": "Contract address" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "chain": { "type": "string" }, - "contractAddress": { - "description": "A contract or wallet address", - "type": "string", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0x152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4" - }, - "fromBlock": { "type": "number" }, - "toBlock": { "type": "number" }, - "status": { "type": "string" } - }, - "required": [ - "chain", - "contractAddress", - "fromBlock", - "toBlock", - "status" - ] - } - }, - "required": ["result"], - "example": { - "result": { - "chain": "ethereum", - "contractAddress": "0x....", - "fromBlock": 100, - "toBlock": 200, - "status": "success" - } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - }, - "/contract-subscriptions/last-block": { - "get": { - "operationId": "getLatestBlock", - "summary": "Get last processed block", - "tags": ["Contract-Subscriptions"], - "description": "Get the last processed block for a chain.", - "parameters": [ - { - "schema": { "type": "string" }, - "examples": { - "1": { "value": "1" }, - "ethereum": { "value": "ethereum" } - }, - "in": "query", - "name": "chain", - "required": true, - "description": "Chain name or ID" - } - ], - "responses": { - "200": { - "description": "Default Response", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "lastBlock": { "type": "number" }, - "status": { "type": "string" } - }, - "required": ["lastBlock", "status"] - } - }, - "required": ["result"], - "example": { - "result": { "lastBlock": 100, "status": "success" } - } - } - } - } - }, - "400": { - "description": "Bad Request", - "content": { - "application/json": { - "schema": { - "description": "Bad Request", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "", - "code": "BAD_REQUEST", - "statusCode": 400 - } - } - } - } - }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { - "description": "Not Found", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - "code": "NOT_FOUND", - "statusCode": 404 - } - } - } - } - }, - "500": { - "description": "Internal Server Error", - "content": { - "application/json": { - "schema": { - "description": "Internal Server Error", - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { "type": "string" }, - "reason": {}, - "code": { "type": "string" }, - "stack": { "type": "string" }, - "statusCode": { "type": "number" } - } - } - } - }, - "example": { - "error": { - "message": "Transaction simulation failed with reason: types/values length mismatch", - "code": "INTERNAL_SERVER_ERROR", - "statusCode": 500 - } - } - } - } - } - } - } - } - }, - "security": [{ "bearerAuth": [] }] -} diff --git a/sdk/package.json b/sdk/package.json deleted file mode 100644 index 5cc6fa596..000000000 --- a/sdk/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@thirdweb-dev/engine", - "version": "0.0.19", - "main": "dist/thirdweb-dev-engine.cjs.js", - "module": "dist/thirdweb-dev-engine.esm.js", - "files": [ - "dist" - ], - "license": "MIT", - "devDependencies": { - "@babel/preset-typescript": "^7.23.2", - "@preconstruct/cli": "^2.8.1" - }, - "dependencies": {}, - "scripts": { - "build": "preconstruct build" - } -} diff --git a/sdk/src/Engine.ts b/sdk/src/Engine.ts deleted file mode 100644 index 72dd69d95..000000000 --- a/sdk/src/Engine.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { BaseHttpRequest } from './core/BaseHttpRequest'; -import type { OpenAPIConfig } from './core/OpenAPI'; -import { FetchHttpRequest } from './core/FetchHttpRequest'; - -import { AccessTokensService } from './services/AccessTokensService'; -import { AccountService } from './services/AccountService'; -import { AccountFactoryService } from './services/AccountFactoryService'; -import { BackendWalletService } from './services/BackendWalletService'; -import { ChainService } from './services/ChainService'; -import { ConfigurationService } from './services/ConfigurationService'; -import { ContractService } from './services/ContractService'; -import { ContractEventsService } from './services/ContractEventsService'; -import { ContractMetadataService } from './services/ContractMetadataService'; -import { ContractRolesService } from './services/ContractRolesService'; -import { ContractRoyaltiesService } from './services/ContractRoyaltiesService'; -import { ContractSubscriptionsService } from './services/ContractSubscriptionsService'; -import { DefaultService } from './services/DefaultService'; -import { DeployService } from './services/DeployService'; -import { Erc1155Service } from './services/Erc1155Service'; -import { Erc20Service } from './services/Erc20Service'; -import { Erc721Service } from './services/Erc721Service'; -import { KeypairService } from './services/KeypairService'; -import { MarketplaceDirectListingsService } from './services/MarketplaceDirectListingsService'; -import { MarketplaceEnglishAuctionsService } from './services/MarketplaceEnglishAuctionsService'; -import { MarketplaceOffersService } from './services/MarketplaceOffersService'; -import { PermissionsService } from './services/PermissionsService'; -import { RelayerService } from './services/RelayerService'; -import { TransactionService } from './services/TransactionService'; -import { WalletCredentialsService } from './services/WalletCredentialsService'; -import { WebhooksService } from './services/WebhooksService'; - -type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest; - -class EngineLogic { - - public readonly accessTokens: AccessTokensService; - public readonly account: AccountService; - public readonly accountFactory: AccountFactoryService; - public readonly backendWallet: BackendWalletService; - public readonly chain: ChainService; - public readonly configuration: ConfigurationService; - public readonly contract: ContractService; - public readonly contractEvents: ContractEventsService; - public readonly contractMetadata: ContractMetadataService; - public readonly contractRoles: ContractRolesService; - public readonly contractRoyalties: ContractRoyaltiesService; - public readonly contractSubscriptions: ContractSubscriptionsService; - public readonly default: DefaultService; - public readonly deploy: DeployService; - public readonly erc1155: Erc1155Service; - public readonly erc20: Erc20Service; - public readonly erc721: Erc721Service; - public readonly keypair: KeypairService; - public readonly marketplaceDirectListings: MarketplaceDirectListingsService; - public readonly marketplaceEnglishAuctions: MarketplaceEnglishAuctionsService; - public readonly marketplaceOffers: MarketplaceOffersService; - public readonly permissions: PermissionsService; - public readonly relayer: RelayerService; - public readonly transaction: TransactionService; - public readonly walletCredentials: WalletCredentialsService; - public readonly webhooks: WebhooksService; - - public readonly request: BaseHttpRequest; - - constructor(config?: Partial, HttpRequest: HttpRequestConstructor = FetchHttpRequest) { - this.request = new HttpRequest({ - BASE: config?.BASE ?? '', - VERSION: config?.VERSION ?? '1.0.0', - WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false, - CREDENTIALS: config?.CREDENTIALS ?? 'include', - TOKEN: config?.TOKEN, - USERNAME: config?.USERNAME, - PASSWORD: config?.PASSWORD, - HEADERS: config?.HEADERS, - ENCODE_PATH: config?.ENCODE_PATH, - }); - - this.accessTokens = new AccessTokensService(this.request); - this.account = new AccountService(this.request); - this.accountFactory = new AccountFactoryService(this.request); - this.backendWallet = new BackendWalletService(this.request); - this.chain = new ChainService(this.request); - this.configuration = new ConfigurationService(this.request); - this.contract = new ContractService(this.request); - this.contractEvents = new ContractEventsService(this.request); - this.contractMetadata = new ContractMetadataService(this.request); - this.contractRoles = new ContractRolesService(this.request); - this.contractRoyalties = new ContractRoyaltiesService(this.request); - this.contractSubscriptions = new ContractSubscriptionsService(this.request); - this.default = new DefaultService(this.request); - this.deploy = new DeployService(this.request); - this.erc1155 = new Erc1155Service(this.request); - this.erc20 = new Erc20Service(this.request); - this.erc721 = new Erc721Service(this.request); - this.keypair = new KeypairService(this.request); - this.marketplaceDirectListings = new MarketplaceDirectListingsService(this.request); - this.marketplaceEnglishAuctions = new MarketplaceEnglishAuctionsService(this.request); - this.marketplaceOffers = new MarketplaceOffersService(this.request); - this.permissions = new PermissionsService(this.request); - this.relayer = new RelayerService(this.request); - this.transaction = new TransactionService(this.request); - this.walletCredentials = new WalletCredentialsService(this.request); - this.webhooks = new WebhooksService(this.request); - } -} - - -export class Engine extends EngineLogic { - constructor(config: { url: string; accessToken: string; }) { - super({ BASE: config.url, TOKEN: config.accessToken }); - } -} diff --git a/sdk/src/core/ApiError.ts b/sdk/src/core/ApiError.ts deleted file mode 100644 index d6b8fcc3a..000000000 --- a/sdk/src/core/ApiError.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { ApiResult } from './ApiResult'; - -export class ApiError extends Error { - public readonly url: string; - public readonly status: number; - public readonly statusText: string; - public readonly body: any; - public readonly request: ApiRequestOptions; - - constructor(request: ApiRequestOptions, response: ApiResult, message: string) { - super(message); - - this.name = 'ApiError'; - this.url = response.url; - this.status = response.status; - this.statusText = response.statusText; - this.body = response.body; - this.request = request; - } -} diff --git a/sdk/src/core/ApiRequestOptions.ts b/sdk/src/core/ApiRequestOptions.ts deleted file mode 100644 index c19adcc94..000000000 --- a/sdk/src/core/ApiRequestOptions.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ApiRequestOptions = { - readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly url: string; - readonly path?: Record; - readonly cookies?: Record; - readonly headers?: Record; - readonly query?: Record; - readonly formData?: Record; - readonly body?: any; - readonly mediaType?: string; - readonly responseHeader?: string; - readonly errors?: Record; -}; diff --git a/sdk/src/core/ApiResult.ts b/sdk/src/core/ApiResult.ts deleted file mode 100644 index ad8fef2bc..000000000 --- a/sdk/src/core/ApiResult.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ApiResult = { - readonly url: string; - readonly ok: boolean; - readonly status: number; - readonly statusText: string; - readonly body: any; -}; diff --git a/sdk/src/core/BaseHttpRequest.ts b/sdk/src/core/BaseHttpRequest.ts deleted file mode 100644 index 8da3f4df7..000000000 --- a/sdk/src/core/BaseHttpRequest.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { CancelablePromise } from './CancelablePromise'; -import type { OpenAPIConfig } from './OpenAPI'; - -export abstract class BaseHttpRequest { - - constructor(public readonly config: OpenAPIConfig) {} - - public abstract request(options: ApiRequestOptions): CancelablePromise; -} diff --git a/sdk/src/core/CancelablePromise.ts b/sdk/src/core/CancelablePromise.ts deleted file mode 100644 index 55fef8517..000000000 --- a/sdk/src/core/CancelablePromise.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export class CancelError extends Error { - - constructor(message: string) { - super(message); - this.name = 'CancelError'; - } - - public get isCancelled(): boolean { - return true; - } -} - -export interface OnCancel { - readonly isResolved: boolean; - readonly isRejected: boolean; - readonly isCancelled: boolean; - - (cancelHandler: () => void): void; -} - -export class CancelablePromise implements Promise { - #isResolved: boolean; - #isRejected: boolean; - #isCancelled: boolean; - readonly #cancelHandlers: (() => void)[]; - readonly #promise: Promise; - #resolve?: (value: T | PromiseLike) => void; - #reject?: (reason?: any) => void; - - constructor( - executor: ( - resolve: (value: T | PromiseLike) => void, - reject: (reason?: any) => void, - onCancel: OnCancel - ) => void - ) { - this.#isResolved = false; - this.#isRejected = false; - this.#isCancelled = false; - this.#cancelHandlers = []; - this.#promise = new Promise((resolve, reject) => { - this.#resolve = resolve; - this.#reject = reject; - - const onResolve = (value: T | PromiseLike): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isResolved = true; - this.#resolve?.(value); - }; - - const onReject = (reason?: any): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isRejected = true; - this.#reject?.(reason); - }; - - const onCancel = (cancelHandler: () => void): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#cancelHandlers.push(cancelHandler); - }; - - Object.defineProperty(onCancel, 'isResolved', { - get: (): boolean => this.#isResolved, - }); - - Object.defineProperty(onCancel, 'isRejected', { - get: (): boolean => this.#isRejected, - }); - - Object.defineProperty(onCancel, 'isCancelled', { - get: (): boolean => this.#isCancelled, - }); - - return executor(onResolve, onReject, onCancel as OnCancel); - }); - } - - get [Symbol.toStringTag]() { - return "Cancellable Promise"; - } - - public then( - onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, - onRejected?: ((reason: any) => TResult2 | PromiseLike) | null - ): Promise { - return this.#promise.then(onFulfilled, onRejected); - } - - public catch( - onRejected?: ((reason: any) => TResult | PromiseLike) | null - ): Promise { - return this.#promise.catch(onRejected); - } - - public finally(onFinally?: (() => void) | null): Promise { - return this.#promise.finally(onFinally); - } - - public cancel(): void { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isCancelled = true; - if (this.#cancelHandlers.length) { - try { - for (const cancelHandler of this.#cancelHandlers) { - cancelHandler(); - } - } catch (error) { - console.warn('Cancellation threw an error', error); - return; - } - } - this.#cancelHandlers.length = 0; - this.#reject?.(new CancelError('Request aborted')); - } - - public get isCancelled(): boolean { - return this.#isCancelled; - } -} diff --git a/sdk/src/core/FetchHttpRequest.ts b/sdk/src/core/FetchHttpRequest.ts deleted file mode 100644 index b1083b2a3..000000000 --- a/sdk/src/core/FetchHttpRequest.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; -import { BaseHttpRequest } from './BaseHttpRequest'; -import type { CancelablePromise } from './CancelablePromise'; -import type { OpenAPIConfig } from './OpenAPI'; -import { request as __request } from './request'; - -export class FetchHttpRequest extends BaseHttpRequest { - - constructor(config: OpenAPIConfig) { - super(config); - } - - /** - * Request method - * @param options The request options from the service - * @returns CancelablePromise - * @throws ApiError - */ - public override request(options: ApiRequestOptions): CancelablePromise { - return __request(this.config, options); - } -} diff --git a/sdk/src/core/OpenAPI.ts b/sdk/src/core/OpenAPI.ts deleted file mode 100644 index 52c1bc25b..000000000 --- a/sdk/src/core/OpenAPI.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; - -type Resolver = (options: ApiRequestOptions) => Promise; -type Headers = Record; - -export type OpenAPIConfig = { - BASE: string; - VERSION: string; - WITH_CREDENTIALS: boolean; - CREDENTIALS: 'include' | 'omit' | 'same-origin'; - TOKEN?: string | Resolver | undefined; - USERNAME?: string | Resolver | undefined; - PASSWORD?: string | Resolver | undefined; - HEADERS?: Headers | Resolver | undefined; - ENCODE_PATH?: ((path: string) => string) | undefined; -}; - -export const OpenAPI: OpenAPIConfig = { - BASE: '', - VERSION: '1.0.0', - WITH_CREDENTIALS: false, - CREDENTIALS: 'include', - TOKEN: undefined, - USERNAME: undefined, - PASSWORD: undefined, - HEADERS: undefined, - ENCODE_PATH: undefined, -}; diff --git a/sdk/src/core/request.ts b/sdk/src/core/request.ts deleted file mode 100644 index b018a07ca..000000000 --- a/sdk/src/core/request.ts +++ /dev/null @@ -1,320 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import { ApiError } from './ApiError'; -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { ApiResult } from './ApiResult'; -import { CancelablePromise } from './CancelablePromise'; -import type { OnCancel } from './CancelablePromise'; -import type { OpenAPIConfig } from './OpenAPI'; - -export const isDefined = (value: T | null | undefined): value is Exclude => { - return value !== undefined && value !== null; -}; - -export const isString = (value: any): value is string => { - return typeof value === 'string'; -}; - -export const isStringWithValue = (value: any): value is string => { - return isString(value) && value !== ''; -}; - -export const isBlob = (value: any): value is Blob => { - return ( - typeof value === 'object' && - typeof value.type === 'string' && - typeof value.stream === 'function' && - typeof value.arrayBuffer === 'function' && - typeof value.constructor === 'function' && - typeof value.constructor.name === 'string' && - /^(Blob|File)$/.test(value.constructor.name) && - /^(Blob|File)$/.test(value[Symbol.toStringTag]) - ); -}; - -export const isFormData = (value: any): value is FormData => { - return value instanceof FormData; -}; - -export const base64 = (str: string): string => { - try { - return btoa(str); - } catch (err) { - // @ts-ignore - return Buffer.from(str).toString('base64'); - } -}; - -export const getQueryString = (params: Record): string => { - const qs: string[] = []; - - const append = (key: string, value: any) => { - qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); - }; - - const process = (key: string, value: any) => { - if (isDefined(value)) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(`${key}[${k}]`, v); - }); - } else { - append(key, value); - } - } - }; - - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); - - if (qs.length > 0) { - return `?${qs.join('&')}`; - } - - return ''; -}; - -const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { - const encoder = config.ENCODE_PATH || encodeURI; - - const path = options.url - .replace('{api-version}', config.VERSION) - .replace(/{(.*?)}/g, (substring: string, group: string) => { - if (options.path?.hasOwnProperty(group)) { - return encoder(String(options.path[group])); - } - return substring; - }); - - const url = `${config.BASE}${path}`; - if (options.query) { - return `${url}${getQueryString(options.query)}`; - } - return url; -}; - -export const getFormData = (options: ApiRequestOptions): FormData | undefined => { - if (options.formData) { - const formData = new FormData(); - - const process = (key: string, value: any) => { - if (isString(value) || isBlob(value)) { - formData.append(key, value); - } else { - formData.append(key, JSON.stringify(value)); - } - }; - - Object.entries(options.formData) - .filter(([_, value]) => isDefined(value)) - .forEach(([key, value]) => { - if (Array.isArray(value)) { - value.forEach(v => process(key, v)); - } else { - process(key, value); - } - }); - - return formData; - } - return undefined; -}; - -type Resolver = (options: ApiRequestOptions) => Promise; - -export const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { - if (typeof resolver === 'function') { - return (resolver as Resolver)(options); - } - return resolver; -}; - -export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { - const token = await resolve(options, config.TOKEN); - const username = await resolve(options, config.USERNAME); - const password = await resolve(options, config.PASSWORD); - const additionalHeaders = await resolve(options, config.HEADERS); - - const headers = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); - - if (isStringWithValue(token)) { - headers['Authorization'] = `Bearer ${token}`; - } - - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers['Authorization'] = `Basic ${credentials}`; - } - - if (options.body) { - if (options.mediaType) { - headers['Content-Type'] = options.mediaType; - } else if (isBlob(options.body)) { - headers['Content-Type'] = options.body.type || 'application/octet-stream'; - } else if (isString(options.body)) { - headers['Content-Type'] = 'text/plain'; - } else if (!isFormData(options.body)) { - headers['Content-Type'] = 'application/json'; - } - } - - return new Headers(headers); -}; - -export const getRequestBody = (options: ApiRequestOptions): any => { - if (options.body !== undefined) { - if (options.mediaType?.includes('/json')) { - return JSON.stringify(options.body) - } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { - return options.body; - } else { - return JSON.stringify(options.body); - } - } - return undefined; -}; - -export const sendRequest = async ( - config: OpenAPIConfig, - options: ApiRequestOptions, - url: string, - body: any, - formData: FormData | undefined, - headers: Headers, - onCancel: OnCancel -): Promise => { - const controller = new AbortController(); - - const request: RequestInit = { - headers, - body: body ?? formData, - method: options.method, - signal: controller.signal, - }; - - if (config.WITH_CREDENTIALS) { - request.credentials = config.CREDENTIALS; - } - - onCancel(() => controller.abort()); - - return await fetch(url, request); -}; - -export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { - if (responseHeader) { - const content = response.headers.get(responseHeader); - if (isString(content)) { - return content; - } - } - return undefined; -}; - -export const getResponseBody = async (response: Response): Promise => { - if (response.status !== 204) { - try { - const contentType = response.headers.get('Content-Type'); - if (contentType) { - const jsonTypes = ['application/json', 'application/problem+json'] - const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type)); - if (isJSON) { - return await response.json(); - } else { - return await response.text(); - } - } - } catch (error) { - console.error(error); - } - } - return undefined; -}; - -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { - const errors: Record = { - 400: 'Bad Request', - 401: 'Unauthorized', - 403: 'Forbidden', - 404: 'Not Found', - 500: 'Internal Server Error', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - ...options.errors, - } - - const error = errors[result.status]; - if (error) { - throw new ApiError(options, result, error); - } - - if (!result.ok) { - const errorStatus = result.status ?? 'unknown'; - const errorStatusText = result.statusText ?? 'unknown'; - const errorBody = (() => { - try { - return JSON.stringify(result.body, null, 2); - } catch (e) { - return undefined; - } - })(); - - throw new ApiError(options, result, - `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}` - ); - } -}; - -/** - * Request method - * @param config The OpenAPI configuration object - * @param options The request options from the service - * @returns CancelablePromise - * @throws ApiError - */ -export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(config, options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(config, options); - - if (!onCancel.isCancelled) { - const response = await sendRequest(config, options, url, body, formData, headers, onCancel); - const responseBody = await getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); - - const result: ApiResult = { - url, - ok: response.ok, - status: response.status, - statusText: response.statusText, - body: responseHeader ?? responseBody, - }; - - catchErrorCodes(options, result); - - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); -}; diff --git a/sdk/src/index.ts b/sdk/src/index.ts deleted file mode 100644 index 9a6e7cda8..000000000 --- a/sdk/src/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export { Engine } from './Engine'; - -export { ApiError } from './core/ApiError'; -export { BaseHttpRequest } from './core/BaseHttpRequest'; -export { CancelablePromise, CancelError } from './core/CancelablePromise'; -export { OpenAPI } from './core/OpenAPI'; -export type { OpenAPIConfig } from './core/OpenAPI'; - -export { AccessTokensService } from './services/AccessTokensService'; -export { AccountService } from './services/AccountService'; -export { AccountFactoryService } from './services/AccountFactoryService'; -export { BackendWalletService } from './services/BackendWalletService'; -export { ChainService } from './services/ChainService'; -export { ConfigurationService } from './services/ConfigurationService'; -export { ContractService } from './services/ContractService'; -export { ContractEventsService } from './services/ContractEventsService'; -export { ContractMetadataService } from './services/ContractMetadataService'; -export { ContractRolesService } from './services/ContractRolesService'; -export { ContractRoyaltiesService } from './services/ContractRoyaltiesService'; -export { ContractSubscriptionsService } from './services/ContractSubscriptionsService'; -export { DefaultService } from './services/DefaultService'; -export { DeployService } from './services/DeployService'; -export { Erc1155Service } from './services/Erc1155Service'; -export { Erc20Service } from './services/Erc20Service'; -export { Erc721Service } from './services/Erc721Service'; -export { KeypairService } from './services/KeypairService'; -export { MarketplaceDirectListingsService } from './services/MarketplaceDirectListingsService'; -export { MarketplaceEnglishAuctionsService } from './services/MarketplaceEnglishAuctionsService'; -export { MarketplaceOffersService } from './services/MarketplaceOffersService'; -export { PermissionsService } from './services/PermissionsService'; -export { RelayerService } from './services/RelayerService'; -export { TransactionService } from './services/TransactionService'; -export { WalletCredentialsService } from './services/WalletCredentialsService'; -export { WebhooksService } from './services/WebhooksService'; diff --git a/sdk/src/services/AccessTokensService.ts b/sdk/src/services/AccessTokensService.ts deleted file mode 100644 index 565f90fe6..000000000 --- a/sdk/src/services/AccessTokensService.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class AccessTokensService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all access tokens - * Get all access tokens - * @returns any Default Response - * @throws ApiError - */ - public getAll(): CancelablePromise<{ - result: Array<{ - id: string; - tokenMask: string; - /** - * A contract or wallet address - */ - walletAddress: string; - createdAt: string; - expiresAt: string; - label: (string | null); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/auth/access-tokens/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create a new access token - * Create a new access token - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public create( - requestBody?: { - label?: string; - }, - ): CancelablePromise<{ - result: { - id: string; - tokenMask: string; - /** - * A contract or wallet address - */ - walletAddress: string; - createdAt: string; - expiresAt: string; - label: (string | null); - accessToken: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/access-tokens/create', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke an access token - * Revoke an access token - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public revoke( - requestBody: { - id: string; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/access-tokens/revoke', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update an access token - * Update an access token - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public update( - requestBody: { - id: string; - label?: string; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/access-tokens/update', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/AccountFactoryService.ts b/sdk/src/services/AccountFactoryService.ts deleted file mode 100644 index 6eefd2e3e..000000000 --- a/sdk/src/services/AccountFactoryService.ts +++ /dev/null @@ -1,260 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class AccountFactoryService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all smart accounts - * Get all the smart accounts for this account factory. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAllAccounts( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - /** - * The account addresses of all the accounts in this factory - */ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/account-factory/get-all-accounts', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get associated smart accounts - * Get all the smart accounts for this account factory associated with the specific admin wallet. - * @param signerAddress The address of the signer to get associated accounts from - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAssociatedAccounts( - signerAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - /** - * The account addresses of all the accounts with a specific signer in this factory - */ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/account-factory/get-associated-accounts', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'signerAddress': signerAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check if deployed - * Check if a smart account has been deployed to the blockchain. - * @param adminAddress The address of the admin to check if the account address is deployed - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param extraData Extra data to use in predicting the account address - * @returns any Default Response - * @throws ApiError - */ - public isAccountDeployed( - adminAddress: string, - chain: string, - contractAddress: string, - extraData?: string, - ): CancelablePromise<{ - /** - * Whether or not the account has been deployed - */ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/account-factory/is-account-deployed', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'adminAddress': adminAddress, - 'extraData': extraData, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Predict smart account address - * Get the counterfactual address of a smart account. - * @param adminAddress The address of the admin to predict the account address for - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param extraData Extra data (account salt) to add to use in predicting the account address - * @returns any Default Response - * @throws ApiError - */ - public predictAccountAddress( - adminAddress: string, - chain: string, - contractAddress: string, - extraData?: string, - ): CancelablePromise<{ - /** - * New account counter-factual address. - */ - result: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/account-factory/predict-account-address', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'adminAddress': adminAddress, - 'extraData': extraData, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create smart account - * Create a smart account for this account factory. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public createAccount( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The admin address to create an account for - */ - adminAddress: string; - /** - * Extra data to add to use in creating the account address - */ - extraData?: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/account-factory/create-account', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/AccountService.ts b/sdk/src/services/AccountService.ts deleted file mode 100644 index c16916400..000000000 --- a/sdk/src/services/AccountService.ts +++ /dev/null @@ -1,560 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class AccountService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all admins - * Get all admins for a smart account. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAllAdmins( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - /** - * The address of the admins on this account - */ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/account/admins/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all session keys - * Get all session keys for a smart account. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAllSessions( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array<{ - /** - * A contract or wallet address - */ - signerAddress: string; - startDate: string; - expirationDate: string; - nativeTokenLimitPerTransaction: string; - approvedCallTargets: Array; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/account/sessions/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Grant admin - * Grant a smart account's admin permission. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public grantAdmin( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address to grant admin permissions to - */ - signerAddress: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/account/admins/grant', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke admin - * Revoke a smart account's admin permission. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public revokeAdmin( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address to revoke admin permissions from - */ - walletAddress: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/account/admins/revoke', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create session key - * Create a session key for a smart account. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public grantSession( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * A contract or wallet address - */ - signerAddress: string; - startDate: string; - expirationDate: string; - nativeTokenLimitPerTransaction: string; - approvedCallTargets: Array; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/account/sessions/create', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke session key - * Revoke a session key for a smart account. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public revokeSession( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address to revoke session from - */ - walletAddress: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/account/sessions/revoke', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update session key - * Update a session key for a smart account. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateSession( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * A contract or wallet address - */ - signerAddress: string; - approvedCallTargets: Array; - startDate?: string; - expirationDate?: string; - nativeTokenLimitPerTransaction?: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/account/sessions/update', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/BackendWalletService.ts b/sdk/src/services/BackendWalletService.ts deleted file mode 100644 index 9be834083..000000000 --- a/sdk/src/services/BackendWalletService.ts +++ /dev/null @@ -1,1237 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class BackendWalletService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Create backend wallet - * Create a backend wallet. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public create( - requestBody?: ({ - label?: string; - type?: ('local' | 'aws-kms' | 'gcp-kms' | 'smart:aws-kms' | 'smart:gcp-kms' | 'smart:local'); - } | { - label?: string; - type: ('circle' | 'smart:circle'); - /** - * If your engine is configured with a testnet API Key for Circle, you can only create testnet wallets and send testnet transactions. Enable this field for testnet wallets. NOTE: A production API Key cannot be used for testnet transactions, and a testnet API Key cannot be used for production transactions. See: https://developers.circle.com/w3s/sandbox-vs-production - */ - isTestnet?: boolean; - credentialId: string; - walletSetId?: string; - }), - ): CancelablePromise<{ - result: { - /** - * A contract or wallet address - */ - walletAddress: string; - status: string; - type: ('local' | 'aws-kms' | 'gcp-kms' | 'smart:aws-kms' | 'smart:gcp-kms' | 'smart:local' | 'circle' | 'smart:circle'); - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/create', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Remove backend wallet - * Remove an existing backend wallet. NOTE: This is an irreversible action for local wallets. Ensure any funds are transferred out before removing a local wallet. - * @param walletAddress A contract or wallet address - * @returns any Default Response - * @throws ApiError - */ - public removeBackendWallet( - walletAddress: string, - ): CancelablePromise<{ - result: { - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'DELETE', - url: '/backend-wallet/{walletAddress}', - path: { - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Import backend wallet - * Import an existing wallet as a backend wallet. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public import( - requestBody?: ({ - /** - * Optional label for the imported wallet - */ - label?: string; - } & ({ - /** - * AWS KMS key ARN - */ - awsKmsArn: string; - /** - * Optional AWS credentials to use for importing the wallet, if not provided, the default AWS credentials will be used (if available). - */ - credentials?: { - /** - * AWS Access Key ID - */ - awsAccessKeyId: string; - /** - * AWS Secret Access Key - */ - awsSecretAccessKey: string; - }; - } | { - /** - * GCP KMS key ID - */ - gcpKmsKeyId: string; - /** - * GCP KMS key version ID - */ - gcpKmsKeyVersionId: string; - /** - * Optional GCP credentials to use for importing the wallet, if not provided, the default GCP credentials will be used (if available). - */ - credentials?: { - /** - * GCP service account email - */ - email: string; - /** - * GCP service account private key - */ - privateKey: string; - }; - } | { - /** - * The private key of the wallet to import - */ - privateKey: string; - } | { - /** - * The mnemonic phrase of the wallet to import - */ - mnemonic: string; - } | { - /** - * The encrypted JSON of the wallet to import - */ - encryptedJson: string; - /** - * The password used to encrypt the encrypted JSON - */ - password: string; - })), - ): CancelablePromise<{ - result: { - /** - * A contract or wallet address - */ - walletAddress: string; - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/import', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update backend wallet - * Update a backend wallet. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public update( - requestBody: { - /** - * A contract or wallet address - */ - walletAddress: string; - label?: string; - }, - ): CancelablePromise<{ - result: { - /** - * A contract or wallet address - */ - walletAddress: string; - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/update', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get balance - * Get the native balance for a backend wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param walletAddress Backend wallet address - * @returns any Default Response - * @throws ApiError - */ - public getBalance( - chain: string, - walletAddress: string, - ): CancelablePromise<{ - result: { - /** - * A contract or wallet address - */ - walletAddress: string; - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/backend-wallet/{chain}/{walletAddress}/get-balance', - path: { - 'chain': chain, - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all backend wallets - * Get all backend wallets. - * @param page The page of wallets to get. - * @param limit The number of wallets to get per page. - * @returns any Default Response - * @throws ApiError - */ - public getAll( - page: number = 1, - limit: number = 10, - ): CancelablePromise<{ - result: Array<{ - /** - * Wallet Address - */ - address: string; - /** - * Wallet Type - */ - type: string; - label: (string | null); - awsKmsKeyId: (string | null); - awsKmsArn: (string | null); - gcpKmsKeyId: (string | null); - gcpKmsKeyRingId: (string | null); - gcpKmsLocationId: (string | null); - gcpKmsKeyVersionId: (string | null); - gcpKmsResourcePath: (string | null); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/backend-wallet/get-all', - query: { - 'page': page, - 'limit': limit, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer tokens - * Transfer native currency or ERC20 tokens to another wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @returns any Default Response - * @throws ApiError - */ - public transfer( - chain: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The recipient wallet address. - */ - to: string; - /** - * The token address to transfer. Omit to transfer the chain's native currency (e.g. ETH on Ethereum). - */ - currencyAddress?: string; - /** - * The amount in ether to transfer. Example: "0.1" to send 0.1 ETH. - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/transfer', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Withdraw funds - * Withdraw all funds from this wallet to another wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @returns any Default Response - * @throws ApiError - */ - public withdraw( - chain: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address to withdraw all funds to - */ - toAddress: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - ): CancelablePromise<{ - result: { - /** - * A transaction hash - */ - transactionHash: string; - /** - * An amount in native token (decimals allowed). Example: "0.1" - */ - amount: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/withdraw', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Send a transaction - * Send a transaction with transaction parameters - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public sendTransaction( - chain: string, - xBackendWalletAddress: string, - requestBody: { - /** - * A contract or wallet address - */ - toAddress?: string; - data: string; - value: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/send-transaction', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Send a batch of raw transactions - * Send a batch of raw transactions with transaction parameters - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public sendTransactionBatch( - chain: string, - xBackendWalletAddress: string, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - requestBody?: Array<{ - /** - * A contract or wallet address - */ - toAddress?: string; - data: string; - value: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }>, - ): CancelablePromise<{ - result: { - queueIds: Array; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/send-transaction-batch', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Send a batch of raw transactions atomically - * Send a batch of raw transactions in a single UserOp. Transactions will be sent in-order and atomically. Can only be used with smart wallets. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public sendTransactionBatchAtomic( - chain: string, - xBackendWalletAddress: string, - requestBody: { - transactions: Array<{ - /** - * A contract or wallet address - */ - toAddress?: string; - /** - * A valid hex string - */ - data: string; - /** - * An amount in wei (no decimals). Example: "50000000000" - */ - value: string; - }>; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/send-transaction-batch-atomic', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Sign a transaction - * Sign a transaction - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @returns any Default Response - * @throws ApiError - */ - public signTransaction( - xBackendWalletAddress: string, - requestBody: { - transaction: { - to?: string; - nonce?: string; - gasLimit?: string; - gasPrice?: string; - data?: string; - value?: string; - chainId: number; - type?: number; - accessList?: any; - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - ccipReadEnabled?: boolean; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/sign-transaction', - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Sign a message - * Send a message - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @returns any Default Response - * @throws ApiError - */ - public signMessage( - xBackendWalletAddress: string, - requestBody: { - message: string; - isBytes?: boolean; - chainId?: number; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/sign-message', - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Sign an EIP-712 message - * Send an EIP-712 message ("typed data") - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @returns any Default Response - * @throws ApiError - */ - public signTypedData( - xBackendWalletAddress: string, - requestBody: { - domain: Record; - types: Record; - value: Record; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/sign-typed-data', - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get recent transactions - * Get recent transactions for this backend wallet. - * @param status The status to query: 'queued', 'mined', 'errored', or 'cancelled'. Default: 'queued' - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param walletAddress Backend wallet address - * @param page Specify the page number. - * @param limit Specify the number of results to return per page. - * @returns any Default Response - * @throws ApiError - */ - public getTransactionsForBackendWallet( - status: ('queued' | 'mined' | 'cancelled' | 'errored'), - chain: string, - walletAddress: string, - page: number = 1, - limit: number = 100, - ): CancelablePromise<{ - result: { - transactions: Array<{ - queueId: (string | null); - /** - * The current state of the transaction. - */ - status: ('queued' | 'sent' | 'mined' | 'errored' | 'cancelled'); - chainId: (string | null); - fromAddress: (string | null); - toAddress: (string | null); - data: (string | null); - extension: (string | null); - value: (string | null); - nonce: (number | string | null); - gasLimit: (string | null); - gasPrice: (string | null); - maxFeePerGas: (string | null); - maxPriorityFeePerGas: (string | null); - transactionType: (number | null); - transactionHash: (string | null); - queuedAt: (string | null); - sentAt: (string | null); - minedAt: (string | null); - cancelledAt: (string | null); - deployedContractAddress: (string | null); - deployedContractType: (string | null); - errorMessage: (string | null); - sentAtBlockNumber: (number | null); - blockNumber: (number | null); - /** - * The number of retry attempts - */ - retryCount: number; - retryGasValues: (boolean | null); - retryMaxFeePerGas: (string | null); - retryMaxPriorityFeePerGas: (string | null); - signerAddress: (string | null); - accountAddress: (string | null); - accountSalt: (string | null); - accountFactoryAddress: (string | null); - target: (string | null); - sender: (string | null); - initCode: (string | null); - callData: (string | null); - callGasLimit: (string | null); - verificationGasLimit: (string | null); - preVerificationGas: (string | null); - paymasterAndData: (string | null); - userOpHash: (string | null); - functionName: (string | null); - functionArgs: (string | null); - onChainTxStatus: (number | null); - onchainStatus: ('success' | 'reverted' | null); - effectiveGasPrice: (string | null); - cumulativeGasUsed: (string | null); - batchOperations: null; - }>; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/backend-wallet/{chain}/{walletAddress}/get-all-transactions', - path: { - 'chain': chain, - 'walletAddress': walletAddress, - }, - query: { - 'page': page, - 'limit': limit, - 'status': status, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get recent transactions by nonce - * Get recent transactions for this backend wallet, sorted by descending nonce. - * @param fromNonce The earliest nonce, inclusive. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param walletAddress Backend wallet address - * @param toNonce The latest nonce, inclusive. If omitted, queries up to the latest sent nonce. - * @returns any Default Response - * @throws ApiError - */ - public getTransactionsForBackendWalletByNonce( - fromNonce: number, - chain: string, - walletAddress: string, - toNonce?: number, - ): CancelablePromise<{ - result: Array<{ - nonce: number; - transaction: ({ - queueId: (string | null); - /** - * The current state of the transaction. - */ - status: ('queued' | 'sent' | 'mined' | 'errored' | 'cancelled'); - chainId: (string | null); - fromAddress: (string | null); - toAddress: (string | null); - data: (string | null); - extension: (string | null); - value: (string | null); - nonce: (number | string | null); - gasLimit: (string | null); - gasPrice: (string | null); - maxFeePerGas: (string | null); - maxPriorityFeePerGas: (string | null); - transactionType: (number | null); - transactionHash: (string | null); - queuedAt: (string | null); - sentAt: (string | null); - minedAt: (string | null); - cancelledAt: (string | null); - deployedContractAddress: (string | null); - deployedContractType: (string | null); - errorMessage: (string | null); - sentAtBlockNumber: (number | null); - blockNumber: (number | null); - /** - * The number of retry attempts - */ - retryCount: number; - retryGasValues: (boolean | null); - retryMaxFeePerGas: (string | null); - retryMaxPriorityFeePerGas: (string | null); - signerAddress: (string | null); - accountAddress: (string | null); - accountSalt: (string | null); - accountFactoryAddress: (string | null); - target: (string | null); - sender: (string | null); - initCode: (string | null); - callData: (string | null); - callGasLimit: (string | null); - verificationGasLimit: (string | null); - preVerificationGas: (string | null); - paymasterAndData: (string | null); - userOpHash: (string | null); - functionName: (string | null); - functionArgs: (string | null); - onChainTxStatus: (number | null); - onchainStatus: ('success' | 'reverted' | null); - effectiveGasPrice: (string | null); - cumulativeGasUsed: (string | null); - batchOperations: null; - } | string); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/backend-wallet/{chain}/{walletAddress}/get-transactions-by-nonce', - path: { - 'chain': chain, - 'walletAddress': walletAddress, - }, - query: { - 'fromNonce': fromNonce, - 'toNonce': toNonce, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Reset nonces - * Reset nonces for all backend wallets. This is for debugging purposes and does not impact held tokens. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public resetNonces( - requestBody: { - /** - * The chain ID to reset nonces for. - */ - chainId?: number; - /** - * The backend wallet address to reset nonces for. Omit to reset all backend wallets. - */ - walletAddress?: string; - /** - * Resync nonces to match the onchain transaction count for your backend wallets. (Default: true) - */ - syncOnchainNonces: boolean; - }, - ): CancelablePromise<{ - result: { - status: string; - /** - * The number of backend wallets processed. - */ - count: number; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/reset-nonces', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Cancel nonces - * Cancel all nonces up to the provided nonce. This is useful to unblock a backend wallet that has transactions waiting for nonces to be mined. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @returns any Default Response - * @throws ApiError - */ - public cancelNonces( - chain: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The nonce to cancel up to, inclusive. Example: If the onchain nonce is 10 and 'toNonce' is 15, this request will cancel nonces: 11, 12, 13, 14, 15 - */ - toNonce: number; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - ): CancelablePromise<{ - result: { - cancelledNonces: Array; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/cancel-nonces', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get nonce - * Get the last used nonce for this backend wallet. This value managed by Engine may differ from the onchain value. Use `/backend-wallet/reset-nonces` if this value looks incorrect while idle. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param walletAddress Backend wallet address - * @returns any Default Response - * @throws ApiError - */ - public getNonce( - chain: string, - walletAddress: string, - ): CancelablePromise<{ - result: { - nonce: number; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/backend-wallet/{chain}/{walletAddress}/get-nonce', - path: { - 'chain': chain, - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Simulate a transaction - * Simulate a transaction with transaction parameters - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public simulateTransaction( - chain: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The contract address - */ - toAddress: string; - /** - * The amount of native currency in wei - */ - value?: string; - /** - * The function to call on the contract - */ - functionName?: string; - /** - * The arguments to call for this function - */ - args?: Array<(string | number | boolean)>; - /** - * Raw calldata - */ - data?: string; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Simulation Success - */ - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/backend-wallet/{chain}/simulate-transaction', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ChainService.ts b/sdk/src/services/ChainService.ts deleted file mode 100644 index f2fb6e544..000000000 --- a/sdk/src/services/ChainService.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ChainService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get chain details - * Get details about a chain. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @returns any Default Response - * @throws ApiError - */ - public get( - chain: string, - ): CancelablePromise<{ - result: { - /** - * Chain name - */ - name?: string; - /** - * Chain name - */ - chain?: string; - rpc?: Array; - nativeCurrency?: { - /** - * Native currency name - */ - name: string; - /** - * Native currency symbol - */ - symbol: string; - /** - * Native currency decimals - */ - decimals: number; - }; - /** - * Chain short name - */ - shortName?: string; - /** - * Chain ID - */ - chainId?: number; - /** - * Is testnet - */ - testnet?: boolean; - /** - * Chain slug - */ - slug?: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/chain/get', - query: { - 'chain': chain, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all chain details - * Get details about all supported chains. - * @returns any Default Response - * @throws ApiError - */ - public getAll(): CancelablePromise<{ - result: Array<{ - /** - * Chain name - */ - name?: string; - /** - * Chain name - */ - chain?: string; - rpc?: Array; - nativeCurrency?: { - /** - * Native currency name - */ - name: string; - /** - * Native currency symbol - */ - symbol: string; - /** - * Native currency decimals - */ - decimals: number; - }; - /** - * Chain short name - */ - shortName?: string; - /** - * Chain ID - */ - chainId?: number; - /** - * Is testnet - */ - testnet?: boolean; - /** - * Chain slug - */ - slug?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/chain/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ConfigurationService.ts b/sdk/src/services/ConfigurationService.ts deleted file mode 100644 index 40de38b91..000000000 --- a/sdk/src/services/ConfigurationService.ts +++ /dev/null @@ -1,709 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ConfigurationService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get wallets configuration - * Get wallets configuration - * @returns any Default Response - * @throws ApiError - */ - public getWalletsConfiguration(): CancelablePromise<{ - result: { - type: ('local' | 'aws-kms' | 'gcp-kms' | 'smart:aws-kms' | 'smart:gcp-kms' | 'smart:local' | 'circle' | 'smart:circle'); - awsAccessKeyId: (string | null); - awsRegion: (string | null); - gcpApplicationProjectId: (string | null); - gcpKmsLocationId: (string | null); - gcpKmsKeyRingId: (string | null); - gcpApplicationCredentialEmail: (string | null); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/wallets', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update wallets configuration - * Update wallets configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateWalletsConfiguration( - requestBody?: ({ - awsAccessKeyId: string; - awsSecretAccessKey: string; - awsRegion: string; - } | { - gcpApplicationProjectId: string; - gcpKmsLocationId: string; - gcpKmsKeyRingId: string; - gcpApplicationCredentialEmail: string; - gcpApplicationCredentialPrivateKey: string; - } | { - circleApiKey: string; - }), - ): CancelablePromise<{ - result: { - type: ('local' | 'aws-kms' | 'gcp-kms' | 'smart:aws-kms' | 'smart:gcp-kms' | 'smart:local' | 'circle' | 'smart:circle'); - awsAccessKeyId: (string | null); - awsRegion: (string | null); - gcpApplicationProjectId: (string | null); - gcpKmsLocationId: (string | null); - gcpKmsKeyRingId: (string | null); - gcpApplicationCredentialEmail: (string | null); - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/wallets', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get chain overrides configuration - * Get chain overrides configuration - * @returns any Default Response - * @throws ApiError - */ - public getChainsConfiguration(): CancelablePromise<{ - result: Array<{ - /** - * Chain name - */ - name?: string; - /** - * Chain name - */ - chain?: string; - rpc?: Array; - nativeCurrency?: { - /** - * Native currency name - */ - name: string; - /** - * Native currency symbol - */ - symbol: string; - /** - * Native currency decimals - */ - decimals: number; - }; - /** - * Chain short name - */ - shortName?: string; - /** - * Chain ID - */ - chainId?: number; - /** - * Is testnet - */ - testnet?: boolean; - /** - * Chain slug - */ - slug?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/chains', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update chain overrides configuration - * Update chain overrides configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateChainsConfiguration( - requestBody: { - chainOverrides: Array<{ - /** - * Chain name - */ - name?: string; - /** - * Chain name - */ - chain?: string; - rpc?: Array; - nativeCurrency?: { - /** - * Native currency name - */ - name: string; - /** - * Native currency symbol - */ - symbol: string; - /** - * Native currency decimals - */ - decimals: number; - }; - /** - * Chain short name - */ - shortName?: string; - /** - * Chain ID - */ - chainId?: number; - /** - * Is testnet - */ - testnet?: boolean; - /** - * Chain slug - */ - slug?: string; - }>; - }, - ): CancelablePromise<{ - result: Array<{ - /** - * Chain name - */ - name?: string; - /** - * Chain name - */ - chain?: string; - rpc?: Array; - nativeCurrency?: { - /** - * Native currency name - */ - name: string; - /** - * Native currency symbol - */ - symbol: string; - /** - * Native currency decimals - */ - decimals: number; - }; - /** - * Chain short name - */ - shortName?: string; - /** - * Chain ID - */ - chainId?: number; - /** - * Is testnet - */ - testnet?: boolean; - /** - * Chain slug - */ - slug?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/chains', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get transaction processing configuration - * Get transactions processing configuration - * @returns any Default Response - * @throws ApiError - */ - public getTransactionConfiguration(): CancelablePromise<{ - result: { - minTxsToProcess: number; - maxTxsToProcess: number; - minedTxListenerCronSchedule: (string | null); - maxTxsToUpdate: number; - retryTxListenerCronSchedule: (string | null); - minEllapsedBlocksBeforeRetry: number; - maxFeePerGasForRetries: string; - maxPriorityFeePerGasForRetries: string; - maxRetriesPerTx: number; - clearCacheCronSchedule: (string | null); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/transactions', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update transaction processing configuration - * Update transaction processing configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateTransactionConfiguration( - requestBody?: { - maxTxsToProcess?: number; - maxTxsToUpdate?: number; - minedTxListenerCronSchedule?: (string | null); - retryTxListenerCronSchedule?: (string | null); - minEllapsedBlocksBeforeRetry?: number; - maxFeePerGasForRetries?: string; - maxRetriesPerTx?: number; - }, - ): CancelablePromise<{ - result: { - minTxsToProcess: number; - maxTxsToProcess: number; - minedTxListenerCronSchedule: (string | null); - maxTxsToUpdate: number; - retryTxListenerCronSchedule: (string | null); - minEllapsedBlocksBeforeRetry: number; - maxFeePerGasForRetries: string; - maxPriorityFeePerGasForRetries: string; - maxRetriesPerTx: number; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/transactions', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get auth configuration - * Get auth configuration - * @returns any Default Response - * @throws ApiError - */ - public getAuthConfiguration(): CancelablePromise<{ - result: { - authDomain: string; - mtlsCertificate: (string | null); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/auth', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update auth configuration - * Update auth configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateAuthConfiguration( - requestBody?: { - authDomain?: string; - /** - * Engine certificate used for outbound mTLS requests. Must provide the full certificate chain. - */ - mtlsCertificate?: string; - /** - * Engine private key used for outbound mTLS requests. - */ - mtlsPrivateKey?: string; - }, - ): CancelablePromise<{ - result: { - authDomain: string; - mtlsCertificate: (string | null); - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/auth', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get wallet-balance configuration - * Get wallet-balance configuration - * @returns any Default Response - * @throws ApiError - */ - public getBackendWalletBalanceConfiguration(): CancelablePromise<{ - result: { - /** - * Minimum wallet balance in wei - */ - minWalletBalance: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/backend-wallet-balance', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update backend wallet balance configuration - * Update backend wallet balance configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateBackendWalletBalanceConfiguration( - requestBody?: { - /** - * Minimum wallet balance in wei - */ - minWalletBalance?: string; - }, - ): CancelablePromise<{ - result: { - /** - * Minimum wallet balance in wei - */ - minWalletBalance: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/backend-wallet-balance', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get CORS configuration - * Get CORS configuration - * @returns any Default Response - * @throws ApiError - */ - public getCorsConfiguration(): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/cors', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Add a CORS URL - * Add a URL to allow client-side calls to Engine - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public addUrlToCorsConfiguration( - requestBody: { - urlsToAdd: Array; - }, - ): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/cors', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Remove CORS URLs - * Remove URLs from CORS configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public removeUrlToCorsConfiguration( - requestBody: { - urlsToRemove: Array; - }, - ): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'DELETE', - url: '/configuration/cors', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set CORS URLs - * Replaces the CORS URLs to allow client-side calls to Engine - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public setUrlsToCorsConfiguration( - requestBody: { - urls: Array; - }, - ): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'PUT', - url: '/configuration/cors', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get cache configuration - * Get cache configuration - * @returns any Default Response - * @throws ApiError - */ - public getCacheConfiguration(): CancelablePromise<{ - result: { - clearCacheCronSchedule: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/cache', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update cache configuration - * Update cache configuration - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateCacheConfiguration( - requestBody: { - /** - * Cron expression for clearing cache. It should be in the format of 'ss mm hh * * *' where ss is seconds, mm is minutes and hh is hours. Seconds should not be '*' or less than 10 - */ - clearCacheCronSchedule: string; - }, - ): CancelablePromise<{ - result: { - clearCacheCronSchedule: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/cache', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get Contract Subscriptions configuration - * Get the configuration for Contract Subscriptions - * @returns any Default Response - * @throws ApiError - */ - public getContractSubscriptionsConfiguration(): CancelablePromise<{ - result: { - maxBlocksToIndex: number; - contractSubscriptionsRequeryDelaySeconds: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/contract-subscriptions', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update Contract Subscriptions configuration - * Update the configuration for Contract Subscriptions - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public updateContractSubscriptionsConfiguration( - requestBody?: { - maxBlocksToIndex?: number; - /** - * Requery after one or more delays. Use comma-separated positive integers. Example: "2,10" means requery after 2s and 10s. - */ - contractSubscriptionsRequeryDelaySeconds?: string; - }, - ): CancelablePromise<{ - result: { - maxBlocksToIndex: number; - contractSubscriptionsRequeryDelaySeconds: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/configuration/contract-subscriptions', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get Allowed IP Addresses - * Get the list of allowed IP addresses - * @returns any Default Response - * @throws ApiError - */ - public getIpAllowlist(): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/configuration/ip-allowlist', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set IP Allowlist - * Replaces the IP Allowlist array to allow calls to Engine - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public setIpAllowlist( - requestBody: { - /** - * Array of IP addresses to allowlist - */ - ips: Array; - }, - ): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'PUT', - url: '/configuration/ip-allowlist', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ContractEventsService.ts b/sdk/src/services/ContractEventsService.ts deleted file mode 100644 index d799dd2ec..000000000 --- a/sdk/src/services/ContractEventsService.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ContractEventsService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all events - * Get a list of all blockchain events for this contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param fromBlock - * @param toBlock - * @param order - * @returns any Default Response - * @throws ApiError - */ - public getAllEvents( - chain: string, - contractAddress: string, - fromBlock?: (number | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'), - toBlock?: (number | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'), - order?: ('asc' | 'desc'), - ): CancelablePromise<{ - result: Array>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/events/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'fromBlock': fromBlock, - 'toBlock': toBlock, - 'order': order, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get events - * Get a list of specific blockchain events emitted from this contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody Specify the from and to block numbers to get events for, defaults to all blocks - * @returns any Default Response - * @throws ApiError - */ - public getEvents( - chain: string, - contractAddress: string, - requestBody: { - eventName: string; - fromBlock?: (number | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'); - toBlock?: (number | 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'); - order?: ('asc' | 'desc'); - filters?: any; - }, - ): CancelablePromise<{ - result: Array>; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/events/get', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ContractMetadataService.ts b/sdk/src/services/ContractMetadataService.ts deleted file mode 100644 index 7fb08c2f4..000000000 --- a/sdk/src/services/ContractMetadataService.ts +++ /dev/null @@ -1,209 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ContractMetadataService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get ABI - * Get the ABI of a contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAbi( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array<{ - type: string; - name?: string; - inputs?: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - outputs?: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - stateMutability?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/metadata/abi', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get events - * Get details of all events implemented by a contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getEvents( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array<{ - name: string; - inputs: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - outputs: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - comment?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/metadata/events', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get extensions - * Get all detected extensions for a contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getExtensions( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - /** - * Array of detected extension names - */ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/metadata/extensions', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get functions - * Get details of all functions implemented by the contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getFunctions( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array<{ - name: string; - inputs: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - outputs: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - comment?: string; - signature: string; - stateMutability: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/metadata/functions', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ContractRolesService.ts b/sdk/src/services/ContractRolesService.ts deleted file mode 100644 index 1810d20e1..000000000 --- a/sdk/src/services/ContractRolesService.ts +++ /dev/null @@ -1,281 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ContractRolesService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get wallets for role - * Get all wallets with a specific role for a contract. - * @param role The role to list wallet members - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getRole( - role: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/roles/get', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'role': role, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get wallets for all roles - * Get all wallets in each role for a contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAll( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - admin: Array; - transfer: Array; - minter: Array; - pauser: Array; - lister: Array; - asset: Array; - unwrap: Array; - factory: Array; - signer: Array; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/roles/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Grant role - * Grant a role to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public grant( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The role to grant - */ - role: string; - /** - * The address to grant the role to - */ - address: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/roles/grant', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke role - * Revoke a role from a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public revoke( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The role to revoke - */ - role: string; - /** - * The address to revoke the role from - */ - address: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/roles/revoke', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ContractRoyaltiesService.ts b/sdk/src/services/ContractRoyaltiesService.ts deleted file mode 100644 index 2d85046ee..000000000 --- a/sdk/src/services/ContractRoyaltiesService.ts +++ /dev/null @@ -1,291 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ContractRoyaltiesService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get royalty details - * Gets the royalty recipient and BPS (basis points) of the smart contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getDefaultRoyaltyInfo( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - /** - * The royalty fee in BPS (basis points). 100 = 1%. - */ - seller_fee_basis_points: number; - /** - * The wallet address that will receive the royalty fees. - */ - fee_recipient: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/royalties/get-default-royalty-info', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get token royalty details - * Gets the royalty recipient and BPS (basis points) of a particular token in the contract. - * @param tokenId - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getTokenRoyaltyInfo( - tokenId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - /** - * The royalty fee in BPS (basis points). 100 = 1%. - */ - seller_fee_basis_points: number; - /** - * The wallet address that will receive the royalty fees. - */ - fee_recipient: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/royalties/get-token-royalty-info/{tokenId}', - path: { - 'tokenId': tokenId, - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set royalty details - * Set the royalty recipient and fee for the smart contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setDefaultRoyaltyInfo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The royalty fee in BPS (basis points). 100 = 1%. - */ - seller_fee_basis_points: number; - /** - * The wallet address that will receive the royalty fees. - */ - fee_recipient: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/royalties/set-default-royalty-info', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set token royalty details - * Set the royalty recipient and fee for a particular token in the contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setTokenRoyaltyInfo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The royalty fee in BPS (basis points). 100 = 1%. - */ - seller_fee_basis_points: number; - /** - * The wallet address that will receive the royalty fees. - */ - fee_recipient: string; - /** - * The token ID to set the royalty info for. - */ - token_id: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/royalties/set-token-royalty-info', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/ContractService.ts b/sdk/src/services/ContractService.ts deleted file mode 100644 index caef13274..000000000 --- a/sdk/src/services/ContractService.ts +++ /dev/null @@ -1,213 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ContractService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Read from contract - * Call a read function on a contract. - * @param functionName Name of the function to call on Contract - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param args Arguments for the function. Comma Separated - * @returns any Default Response - * @throws ApiError - */ - public read( - functionName: string, - chain: string, - contractAddress: string, - args?: string, - ): CancelablePromise<{ - result: any; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/read', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'functionName': functionName, - 'args': args, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Batch read from multiple contracts - * Execute multiple contract read operations in a single call using Multicall - * @param chain - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public readBatch( - chain: string, - requestBody: { - calls: Array<{ - contractAddress: string; - functionName: string; - functionAbi?: string; - args?: Array; - }>; - /** - * Address of the multicall contract to use. If omitted, multicall3 contract will be used (0xcA11bde05977b3631167028862bE2a173976CA11). - */ - multicallAddress?: string; - }, - ): CancelablePromise<{ - results: Array<{ - success: boolean; - result: any; - }>; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/read-batch', - path: { - 'chain': chain, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Write to contract - * Call a write function on a contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public write( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The function to call on the contract. It is highly recommended to provide a full function signature, such as "function mintTo(address to, uint256 amount)", to avoid ambiguity and to skip ABI resolution. - */ - functionName: string; - /** - * An array of arguments to provide the function. Supports: numbers, strings, arrays, objects. Do not provide: BigNumber, bigint, Date objects - */ - args: Array; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - abi?: Array<{ - type: string; - name?: string; - inputs?: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - outputs?: Array<{ - type?: string; - name?: string; - internalType?: string; - stateMutability?: string; - components?: Array<{ - type?: string; - name?: string; - internalType?: string; - }>; - }>; - stateMutability?: string; - }>; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/write', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - }); - } - -} diff --git a/sdk/src/services/ContractSubscriptionsService.ts b/sdk/src/services/ContractSubscriptionsService.ts deleted file mode 100644 index 2bfbfcca1..000000000 --- a/sdk/src/services/ContractSubscriptionsService.ts +++ /dev/null @@ -1,230 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class ContractSubscriptionsService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get contract subscriptions - * Get all contract subscriptions. - * @returns any Default Response - * @throws ApiError - */ - public getContractSubscriptions(): CancelablePromise<{ - result: Array<{ - id: string; - chainId: number; - /** - * A contract or wallet address - */ - contractAddress: string; - webhook?: { - id: number; - url: string; - name: (string | null); - secret?: string; - eventType: string; - active: boolean; - createdAt: string; - }; - processEventLogs: boolean; - filterEvents: Array; - processTransactionReceipts: boolean; - filterFunctions: Array; - createdAt: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract-subscriptions/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Add contract subscription - * Subscribe to event logs and transaction receipts for a contract. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public addContractSubscription( - requestBody: { - /** - * A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - */ - chain: string; - /** - * The address for the contract. - */ - contractAddress: string; - /** - * Webhook URL - */ - webhookUrl?: string; - /** - * If true, parse event logs for this contract. - */ - processEventLogs: boolean; - /** - * A case-sensitive list of event names to filter event logs. Parses all event logs by default. - */ - filterEvents?: Array; - /** - * If true, parse transaction receipts for this contract. - */ - processTransactionReceipts: boolean; - /** - * A case-sensitive list of function names to filter transaction receipts. Parses all transaction receipts by default. - */ - filterFunctions?: Array; - }, - ): CancelablePromise<{ - result: { - id: string; - chainId: number; - /** - * A contract or wallet address - */ - contractAddress: string; - webhook?: { - id: number; - url: string; - name: (string | null); - secret?: string; - eventType: string; - active: boolean; - createdAt: string; - }; - processEventLogs: boolean; - filterEvents: Array; - processTransactionReceipts: boolean; - filterFunctions: Array; - createdAt: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract-subscriptions/add', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Remove contract subscription - * Remove an existing contract subscription - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public removeContractSubscription( - requestBody: { - /** - * The ID for an existing contract subscription. - */ - contractSubscriptionId: string; - }, - ): CancelablePromise<{ - result: { - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract-subscriptions/remove', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get subscribed contract indexed block range - * Gets the subscribed contract's indexed block range - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getContractIndexedBlockRange( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - /** - * A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - */ - chain: string; - /** - * A contract or wallet address - */ - contractAddress: string; - fromBlock: number; - toBlock: number; - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/subscriptions/get-indexed-blocks', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get last processed block - * Get the last processed block for a chain. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @returns any Default Response - * @throws ApiError - */ - public getLatestBlock( - chain: string, - ): CancelablePromise<{ - result: { - lastBlock: number; - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract-subscriptions/last-block', - query: { - 'chain': chain, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/DefaultService.ts b/sdk/src/services/DefaultService.ts deleted file mode 100644 index 54389d7a7..000000000 --- a/sdk/src/services/DefaultService.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class DefaultService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * @returns any Default Response - * @throws ApiError - */ - public getJson(): CancelablePromise { - return this.httpRequest.request({ - method: 'GET', - url: '/json', - }); - } - - /** - * @returns any Default Response - * @throws ApiError - */ - public getOpenapiJson(): CancelablePromise { - return this.httpRequest.request({ - method: 'GET', - url: '/openapi.json', - }); - } - - /** - * @returns any Default Response - * @throws ApiError - */ - public getJson1(): CancelablePromise { - return this.httpRequest.request({ - method: 'GET', - url: '/json/', - }); - } - -} diff --git a/sdk/src/services/DeployService.ts b/sdk/src/services/DeployService.ts deleted file mode 100644 index c865fc3a0..000000000 --- a/sdk/src/services/DeployService.ts +++ /dev/null @@ -1,1438 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class DeployService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Deploy Edition - * Deploy an Edition contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployEdition( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/edition', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Edition Drop - * Deploy an Edition Drop contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployEditionDrop( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - merkle?: Record; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/edition-drop', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Marketplace - * Deploy a Marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployMarketplaceV3( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/marketplace-v3', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Multiwrap - * Deploy a Multiwrap contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployMultiwrap( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - symbol: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/multiwrap', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy NFT Collection - * Deploy an NFT Collection contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployNftCollection( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/nft-collection', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy NFT Drop - * Deploy an NFT Drop contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployNftDrop( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - merkle?: Record; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/nft-drop', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Pack - * Deploy a Pack contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployPack( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/pack', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Signature Drop - * Deploy a Signature Drop contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deploySignatureDrop( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - seller_fee_basis_points: number; - fee_recipient: string; - merkle?: Record; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/signature-drop', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Split - * Deploy a Split contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deploySplit( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - recipients: Array<{ - /** - * A contract or wallet address - */ - address: string; - sharesBps: number; - }>; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/split', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Token - * Deploy a Token contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployToken( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/token', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Token Drop - * Deploy a Token Drop contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployTokenDrop( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - merkle?: Record; - symbol: string; - platform_fee_basis_points: number; - platform_fee_recipient: string; - primary_sale_recipient?: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/token-drop', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy Vote - * Deploy a Vote contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployVote( - chain: string, - xBackendWalletAddress: string, - requestBody: { - contractMetadata: { - name: string; - description?: string; - image?: string; - external_link?: string; - app_uri?: string; - defaultAdmin?: string; - voting_delay_in_blocks: number; - voting_period_in_blocks: number; - /** - * A contract or wallet address - */ - voting_token_address: string; - voting_quorum_fraction: number; - proposal_token_threshold: string; - trusted_forwarders: Array; - }; - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - queueId?: string; - /** - * A contract or wallet address - */ - deployedAddress?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/prebuilts/vote', - path: { - 'chain': chain, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Deploy published contract - * Deploy a published contract to the blockchain. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param publisher Address or ENS of the publisher of the contract - * @param contractName Name of the published contract to deploy - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public deployPublished( - chain: string, - publisher: string, - contractName: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Version of the contract to deploy. Defaults to latest. - */ - version?: string; - forceDirectDeploy?: boolean; - saltForProxyDeploy?: string; - compilerOptions?: { - compilerType: 'zksolc'; - compilerVersion?: string; - evmVersion?: string; - }; - /** - * Constructor arguments for the deployment. - */ - constructorParams: Array; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - queueId?: string; - /** - * Not all contracts return a deployed address. - */ - deployedAddress?: string; - message?: string; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/deploy/{chain}/{publisher}/{contractName}', - path: { - 'chain': chain, - 'publisher': publisher, - 'contractName': contractName, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get contract types - * Get all prebuilt contract types. - * @returns any Default Response - * @throws ApiError - */ - public contractTypes(): CancelablePromise<{ - result: Array; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/deploy/contract-types', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/Erc1155Service.ts b/sdk/src/services/Erc1155Service.ts deleted file mode 100644 index 2c0730372..000000000 --- a/sdk/src/services/Erc1155Service.ts +++ /dev/null @@ -1,2655 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class Erc1155Service { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get details - * Get the details for a token in an ERC-1155 contract. - * @param tokenId The tokenId of the NFT to retrieve - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @returns any Default Response - * @throws ApiError - */ - public get( - tokenId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - metadata: Record; - owner: string; - type: ('ERC1155' | 'ERC721' | 'metaplex'); - supply: string; - quantityOwned?: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/get', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all details - * Get details for all tokens in an ERC-1155 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param start The start token ID for paginated results. Defaults to 0. - * @param count The page count for paginated results. Defaults to 100. - * @returns any Default Response - * @throws ApiError - */ - public getAll( - chain: string, - contractAddress: string, - start?: number, - count?: number, - ): CancelablePromise<{ - result: Array<{ - metadata: Record; - owner: string; - type: ('ERC1155' | 'ERC721' | 'metaplex'); - supply: string; - quantityOwned?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'start': start, - 'count': count, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get owned tokens - * Get all tokens in an ERC-1155 contract owned by a specific wallet. - * @param walletAddress Address of the wallet to get NFTs for - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @returns any Default Response - * @throws ApiError - */ - public getOwned( - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array<{ - metadata: Record; - owner: string; - type: ('ERC1155' | 'ERC721' | 'metaplex'); - supply: string; - quantityOwned?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/get-owned', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get balance - * Get the balance of a specific wallet address for this ERC-1155 contract. - * @param walletAddress Address of the wallet to check NFT balance - * @param tokenId The tokenId of the NFT to check balance of - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @returns any Default Response - * @throws ApiError - */ - public balanceOf( - walletAddress: string, - tokenId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/balance-of', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'walletAddress': walletAddress, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check if approved transfers - * Check if the specific wallet has approved transfers from a specific operator wallet. - * @param ownerWallet Address of the wallet who owns the NFT - * @param operator Address of the operator to check approval on - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @returns any Default Response - * @throws ApiError - */ - public isApproved( - ownerWallet: string, - operator: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/is-approved', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'ownerWallet': ownerWallet, - 'operator': operator, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get total supply - * Get the total supply in circulation for this ERC-1155 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @returns any Default Response - * @throws ApiError - */ - public totalCount( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/total-count', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get total supply - * Get the total supply in circulation for this ERC-1155 contract. - * @param tokenId The tokenId of the NFT to retrieve - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @returns any Default Response - * @throws ApiError - */ - public totalSupply( - tokenId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/total-supply', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Generate signature - * Generate a signature granting access for another wallet to mint tokens from this ERC-1155 contract. This method is typically called by the token contract owner. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @param xThirdwebSdkVersion Override the thirdweb sdk version used. Example: "5" for v5 SDK compatibility. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public signatureGenerate( - chain: string, - contractAddress: string, - xBackendWalletAddress?: string, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - xThirdwebSdkVersion?: string, - requestBody?: ({ - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract. - */ - royaltyRecipient?: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract. - */ - royaltyBps?: number; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient?: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid?: string; - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress?: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price?: string; - mintStartTime?: (string | number); - mintEndTime?: (string | number); - } | ({ - contractType?: ('TokenERC1155' | 'SignatureMintERC1155'); - to: string; - quantity: string; - royaltyRecipient?: string; - royaltyBps?: number; - primarySaleRecipient?: string; - /** - * An amount in native token (decimals allowed). Example: "0.1" - */ - pricePerToken?: string; - /** - * An amount in wei (no decimals). Example: "50000000000" - */ - pricePerTokenWei?: string; - currency?: string; - validityStartTimestamp: number; - validityEndTimestamp?: number; - uid?: string; - } & ({ - metadata: ({ - /** - * The name of the NFT - */ - name?: string; - /** - * The description of the NFT - */ - description?: string; - /** - * The image of the NFT - */ - image?: string; - /** - * The animation url of the NFT - */ - animation_url?: string; - /** - * The external url of the NFT - */ - external_url?: string; - /** - * The background color of the NFT - */ - background_color?: string; - /** - * (not recommended - use "attributes") The properties of the NFT. - */ - properties?: any; - /** - * Arbitrary metadata for this item. - */ - attributes?: Array<{ - trait_type: string; - value: string; - }>; - } | string); - } | { - tokenId: string; - }))), - ): CancelablePromise<{ - result: ({ - payload: { - uri: string; - tokenId: string; - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract. - */ - royaltyRecipient: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract. - */ - royaltyBps: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price: string; - /** - * The time from which the signature can be used to mint tokens. Defaults to now if value not provided. - */ - mintStartTime: number; - /** - * The time until which the signature can be used to mint tokens. Defaults to 10 years from now. - */ - mintEndTime: number; - }; - signature: string; - } | { - payload: { - to: string; - royaltyRecipient: string; - royaltyBps: string; - primarySaleRecipient: string; - tokenId: string; - uri: string; - quantity: string; - pricePerToken: string; - currency: string; - validityStartTimestamp: number; - validityEndTimestamp: number; - uid: string; - }; - signature: string; - }); - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/signature/generate', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - 'x-thirdweb-sdk-version': xThirdwebSdkVersion, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check if tokens are available for claiming - * Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim. - * @param quantity The amount of tokens to claim. - * @param tokenId The token ID of the NFT you want to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param addressToCheck The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc. - * @returns any Default Response - * @throws ApiError - */ - public canClaim( - quantity: string, - tokenId: string, - chain: string, - contractAddress: string, - addressToCheck?: string, - ): CancelablePromise<{ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/can-claim', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'quantity': quantity, - 'tokenId': tokenId, - 'addressToCheck': addressToCheck, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get currently active claim phase for a specific token ID. - * Retrieve the currently active claim phase for a specific token ID, if any. - * @param tokenId The token ID of the NFT you want to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param withAllowList Provide a boolean value to include the allowlist in the response. - * @returns any Default Response - * @throws ApiError - */ - public getActiveClaimConditions( - tokenId: (string | number), - chain: string, - contractAddress: string, - withAllowList?: boolean, - ): CancelablePromise<{ - result: { - maxClaimableSupply?: (string | number); - startTime: string; - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash: (string | Array); - availableSupply: string; - currentMintSupply: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyMetadata: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - metadata?: { - name?: string; - }; - snapshot?: (null | Array); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-active', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - 'withAllowList': withAllowList, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all the claim phases configured for a specific token ID. - * Get all the claim phases configured for a specific token ID. - * @param tokenId The token ID of the NFT you want to get the claim conditions for. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param withAllowList Provide a boolean value to include the allowlist in the response. - * @returns any Default Response - * @throws ApiError - */ - public getAllClaimConditions( - tokenId: (string | number), - chain: string, - contractAddress: string, - withAllowList?: boolean, - ): CancelablePromise<{ - result: Array<{ - maxClaimableSupply?: (string | number); - startTime: string; - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash: (string | Array); - availableSupply: string; - currentMintSupply: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyMetadata: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - metadata?: { - name?: string; - }; - snapshot?: (null | Array); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - 'withAllowList': withAllowList, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claimer proofs - * Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address. - * @param tokenId The token ID of the NFT you want to get the claimer proofs for. - * @param walletAddress The wallet address to get the merkle proofs for. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getClaimerProofs( - tokenId: (string | number), - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: (null | { - price?: string; - /** - * A contract or wallet address - */ - currencyAddress?: string; - /** - * A contract or wallet address - */ - address: string; - maxClaimable: string; - proof: Array; - }); - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-claimer-proofs', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claim ineligibility reasons - * Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any. - * @param tokenId The token ID of the NFT you want to check if the wallet address can claim. - * @param quantity The amount of tokens to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param addressToCheck The wallet address to check if it can claim tokens. - * @returns any Default Response - * @throws ApiError - */ - public getClaimIneligibilityReasons( - tokenId: (string | number), - quantity: string, - chain: string, - contractAddress: string, - addressToCheck?: string, - ): CancelablePromise<{ - result: Array<(string | ('There is not enough supply to claim.' | 'This address is not on the allowlist.' | 'Not enough time since last claim transaction. Please wait.' | 'Claim phase has not started yet.' | 'You have already claimed the token.' | 'Incorrect price or currency.' | 'Cannot claim more than maximum allowed quantity.' | 'There are not enough tokens in the wallet to pay for the claim.' | 'There is no active claim phase at the moment. Please check back in later.' | 'There is no claim condition set.' | 'No wallet connected.' | 'No claim conditions found.'))>; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/get-claim-ineligibility-reasons', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - 'quantity': quantity, - 'addressToCheck': addressToCheck, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Airdrop tokens - * Airdrop ERC-1155 tokens to specific wallets. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public airdrop( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Token ID of the NFT to airdrop - */ - tokenId: string; - /** - * Addresses and quantities to airdrop to - */ - addresses: Array<{ - /** - * A contract or wallet address - */ - address: string; - quantity: string; - }>; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/airdrop', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Burn token - * Burn ERC-1155 tokens in the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public burn( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The token ID to burn - */ - tokenId: string; - /** - * The amount of tokens to burn - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/burn', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Burn tokens (batch) - * Burn a batch of ERC-1155 tokens in the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public burnBatch( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - tokenIds: Array; - amounts: Array; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/burn-batch', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Claim tokens to wallet - * Claim ERC-1155 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public claimTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to claim the NFT to - */ - receiver: string; - /** - * Token ID of the NFT to claim - */ - tokenId: string; - /** - * Quantity of NFTs to mint - */ - quantity: string; - /** - * Whether the drop is a single phase drop - */ - singlePhaseDrop?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Lazy mint - * Lazy mint ERC-1155 tokens to be claimed in the future. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public lazyMint( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - metadatas: Array<({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string)>; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/lazy-mint', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint additional supply - * Mint additional supply of ERC-1155 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintAdditionalSupplyTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to mint the NFT to - */ - receiver: string; - /** - * Token ID to mint additional supply to - */ - tokenId: string; - /** - * The amount of supply to mint - */ - additionalSupply: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/mint-additional-supply-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint tokens (batch) - * Mint ERC-1155 tokens to multiple wallets in one transaction. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintBatchTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to mint the NFT to - */ - receiver: string; - metadataWithSupply: Array<{ - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - supply: string; - }>; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/mint-batch-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint tokens - * Mint ERC-1155 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to mint the NFT to - */ - receiver: string; - metadataWithSupply: { - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - supply: string; - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/mint-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set approval for all - * Approve or remove operator as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setApprovalForAll( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the operator to give approval to - */ - operator: string; - /** - * whether to approve or revoke approval - */ - approved: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/set-approval-for-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer token - * Transfer an ERC-1155 token from the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public transfer( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The recipient address. - */ - to: string; - /** - * The token ID to transfer. - */ - tokenId: string; - /** - * The amount of tokens to transfer. - */ - amount: string; - /** - * A valid hex string - */ - data?: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/transfer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer token from wallet - * Transfer an ERC-1155 token from the connected wallet to another wallet. Requires allowance. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC1155 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public transferFrom( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The sender address. - */ - from: string; - /** - * The recipient address. - */ - to: string; - /** - * The token ID to transfer. - */ - tokenId: string; - /** - * The amount of tokens to transfer. - */ - amount: string; - /** - * A valid hex string - */ - data?: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/transfer-from', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Signature mint - * Mint ERC-1155 tokens from a generated signature. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public signatureMint( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - payload: { - uri: string; - tokenId: string; - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract. - */ - royaltyRecipient: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract. - */ - royaltyBps: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price: string; - /** - * The time from which the signature can be used to mint tokens. Defaults to now if value not provided. - */ - mintStartTime: number; - /** - * The time until which the signature can be used to mint tokens. Defaults to 10 years from now. - */ - mintEndTime: number; - }; - signature: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/signature/mint', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Overwrite the claim conditions for a specific token ID.. - * Overwrite the claim conditions for a specific token ID. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setClaimConditions( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * ID of the token to set the claim conditions for - */ - tokenId: (string | number); - claimConditionInputs: Array<{ - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }>; - resetClaimEligibilityForAll?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/set', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Overwrite the claim conditions for a specific token ID.. - * Allows you to set claim conditions for multiple token IDs in a single transaction. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public claimConditionsUpdate( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - claimConditionsForToken: Array<{ - /** - * ID of the token to set the claim conditions for - */ - tokenId: (string | number); - claimConditions: Array<{ - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }>; - }>; - resetClaimEligibilityForAll?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/set-batch', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update a single claim phase. - * Update a single claim phase on a specific token ID, by providing the index of the claim phase and the new phase configuration. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateClaimConditions( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Token ID to update claim phase for - */ - tokenId: (string | number); - claimConditionInput: { - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }; - /** - * Index of the claim condition to update - */ - index: number; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/claim-conditions/update', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update token metadata - * Update the metadata for an ERC1155 token. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateTokenMetadata( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Token ID to update metadata - */ - tokenId: string; - metadata: { - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc1155/token/update', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/Erc20Service.ts b/sdk/src/services/Erc20Service.ts deleted file mode 100644 index ba1c0005c..000000000 --- a/sdk/src/services/Erc20Service.ts +++ /dev/null @@ -1,1708 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class Erc20Service { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get token allowance - * Get the allowance of a specific wallet for an ERC-20 contract. - * @param ownerWallet Address of the wallet who owns the funds - * @param spenderWallet Address of the wallet to check token allowance - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @returns any Default Response - * @throws ApiError - */ - public allowanceOf( - ownerWallet: string, - spenderWallet: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - name: string; - symbol: string; - decimals: string; - /** - * Value in wei - */ - value: string; - /** - * Value in tokens - */ - displayValue: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/allowance-of', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'ownerWallet': ownerWallet, - 'spenderWallet': spenderWallet, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get token balance - * Get the balance of a specific wallet address for this ERC-20 contract. - * @param walletAddress Address of the wallet to check token balance - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @returns any Default Response - * @throws ApiError - */ - public balanceOf( - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - name: string; - symbol: string; - decimals: string; - /** - * Value in wei - */ - value: string; - /** - * Value in tokens - */ - displayValue: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/balance-of', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'wallet_address': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get token details - * Get details for this ERC-20 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @returns any Default Response - * @throws ApiError - */ - public get( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - name: string; - symbol: string; - decimals: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/get', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get total supply - * Get the total supply in circulation for this ERC-20 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @returns any Default Response - * @throws ApiError - */ - public totalSupply( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - name: string; - symbol: string; - decimals: string; - /** - * Value in wei - */ - value: string; - /** - * Value in tokens - */ - displayValue: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/total-supply', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Generate signature - * Generate a signature granting access for another wallet to mint tokens from this ERC-20 contract. This method is typically called by the token contract owner. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @param xThirdwebSdkVersion Override the thirdweb sdk version used. Example: "5" for v5 SDK compatibility. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public signatureGenerate( - chain: string, - contractAddress: string, - xBackendWalletAddress?: string, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - xThirdwebSdkVersion?: string, - requestBody?: ({ - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient?: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid?: string; - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress?: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price?: string; - mintStartTime?: (string | number); - mintEndTime?: (string | number); - } | ({ - to: string; - primarySaleRecipient?: string; - price?: string; - priceInWei?: string; - currency?: string; - validityStartTimestamp: number; - validityEndTimestamp?: number; - uid?: string; - } & ({ - quantity: string; - } | { - quantityWei: string; - }))), - ): CancelablePromise<{ - result: ({ - payload: { - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid: string; - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price: string; - /** - * The time from which the signature can be used to mint tokens. Defaults to now. - */ - mintStartTime: number; - /** - * The time until which the signature can be used to mint tokens. Defaults to 10 years from now. - */ - mintEndTime: number; - }; - signature: string; - } | { - payload: { - to: string; - primarySaleRecipient: string; - quantity: string; - price: string; - currency: string; - validityStartTimestamp: number; - validityEndTimestamp: number; - uid: string; - }; - signature: string; - }); - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/signature/generate', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - 'x-thirdweb-sdk-version': xThirdwebSdkVersion, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check if tokens are available for claiming - * Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim. - * @param quantity The amount of tokens to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param addressToCheck The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc. - * @returns any Default Response - * @throws ApiError - */ - public canClaim( - quantity: string, - chain: string, - contractAddress: string, - addressToCheck?: string, - ): CancelablePromise<{ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/can-claim', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'quantity': quantity, - 'addressToCheck': addressToCheck, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Retrieve the currently active claim phase, if any. - * Retrieve the currently active claim phase, if any. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param withAllowList Provide a boolean value to include the allowlist in the response. - * @returns any Default Response - * @throws ApiError - */ - public getActiveClaimConditions( - chain: string, - contractAddress: string, - withAllowList?: boolean, - ): CancelablePromise<{ - result: { - maxClaimableSupply?: (string | number); - startTime: string; - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash: (string | Array); - availableSupply: string; - currentMintSupply: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyMetadata: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - metadata?: { - name?: string; - }; - snapshot?: (null | Array); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-active', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'withAllowList': withAllowList, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all the claim phases configured. - * Get all the claim phases configured on the drop contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param withAllowList Provide a boolean value to include the allowlist in the response. - * @returns any Default Response - * @throws ApiError - */ - public getAllClaimConditions( - chain: string, - contractAddress: string, - withAllowList?: boolean, - ): CancelablePromise<{ - result: Array<{ - maxClaimableSupply?: (string | number); - startTime: string; - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash: (string | Array); - availableSupply: string; - currentMintSupply: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyMetadata: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - metadata?: { - name?: string; - }; - snapshot?: (null | Array); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'withAllowList': withAllowList, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claim ineligibility reasons - * Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any. - * @param quantity The amount of tokens to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param addressToCheck The wallet address to check if it can claim tokens. - * @returns any Default Response - * @throws ApiError - */ - public claimConditionsGetClaimIneligibilityReasons( - quantity: string, - chain: string, - contractAddress: string, - addressToCheck?: string, - ): CancelablePromise<{ - result: Array<(string | ('There is not enough supply to claim.' | 'This address is not on the allowlist.' | 'Not enough time since last claim transaction. Please wait.' | 'Claim phase has not started yet.' | 'You have already claimed the token.' | 'Incorrect price or currency.' | 'Cannot claim more than maximum allowed quantity.' | 'There are not enough tokens in the wallet to pay for the claim.' | 'There is no active claim phase at the moment. Please check back in later.' | 'There is no claim condition set.' | 'No wallet connected.' | 'No claim conditions found.'))>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-claim-ineligibility-reasons', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'quantity': quantity, - 'addressToCheck': addressToCheck, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claimer proofs - * Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address. - * @param walletAddress The wallet address to get the merkle proofs for. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public claimConditionsGetClaimerProofs( - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: (null | { - price?: string; - /** - * A contract or wallet address - */ - currencyAddress?: string; - /** - * A contract or wallet address - */ - address: string; - maxClaimable: string; - proof: Array; - }); - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/get-claimer-proofs', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set allowance - * Grant a specific wallet address to transfer ERC-20 tokens from the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setAllowance( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to allow transfers from - */ - spenderAddress: string; - /** - * The number of tokens to give as allowance - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/set-allowance', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer tokens - * Transfer ERC-20 tokens from the caller wallet to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public transfer( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The recipient address. - */ - toAddress: string; - /** - * The amount of tokens to transfer. - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/transfer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer tokens from wallet - * Transfer ERC-20 tokens from the connected wallet to another wallet. Requires allowance. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public transferFrom( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The sender address. - */ - fromAddress: string; - /** - * The recipient address. - */ - toAddress: string; - /** - * The amount of tokens to transfer. - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/transfer-from', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Burn token - * Burn ERC-20 tokens in the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public burn( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The amount of tokens you want to burn - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/burn', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Burn token from wallet - * Burn ERC-20 tokens in a specific wallet. Requires allowance. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public burnFrom( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet sending the tokens - */ - holderAddress: string; - /** - * The amount of this token you want to burn - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/burn-from', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Claim tokens to wallet - * Claim ERC-20 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public claimTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The wallet address to receive the claimed tokens. - */ - recipient: string; - /** - * The amount of tokens to claim. - */ - amount: string; - /** - * Whether the drop is a single phase drop - */ - singlePhaseDrop?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/claim-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint tokens (batch) - * Mint ERC-20 tokens to multiple wallets in one transaction. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintBatchTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - data: Array<{ - /** - * The address to mint tokens to - */ - toAddress: string; - /** - * The number of tokens to mint to the specific address. - */ - amount: string; - }>; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/mint-batch-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint tokens - * Mint ERC-20 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC20 contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to mint tokens to - */ - toAddress: string; - /** - * The amount of tokens you want to send - */ - amount: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/mint-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Signature mint - * Mint ERC-20 tokens from a generated signature. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public signatureMint( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - payload: { - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid: string; - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price: string; - /** - * The time from which the signature can be used to mint tokens. Defaults to now. - */ - mintStartTime: number; - /** - * The time until which the signature can be used to mint tokens. Defaults to 10 years from now. - */ - mintEndTime: number; - }; - signature: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/signature/mint', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Overwrite the claim conditions for the drop. - * Overwrite the claim conditions for the drop. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setClaimConditions( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - claimConditionInputs: Array<{ - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }>; - resetClaimEligibilityForAll?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/set', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update a single claim phase. - * Update a single claim phase, by providing the index of the claim phase and the new phase configuration. The index is the position of the phase in the list of phases you have made, starting from zero. e.g. if you have two phases, the first phase has an index of 0 and the second phase has an index of 1. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateClaimConditions( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - claimConditionInput: { - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }; - /** - * Index of the claim condition to update - */ - index: number; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc20/claim-conditions/update', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/Erc721Service.ts b/sdk/src/services/Erc721Service.ts deleted file mode 100644 index e4d8095bb..000000000 --- a/sdk/src/services/Erc721Service.ts +++ /dev/null @@ -1,2518 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class Erc721Service { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get details - * Get the details for a token in an ERC-721 contract. - * @param tokenId The tokenId of the NFT to retrieve - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public get( - tokenId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - metadata: Record; - owner: string; - type: ('ERC1155' | 'ERC721' | 'metaplex'); - supply: string; - quantityOwned?: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/get', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all details - * Get details for all tokens in an ERC-721 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param start The start token id for paginated results. Defaults to 0. - * @param count The page count for paginated results. Defaults to 100. - * @returns any Default Response - * @throws ApiError - */ - public getAll( - chain: string, - contractAddress: string, - start?: number, - count?: number, - ): CancelablePromise<{ - result: Array<{ - metadata: Record; - owner: string; - type: ('ERC1155' | 'ERC721' | 'metaplex'); - supply: string; - quantityOwned?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'start': start, - 'count': count, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get owned tokens - * Get all tokens in an ERC-721 contract owned by a specific wallet. - * @param walletAddress Address of the wallet to get NFTs for - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getOwned( - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: Array<{ - metadata: Record; - owner: string; - type: ('ERC1155' | 'ERC721' | 'metaplex'); - supply: string; - quantityOwned?: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/get-owned', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get token balance - * Get the balance of a specific wallet address for this ERC-721 contract. - * @param walletAddress Address of the wallet to check NFT balance - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC721 contract address - * @returns any Default Response - * @throws ApiError - */ - public balanceOf( - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/balance-of', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check if approved transfers - * Check if the specific wallet has approved transfers from a specific operator wallet. - * @param ownerWallet Address of the wallet who owns the NFT - * @param operator Address of the operator to check approval on - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public isApproved( - ownerWallet: string, - operator: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/is-approved', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'ownerWallet': ownerWallet, - 'operator': operator, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get total supply - * Get the total supply in circulation for this ERC-721 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public totalCount( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/total-count', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claimed supply - * Get the claimed supply for this ERC-721 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public totalClaimedSupply( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/total-claimed-supply', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get unclaimed supply - * Get the unclaimed supply for this ERC-721 contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public totalUnclaimedSupply( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/total-unclaimed-supply', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check if tokens are available for claiming - * Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim. - * @param quantity The amount of tokens to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param addressToCheck The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc. - * @returns any Default Response - * @throws ApiError - */ - public canClaim( - quantity: string, - chain: string, - contractAddress: string, - addressToCheck?: string, - ): CancelablePromise<{ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/can-claim', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'quantity': quantity, - 'addressToCheck': addressToCheck, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Retrieve the currently active claim phase, if any. - * Retrieve the currently active claim phase, if any. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param withAllowList Provide a boolean value to include the allowlist in the response. - * @returns any Default Response - * @throws ApiError - */ - public getActiveClaimConditions( - chain: string, - contractAddress: string, - withAllowList?: boolean, - ): CancelablePromise<{ - result: { - maxClaimableSupply?: (string | number); - startTime: string; - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash: (string | Array); - availableSupply: string; - currentMintSupply: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyMetadata: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - metadata?: { - name?: string; - }; - snapshot?: (null | Array); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-active', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'withAllowList': withAllowList, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all the claim phases configured for the drop. - * Get all the claim phases configured for the drop. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param withAllowList Provide a boolean value to include the allowlist in the response. - * @returns any Default Response - * @throws ApiError - */ - public getAllClaimConditions( - chain: string, - contractAddress: string, - withAllowList?: boolean, - ): CancelablePromise<{ - result: Array<{ - maxClaimableSupply?: (string | number); - startTime: string; - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash: (string | Array); - availableSupply: string; - currentMintSupply: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyMetadata: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - metadata?: { - name?: string; - }; - snapshot?: (null | Array); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'withAllowList': withAllowList, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claim ineligibility reasons - * Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any. - * @param quantity The amount of tokens to claim. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param addressToCheck The wallet address to check if it can claim tokens. - * @returns any Default Response - * @throws ApiError - */ - public getClaimIneligibilityReasons( - quantity: string, - chain: string, - contractAddress: string, - addressToCheck?: string, - ): CancelablePromise<{ - result: Array<(string | ('There is not enough supply to claim.' | 'This address is not on the allowlist.' | 'Not enough time since last claim transaction. Please wait.' | 'Claim phase has not started yet.' | 'You have already claimed the token.' | 'Incorrect price or currency.' | 'Cannot claim more than maximum allowed quantity.' | 'There are not enough tokens in the wallet to pay for the claim.' | 'There is no active claim phase at the moment. Please check back in later.' | 'There is no claim condition set.' | 'No wallet connected.' | 'No claim conditions found.'))>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-claim-ineligibility-reasons', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'quantity': quantity, - 'addressToCheck': addressToCheck, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get claimer proofs - * Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address. - * @param walletAddress The wallet address to get the merkle proofs for. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getClaimerProofs( - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: (null | { - price?: string; - /** - * A contract or wallet address - */ - currencyAddress?: string; - /** - * A contract or wallet address - */ - address: string; - maxClaimable: string; - proof: Array; - }); - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/get-claimer-proofs', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set approval for all - * Approve or remove operator as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setApprovalForAll( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the operator to give approval to - */ - operator: string; - /** - * whether to approve or revoke approval - */ - approved: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/set-approval-for-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Set approval for token - * Approve an operator for the NFT owner. Operators can call transferFrom or safeTransferFrom for the specific token. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setApprovalForToken( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the operator to give approval to - */ - operator: string; - /** - * the tokenId to give approval for - */ - tokenId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/set-approval-for-token', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer token - * Transfer an ERC-721 token from the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public transfer( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The recipient address. - */ - to: string; - /** - * The token ID to transfer. - */ - tokenId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/transfer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer token from wallet - * Transfer an ERC-721 token from the connected wallet to another wallet. Requires allowance. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public transferFrom( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The sender address. - */ - from: string; - /** - * The recipient address. - */ - to: string; - /** - * The token ID to transfer. - */ - tokenId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/transfer-from', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint tokens - * Mint ERC-721 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to mint the NFT to - */ - receiver: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/mint-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Mint tokens (batch) - * Mint ERC-721 tokens to multiple wallets in one transaction. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public mintBatchTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to mint the NFT to - */ - receiver: string; - metadatas: Array<({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string)>; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/mint-batch-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Burn token - * Burn ERC-721 tokens in the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public burn( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The token ID to burn - */ - tokenId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/burn', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Lazy mint - * Lazy mint ERC-721 tokens to be claimed in the future. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public lazyMint( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - metadatas: Array<({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string)>; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/lazy-mint', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Claim tokens to wallet - * Claim ERC-721 tokens to a specific wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public claimTo( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Address of the wallet to claim the NFT to - */ - receiver: string; - /** - * Quantity of NFTs to mint - */ - quantity: string; - /** - * Whether the drop is a single phase drop - */ - singlePhaseDrop?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/claim-to', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Generate signature - * Generate a signature granting access for another wallet to mint tokens from this ERC-721 contract. This method is typically called by the token contract owner. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC721 contract address - * @param xBackendWalletAddress Backend wallet address - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @param xThirdwebSdkVersion Override the thirdweb sdk version used. Example: "5" for v5 SDK compatibility. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public signatureGenerate( - chain: string, - contractAddress: string, - xBackendWalletAddress?: string, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - xThirdwebSdkVersion?: string, - requestBody?: ({ - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract. - */ - royaltyRecipient?: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity?: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract. - */ - royaltyBps?: number; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient?: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid?: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress?: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price?: string; - mintStartTime?: (string | number); - mintEndTime?: (string | number); - } | { - metadata: (string | { - /** - * The name of the NFT - */ - name?: string; - /** - * The description of the NFT - */ - description?: string; - /** - * The image of the NFT - */ - image?: string; - /** - * The animation url of the NFT - */ - animation_url?: string; - /** - * The external url of the NFT - */ - external_url?: string; - /** - * The background color of the NFT - */ - background_color?: string; - /** - * (not recommended - use "attributes") The properties of the NFT. - */ - properties?: any; - /** - * Arbitrary metadata for this item. - */ - attributes?: Array<{ - trait_type: string; - value: string; - }>; - }); - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The amount of the "currency" token this token costs. Example: "0.1" - */ - price?: string; - /** - * The amount of the "currency" token this token costs in wei. Remember to use the correct decimals amount for the currency. Example: "100000000000000000" = 0.1 ETH (18 decimals) - */ - priceInWei?: string; - /** - * The currency address to pay for minting the tokens. Defaults to the chain's native token. - */ - currency?: string; - /** - * If a price is specified, funds will be sent to the "primarySaleRecipient" address. Defaults to the "primarySaleRecipient" address of the contract. - */ - primarySaleRecipient?: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the "royaltyRecipient" address of the contract. - */ - royaltyRecipient?: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the "royaltyBps" of the contract. - */ - royaltyBps?: number; - /** - * The start time (in Unix seconds) when the signature can be used to mint. Default: now - */ - validityStartTimestamp?: number; - /** - * The end time (in Unix seconds) when the signature can be used to mint. Default: 10 years - */ - validityEndTimestamp?: number; - /** - * The uid is a unique identifier hashed in the payload to prevent replay attacks, ensuring it's only used once on-chain. - */ - uid?: string; - }), - ): CancelablePromise<{ - result: ({ - payload: { - uri: string; - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract. - */ - royaltyRecipient: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract. - */ - royaltyBps: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price?: string; - /** - * The time from which the signature can be used to mint tokens. Defaults to now. - */ - mintStartTime: number; - /** - * The time until which the signature can be used to mint tokens. Defaults to 10 years from now. - */ - mintEndTime: number; - }; - signature: string; - } | { - payload: { - uri: string; - to: string; - price: string; - /** - * A contract or wallet address - */ - currency: string; - primarySaleRecipient: string; - royaltyRecipient: string; - royaltyBps: string; - validityStartTimestamp: number; - validityEndTimestamp: number; - uid: string; - }; - signature: string; - }); - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/signature/generate', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - 'x-thirdweb-sdk-version': xThirdwebSdkVersion, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Signature mint - * Mint ERC-721 tokens from a generated signature. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public signatureMint( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - payload: ({ - uri: string; - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract. - */ - royaltyRecipient: string; - /** - * The number of tokens this signature can be used to mint. - */ - quantity: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract. - */ - royaltyBps: string; - /** - * If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract. - */ - primarySaleRecipient: string; - /** - * A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - * Note that the input value gets hashed in the actual payload that gets generated. - * The smart contract enforces on-chain that no uid gets used more than once, - * which means you can deterministically generate the uid to prevent specific exploits. - */ - uid: string; - metadata: ({ - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - } | string); - /** - * The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS - */ - currencyAddress: string; - /** - * If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0. - */ - price?: string; - /** - * The time from which the signature can be used to mint tokens. Defaults to now. - */ - mintStartTime: number; - /** - * The time until which the signature can be used to mint tokens. Defaults to 10 years from now. - */ - mintEndTime: number; - } | { - uri: string; - to: string; - price: string; - /** - * A contract or wallet address - */ - currency: string; - primarySaleRecipient: string; - royaltyRecipient: string; - royaltyBps: string; - validityStartTimestamp: number; - validityEndTimestamp: number; - uid: string; - }); - signature: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/signature/mint', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Overwrite the claim conditions for the drop. - * Overwrite the claim conditions for the drop. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public setClaimConditions( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - claimConditionInputs: Array<{ - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }>; - resetClaimEligibilityForAll?: boolean; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/set', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update a single claim phase. - * Update a single claim phase, by providing the index of the claim phase and the new phase configuration. The index is the position of the phase in the list of phases you have made, starting from zero. e.g. if you have two phases, the first phase has an index of 0 and the second phase has an index of 1. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateClaimConditions( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - claimConditionInput: { - maxClaimableSupply?: (string | number); - startTime?: (string | number); - price?: (number | string); - /** - * A contract or wallet address - */ - currencyAddress?: string; - maxClaimablePerWallet?: (number | string); - waitInSeconds?: (number | string); - merkleRootHash?: (string | Array); - metadata?: { - name?: string; - }; - snapshot?: (Array | null); - }; - /** - * Index of the claim condition to update - */ - index: number; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/claim-conditions/update', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Prepare signature - * Prepares a payload for a wallet to generate a signature. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress ERC721 contract address - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public signaturePrepare( - chain: string, - contractAddress: string, - requestBody: { - metadata: (string | { - /** - * The name of the NFT - */ - name?: string; - /** - * The description of the NFT - */ - description?: string; - /** - * The image of the NFT - */ - image?: string; - /** - * The animation url of the NFT - */ - animation_url?: string; - /** - * The external url of the NFT - */ - external_url?: string; - /** - * The background color of the NFT - */ - background_color?: string; - /** - * (not recommended - use "attributes") The properties of the NFT. - */ - properties?: any; - /** - * Arbitrary metadata for this item. - */ - attributes?: Array<{ - trait_type: string; - value: string; - }>; - }); - /** - * The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves. - */ - to: string; - /** - * The amount of the "currency" token this token costs. Example: "0.1" - */ - price?: string; - /** - * The amount of the "currency" token this token costs in wei. Remember to use the correct decimals amount for the currency. Example: "100000000000000000" = 0.1 ETH (18 decimals) - */ - priceInWei?: string; - /** - * The currency address to pay for minting the tokens. Defaults to the chain's native token. - */ - currency?: string; - /** - * If a price is specified, funds will be sent to the "primarySaleRecipient" address. Defaults to the "primarySaleRecipient" address of the contract. - */ - primarySaleRecipient?: string; - /** - * The address that will receive the royalty fees from secondary sales. Defaults to the "royaltyRecipient" address of the contract. - */ - royaltyRecipient?: string; - /** - * The percentage fee you want to charge for secondary sales. Defaults to the "royaltyBps" of the contract. - */ - royaltyBps?: number; - /** - * The start time (in Unix seconds) when the signature can be used to mint. Default: now - */ - validityStartTimestamp?: number; - /** - * The end time (in Unix seconds) when the signature can be used to mint. Default: 10 years - */ - validityEndTimestamp?: number; - /** - * The uid is a unique identifier hashed in the payload to prevent replay attacks, ensuring it's only used once on-chain. - */ - uid?: string; - }, - ): CancelablePromise<{ - result: { - mintPayload: { - uri: string; - to: string; - price: string; - /** - * A contract or wallet address - */ - currency: string; - primarySaleRecipient: string; - royaltyRecipient: string; - royaltyBps: string; - validityStartTimestamp: number; - validityEndTimestamp: number; - uid: string; - }; - /** - * The payload to sign with a wallet's `signTypedData` method. - */ - typedDataPayload: { - /** - * Specifies the contextual information used to prevent signature reuse across different contexts. - */ - domain: { - name: string; - version: string; - chainId: number; - verifyingContract: string; - }; - /** - * Defines the structure of the data types used in the message. - */ - types: { - EIP712Domain: Array<{ - name: string; - type: string; - }>; - MintRequest: Array<{ - name: string; - type: string; - }>; - }; - /** - * The structured data to be signed. - */ - message: { - uri: string; - to: string; - price: string; - /** - * A contract or wallet address - */ - currency: string; - primarySaleRecipient: string; - royaltyRecipient: string; - royaltyBps: string; - validityStartTimestamp: number; - validityEndTimestamp: number; - uid: string; - }; - /** - * The main type of the data in the message corresponding to a defined type in the `types` field. - */ - primaryType: 'MintRequest'; - }; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/signature/prepare', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update token metadata - * Update the metadata for an ERC721 token. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateTokenMetadata( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * Token ID to update metadata - */ - tokenId: string; - metadata: { - /** - * The name of the NFT - */ - name?: (string | number | null); - /** - * The description of the NFT - */ - description?: (string | null); - /** - * The image of the NFT - */ - image?: (string | null); - /** - * The external url of the NFT - */ - external_url?: (string | null); - /** - * The animation url of the NFT - */ - animation_url?: (string | null); - /** - * The properties of the NFT - */ - properties?: any; - /** - * The attributes of the NFT - */ - attributes?: any; - /** - * The background color of the NFT - */ - background_color?: (string | null); - }; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/contract/{chain}/{contractAddress}/erc721/token/update', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/KeypairService.ts b/sdk/src/services/KeypairService.ts deleted file mode 100644 index 24ff24862..000000000 --- a/sdk/src/services/KeypairService.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class KeypairService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * List public keys - * List the public keys configured with Engine - * @returns any Default Response - * @throws ApiError - */ - public list(): CancelablePromise<{ - result: Array<{ - /** - * A unique identifier for the keypair - */ - hash: string; - /** - * The public key - */ - publicKey: string; - /** - * The keypair algorithm. - */ - algorithm: string; - /** - * A description for the keypair. - */ - label?: string; - /** - * When the keypair was added - */ - createdAt: string; - /** - * When the keypair was updated - */ - updatedAt: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/auth/keypair/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Add public key - * Add the public key for a keypair - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public add( - requestBody: { - /** - * The public key of your keypair beginning with '-----BEGIN PUBLIC KEY-----'. - */ - publicKey: string; - algorithm: ('RS256' | 'RS384' | 'RS512' | 'ES256' | 'ES384' | 'ES512' | 'PS256' | 'PS384' | 'PS512'); - label?: string; - }, - ): CancelablePromise<{ - result: { - keypair: { - /** - * A unique identifier for the keypair - */ - hash: string; - /** - * The public key - */ - publicKey: string; - /** - * The keypair algorithm. - */ - algorithm: string; - /** - * A description for the keypair. - */ - label?: string; - /** - * When the keypair was added - */ - createdAt: string; - /** - * When the keypair was updated - */ - updatedAt: string; - }; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/keypair/add', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Remove public key - * Remove the public key for a keypair - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public remove( - requestBody: { - hash: string; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/keypair/remove', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/MarketplaceDirectListingsService.ts b/sdk/src/services/MarketplaceDirectListingsService.ts deleted file mode 100644 index e7d84b53a..000000000 --- a/sdk/src/services/MarketplaceDirectListingsService.ts +++ /dev/null @@ -1,1126 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class MarketplaceDirectListingsService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all listings - * Get all direct listings for this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param count Number of listings to fetch - * @param seller Being sold by this Address - * @param start Start from this index (pagination) - * @param tokenContract Token contract address to show NFTs from - * @param tokenId Only show NFTs with this ID - * @returns any Default Response - * @throws ApiError - */ - public getAll( - chain: string, - contractAddress: string, - count?: number, - seller?: string, - start?: number, - tokenContract?: string, - tokenId?: string, - ): CancelablePromise<{ - result: Array<{ - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The price to pay per unit of NFTs listed. - */ - pricePerToken: string; - /** - * Whether the listing is reserved to be bought from a specific set of buyers. - */ - isReservedListing?: boolean; - /** - * The listing ID. - */ - id: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyValuePerToken?: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - asset?: Record; - status?: (0 | 1 | 2 | 3 | 4 | 5); - /** - * The start time of the listing. If not set, defaults to now. - */ - startTimeInSeconds?: number; - /** - * The end time of the listing. If not set, defaults to 7 days from now. - */ - endTimeInSeconds?: number; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'count': count, - 'seller': seller, - 'start': start, - 'tokenContract': tokenContract, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all valid listings - * Get all the valid direct listings for this marketplace contract. A valid listing is where the listing is active, and the creator still owns & has approved Marketplace to transfer the listed NFTs. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param count Number of listings to fetch - * @param seller Being sold by this Address - * @param start Start from this index (pagination) - * @param tokenContract Token contract address to show NFTs from - * @param tokenId Only show NFTs with this ID - * @returns any Default Response - * @throws ApiError - */ - public getAllValid( - chain: string, - contractAddress: string, - count?: number, - seller?: string, - start?: number, - tokenContract?: string, - tokenId?: string, - ): CancelablePromise<{ - result: Array<{ - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The price to pay per unit of NFTs listed. - */ - pricePerToken: string; - /** - * Whether the listing is reserved to be bought from a specific set of buyers. - */ - isReservedListing?: boolean; - /** - * The listing ID. - */ - id: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyValuePerToken?: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - asset?: Record; - status?: (0 | 1 | 2 | 3 | 4 | 5); - /** - * The start time of the listing. If not set, defaults to now. - */ - startTimeInSeconds?: number; - /** - * The end time of the listing. If not set, defaults to 7 days from now. - */ - endTimeInSeconds?: number; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/get-all-valid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'count': count, - 'seller': seller, - 'start': start, - 'tokenContract': tokenContract, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get direct listing - * Gets a direct listing on this marketplace contract. - * @param listingId The id of the listing to retrieve. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getListing( - listingId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The price to pay per unit of NFTs listed. - */ - pricePerToken: string; - /** - * Whether the listing is reserved to be bought from a specific set of buyers. - */ - isReservedListing?: boolean; - /** - * The listing ID. - */ - id: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyValuePerToken?: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - asset?: Record; - status?: (0 | 1 | 2 | 3 | 4 | 5); - /** - * The start time of the listing. If not set, defaults to now. - */ - startTimeInSeconds?: number; - /** - * The end time of the listing. If not set, defaults to 7 days from now. - */ - endTimeInSeconds?: number; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/get-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check approved buyer - * Check if a buyer is approved to purchase a specific direct listing. - * @param listingId The id of the listing to retrieve. - * @param walletAddress The wallet address of the buyer to check. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public isBuyerApprovedForListing( - listingId: string, - walletAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/is-buyer-approved-for-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - 'walletAddress': walletAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check approved currency - * Check if a currency is approved for a specific direct listing. - * @param listingId The id of the listing to retrieve. - * @param currencyContractAddress The smart contract address of the ERC20 token to check. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public isCurrencyApprovedForListing( - listingId: string, - currencyContractAddress: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/is-currency-approved-for-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - 'currencyContractAddress': currencyContractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Transfer token from wallet - * Get the total number of direct listings on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getTotalCount( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/get-total-count', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create direct listing - * Create a direct listing on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public createListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The price to pay per unit of NFTs listed. - */ - pricePerToken: string; - /** - * Whether the listing is reserved to be bought from a specific set of buyers. - */ - isReservedListing?: boolean; - /** - * The start time of the listing. If not set, defaults to now. - */ - startTimestamp?: number; - /** - * The end time of the listing. If not set, defaults to 7 days from now. - */ - endTimestamp?: number; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/create-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update direct listing - * Update a direct listing on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public updateListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the listing you want to update. - */ - listingId: string; - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The price to pay per unit of NFTs listed. - */ - pricePerToken: string; - /** - * Whether the listing is reserved to be bought from a specific set of buyers. - */ - isReservedListing?: boolean; - /** - * The start time of the listing. If not set, defaults to now. - */ - startTimestamp?: number; - /** - * The end time of the listing. If not set, defaults to 7 days from now. - */ - endTimestamp?: number; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/update-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Buy from direct listing - * Buy from a specific direct listing from this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public buyFromListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the listing you want to approve a buyer for. - */ - listingId: string; - /** - * The number of tokens to buy (default is 1 for ERC721 NFTs). - */ - quantity: string; - /** - * The wallet address of the buyer. - */ - buyer: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/buy-from-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Approve buyer for reserved listing - * Approve a wallet address to buy from a reserved listing. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public approveBuyerForReservedListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the listing you want to approve a buyer for. - */ - listingId: string; - /** - * The wallet address of the buyer to approve. - */ - buyer: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/approve-buyer-for-reserved-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke approval for reserved listings - * Revoke approval for a buyer to purchase a reserved listing. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public revokeBuyerApprovalForReservedListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the listing you want to approve a buyer for. - */ - listingId: string; - /** - * The wallet address of the buyer to approve. - */ - buyerAddress: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/revoke-buyer-approval-for-reserved-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke currency approval for reserved listing - * Revoke approval of a currency for a reserved listing. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public revokeCurrencyApprovalForListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the listing you want to approve a buyer for. - */ - listingId: string; - /** - * The wallet address of the buyer to approve. - */ - currencyContractAddress: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/revoke-currency-approval-for-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Cancel direct listing - * Cancel a direct listing from this marketplace contract. Only the creator of the listing can cancel it. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public cancelListing( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the listing you want to cancel. - */ - listingId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/direct-listings/cancel-listing', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/MarketplaceEnglishAuctionsService.ts b/sdk/src/services/MarketplaceEnglishAuctionsService.ts deleted file mode 100644 index 631a58b28..000000000 --- a/sdk/src/services/MarketplaceEnglishAuctionsService.ts +++ /dev/null @@ -1,938 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class MarketplaceEnglishAuctionsService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all English auctions - * Get all English auction listings on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param count Number of listings to fetch - * @param seller Being sold by this Address - * @param start Start from this index (pagination) - * @param tokenContract Token contract address to show NFTs from - * @param tokenId Only show NFTs with this ID - * @returns any Default Response - * @throws ApiError - */ - public getAll( - chain: string, - contractAddress: string, - count?: number, - seller?: string, - start?: number, - tokenContract?: string, - tokenId?: string, - ): CancelablePromise<{ - result: Array<{ - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The listing ID. - */ - id: string; - /** - * The minimum price that a bid must be in order to be accepted. - */ - minimumBidAmount?: string; - /** - * The buyout price of the auction. - */ - buyoutBidAmount: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - buyoutCurrencyValue: { - name?: string; - symbol?: string; - decimals?: number; - value?: string; - displayValue?: string; - }; - /** - * This is a buffer e.g. x seconds. - */ - timeBufferInSeconds: number; - /** - * To be considered as a new winning bid, a bid must be at least x% greater than the previous bid. - */ - bidBufferBps: number; - /** - * The start time of the auction. - */ - startTimeInSeconds: number; - /** - * The end time of the auction. - */ - endTimeInSeconds: number; - asset?: Record; - status?: (0 | 1 | 2 | 3 | 4 | 5); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'count': count, - 'seller': seller, - 'start': start, - 'tokenContract': tokenContract, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all valid English auctions - * Get all valid English auction listings on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param count Number of listings to fetch - * @param seller Being sold by this Address - * @param start Start from this index (pagination) - * @param tokenContract Token contract address to show NFTs from - * @param tokenId Only show NFTs with this ID - * @returns any Default Response - * @throws ApiError - */ - public getAllValid( - chain: string, - contractAddress: string, - count?: number, - seller?: string, - start?: number, - tokenContract?: string, - tokenId?: string, - ): CancelablePromise<{ - result: Array<{ - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The listing ID. - */ - id: string; - /** - * The minimum price that a bid must be in order to be accepted. - */ - minimumBidAmount?: string; - /** - * The buyout price of the auction. - */ - buyoutBidAmount: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - buyoutCurrencyValue: { - name?: string; - symbol?: string; - decimals?: number; - value?: string; - displayValue?: string; - }; - /** - * This is a buffer e.g. x seconds. - */ - timeBufferInSeconds: number; - /** - * To be considered as a new winning bid, a bid must be at least x% greater than the previous bid. - */ - bidBufferBps: number; - /** - * The start time of the auction. - */ - startTimeInSeconds: number; - /** - * The end time of the auction. - */ - endTimeInSeconds: number; - asset?: Record; - status?: (0 | 1 | 2 | 3 | 4 | 5); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-all-valid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'count': count, - 'seller': seller, - 'start': start, - 'tokenContract': tokenContract, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get English auction - * Get a specific English auction listing on this marketplace contract. - * @param listingId The id of the listing to retrieve. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getAuction( - listingId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The listing ID. - */ - id: string; - /** - * The minimum price that a bid must be in order to be accepted. - */ - minimumBidAmount?: string; - /** - * The buyout price of the auction. - */ - buyoutBidAmount: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - buyoutCurrencyValue: { - name?: string; - symbol?: string; - decimals?: number; - value?: string; - displayValue?: string; - }; - /** - * This is a buffer e.g. x seconds. - */ - timeBufferInSeconds: number; - /** - * To be considered as a new winning bid, a bid must be at least x% greater than the previous bid. - */ - bidBufferBps: number; - /** - * The start time of the auction. - */ - startTimeInSeconds: number; - /** - * The end time of the auction. - */ - endTimeInSeconds: number; - asset?: Record; - status?: (0 | 1 | 2 | 3 | 4 | 5); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-auction', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get bid buffer BPS - * Get the basis points of the bid buffer. - * This is the percentage higher that a new bid must be than the current highest bid in order to be placed. - * If there is no current bid, the bid must be at least the minimum bid amount. - * Returns the value in percentage format, e.g. 100 = 1%. - * @param listingId The id of the listing to retrieve. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getBidBufferBps( - listingId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - /** - * Returns a number representing the basis points of the bid buffer. - */ - result: number; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-bid-buffer-bps', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get minimum next bid - * Helper function to calculate the value that the next bid must be in order to be accepted. - * If there is no current bid, the bid must be at least the minimum bid amount. - * If there is a current bid, the bid must be at least the current bid amount + the bid buffer. - * @param listingId The id of the listing to retrieve. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getMinimumNextBid( - listingId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - result: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-minimum-next-bid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get winning bid - * Get the current highest bid of an active auction. - * @param listingId The ID of the listing to retrieve the winner for. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getWinningBid( - listingId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result?: { - /** - * The id of the auction. - */ - auctionId?: string; - /** - * The address of the buyer who made the offer. - */ - bidderAddress?: string; - /** - * The currency contract address of the offer token. - */ - currencyContractAddress?: string; - /** - * The amount of coins offered per token. - */ - bidAmount?: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - bidAmountCurrencyValue?: { - name?: string; - symbol?: string; - decimals?: number; - value?: string; - displayValue?: string; - }; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-winning-bid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get total listings - * Get the count of English auction listings on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getTotalCount( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-total-count', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Check winning bid - * Check if a bid is or will be the winning bid for an auction. - * @param listingId The ID of the listing to retrieve the winner for. - * @param bidAmount The amount of the bid to check if it is the winning bid. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public isWinningBid( - listingId: string, - bidAmount: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: boolean; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/is-winning-bid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - 'bidAmount': bidAmount, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get winner - * Get the winner of an English auction. Can only be called after the auction has ended. - * @param listingId The ID of the listing to retrieve the winner for. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getWinner( - listingId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/get-winner', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'listingId': listingId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Buyout English auction - * Buyout the listing for this auction. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public buyoutAuction( - chain: string, - contractAddress: string, - requestBody: { - /** - * The ID of the listing to buy NFT(s) from. - */ - listingId: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/buyout-auction', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Cancel English auction - * Cancel an existing auction listing. Only the creator of the listing can cancel it. Auctions cannot be canceled once a bid has been made. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public cancelAuction( - chain: string, - contractAddress: string, - requestBody: { - /** - * The ID of the listing to cancel auction. - */ - listingId: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/cancel-auction', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create English auction - * Create an English auction listing on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public createAuction( - chain: string, - contractAddress: string, - requestBody: { - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The start time of the listing. If not set, defaults to now. - */ - startTimestamp?: number; - /** - * The end time of the listing. If not set, defaults to 7 days from now. - */ - endTimestamp?: number; - /** - * amount to buy the NFT and close the listing. - */ - buyoutBidAmount: string; - /** - * Minimum amount that bids must be to placed - */ - minimumBidAmount: string; - /** - * percentage the next bid must be higher than the current highest bid (default is contract-level bid buffer bps) - */ - bidBufferBps?: string; - /** - * time in seconds that are added to the end time when a bid is placed (default is contract-level time buffer in seconds) - */ - timeBufferInSeconds?: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/create-auction', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Close English auction for bidder - * After an auction has concluded (and a buyout did not occur), - * execute the sale for the buyer, meaning the buyer receives the NFT(s). - * You must also call closeAuctionForSeller to execute the sale for the seller, - * meaning the seller receives the payment from the highest bid. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public closeAuctionForBidder( - chain: string, - contractAddress: string, - requestBody: { - /** - * The ID of the listing to execute the sale for. - */ - listingId: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/close-auction-for-bidder', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Close English auction for seller - * After an auction has concluded (and a buyout did not occur), - * execute the sale for the seller, meaning the seller receives the payment from the highest bid. - * You must also call closeAuctionForBidder to execute the sale for the buyer, meaning the buyer receives the NFT(s). - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public closeAuctionForSeller( - chain: string, - contractAddress: string, - requestBody: { - /** - * The ID of the listing to execute the sale for. - */ - listingId: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/close-auction-for-seller', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Execute sale - * Close the auction for both buyer and seller. - * This means the NFT(s) will be transferred to the buyer and the seller will receive the funds. - * This function can only be called after the auction has ended. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public executeSale( - chain: string, - contractAddress: string, - requestBody: { - /** - * The ID of the listing to execute the sale for. - */ - listingId: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/execute-sale', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Make bid - * Place a bid on an English auction listing. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @returns any Default Response - * @throws ApiError - */ - public makeBid( - chain: string, - contractAddress: string, - requestBody: { - /** - * The ID of the listing to place a bid on. - */ - listingId: string; - /** - * The amount of the bid to place in the currency of the listing. Use getNextBidAmount to get the minimum amount for the next bid. - */ - bidAmount: string; - }, - simulateTx: boolean = false, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/english-auctions/make-bid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/MarketplaceOffersService.ts b/sdk/src/services/MarketplaceOffersService.ts deleted file mode 100644 index 7a8f1d1e1..000000000 --- a/sdk/src/services/MarketplaceOffersService.ts +++ /dev/null @@ -1,604 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class MarketplaceOffersService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all offers - * Get all offers on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param count Number of listings to fetch - * @param offeror has offers from this Address - * @param start Start from this index (pagination) - * @param tokenContract Token contract address to show NFTs from - * @param tokenId Only show NFTs with this ID - * @returns any Default Response - * @throws ApiError - */ - public getAll( - chain: string, - contractAddress: string, - count?: number, - offeror?: string, - start?: number, - tokenContract?: string, - tokenId?: string, - ): CancelablePromise<{ - result: Array<{ - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The id of the offer. - */ - id: string; - /** - * The address of the creator of offer. - */ - offerorAddress: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyValue?: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - /** - * The total offer amount for the NFTs. - */ - totalPrice: string; - asset?: Record; - /** - * The end time of the auction. - */ - endTimeInSeconds?: number; - status?: (0 | 1 | 2 | 3 | 4 | 5); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/offers/get-all', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'count': count, - 'offeror': offeror, - 'start': start, - 'tokenContract': tokenContract, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all valid offers - * Get all valid offers on this marketplace contract. Valid offers are offers that have not expired, been canceled, or been accepted. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param count Number of listings to fetch - * @param offeror has offers from this Address - * @param start Start from this index (pagination) - * @param tokenContract Token contract address to show NFTs from - * @param tokenId Only show NFTs with this ID - * @returns any Default Response - * @throws ApiError - */ - public getAllValid( - chain: string, - contractAddress: string, - count?: number, - offeror?: string, - start?: number, - tokenContract?: string, - tokenId?: string, - ): CancelablePromise<{ - result: Array<{ - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The id of the offer. - */ - id: string; - /** - * The address of the creator of offer. - */ - offerorAddress: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyValue?: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - /** - * The total offer amount for the NFTs. - */ - totalPrice: string; - asset?: Record; - /** - * The end time of the auction. - */ - endTimeInSeconds?: number; - status?: (0 | 1 | 2 | 3 | 4 | 5); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/offers/get-all-valid', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'count': count, - 'offeror': offeror, - 'start': start, - 'tokenContract': tokenContract, - 'tokenId': tokenId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get offer - * Get details about an offer. - * @param offerId The ID of the offer to get information about. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getOffer( - offerId: string, - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: { - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * The id of the offer. - */ - id: string; - /** - * The address of the creator of offer. - */ - offerorAddress: string; - /** - * The `CurrencyValue` of the listing. Useful for displaying the price information. - */ - currencyValue?: { - name: string; - symbol: string; - decimals: number; - value: string; - displayValue: string; - }; - /** - * The total offer amount for the NFTs. - */ - totalPrice: string; - asset?: Record; - /** - * The end time of the auction. - */ - endTimeInSeconds?: number; - status?: (0 | 1 | 2 | 3 | 4 | 5); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/offers/get-offer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - query: { - 'offerId': offerId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get total count - * Get the total number of offers on this marketplace contract. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @returns any Default Response - * @throws ApiError - */ - public getTotalCount( - chain: string, - contractAddress: string, - ): CancelablePromise<{ - result: string; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/marketplace/{chain}/{contractAddress}/offers/get-total-count', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Make offer - * Make an offer on a token. A valid listing is not required. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public makeOffer( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The address of the asset being listed. - */ - assetContractAddress: string; - /** - * The ID of the token to list. - */ - tokenId: string; - /** - * The address of the currency to accept for the listing. - */ - currencyContractAddress?: string; - /** - * The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here). - */ - quantity?: string; - /** - * the price to offer in the currency specified - */ - totalPrice: string; - /** - * Defaults to 10 years from now. - */ - endTimestamp?: number; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/offers/make-offer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Cancel offer - * Cancel a valid offer made by the caller wallet. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public cancelOffer( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the offer to cancel. You can view all offers with getAll or getAllValid. - */ - offerId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/offers/cancel-offer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Accept offer - * Accept a valid offer. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param contractAddress Contract address - * @param xBackendWalletAddress Backend wallet address - * @param requestBody - * @param simulateTx Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes. - * @param xIdempotencyKey Transactions submitted with the same idempotency key will be de-duplicated. Only the last 100000 transactions are compared. - * @param xTransactionMode Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions. - * @param xAccountAddress Smart account address - * @param xAccountFactoryAddress Smart account factory address. If omitted, Engine will try to resolve it from the contract. - * @param xAccountSalt Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop. - * @returns any Default Response - * @throws ApiError - */ - public acceptOffer( - chain: string, - contractAddress: string, - xBackendWalletAddress: string, - requestBody: { - /** - * The ID of the offer to accept. You can view all offers with getAll or getAllValid. - */ - offerId: string; - txOverrides?: { - /** - * Gas limit for the transaction - */ - gas?: string; - /** - * Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions. - */ - gasPrice?: string; - /** - * Maximum fee per gas - */ - maxFeePerGas?: string; - /** - * Maximum priority fee per gas - */ - maxPriorityFeePerGas?: string; - /** - * Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout - */ - timeoutSeconds?: number; - /** - * Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract. - */ - value?: string; - }; - }, - simulateTx: boolean = false, - xIdempotencyKey?: string, - xTransactionMode?: 'sponsored', - xAccountAddress?: string, - xAccountFactoryAddress?: string, - xAccountSalt?: string, - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/marketplace/{chain}/{contractAddress}/offers/accept-offer', - path: { - 'chain': chain, - 'contractAddress': contractAddress, - }, - headers: { - 'x-backend-wallet-address': xBackendWalletAddress, - 'x-idempotency-key': xIdempotencyKey, - 'x-transaction-mode': xTransactionMode, - 'x-account-address': xAccountAddress, - 'x-account-factory-address': xAccountFactoryAddress, - 'x-account-salt': xAccountSalt, - }, - query: { - 'simulateTx': simulateTx, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/PermissionsService.ts b/sdk/src/services/PermissionsService.ts deleted file mode 100644 index 9d43621f8..000000000 --- a/sdk/src/services/PermissionsService.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class PermissionsService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all permissions - * Get all users with their corresponding permissions - * @returns any Default Response - * @throws ApiError - */ - public getAll(): CancelablePromise<{ - result: Array<{ - /** - * A contract or wallet address - */ - walletAddress: string; - permissions: string; - label: (string | null); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/auth/permissions/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Grant permissions to user - * Grant permissions to a user - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public grant( - requestBody: { - /** - * A contract or wallet address - */ - walletAddress: string; - permissions: ('ADMIN' | 'OWNER'); - label?: string; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/permissions/grant', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke permissions from user - * Revoke a user's permissions - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public revoke( - requestBody: { - /** - * A contract or wallet address - */ - walletAddress: string; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/auth/permissions/revoke', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/RelayerService.ts b/sdk/src/services/RelayerService.ts deleted file mode 100644 index fd365786f..000000000 --- a/sdk/src/services/RelayerService.ts +++ /dev/null @@ -1,220 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class RelayerService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all meta-transaction relayers - * Get all meta-transaction relayers - * @returns any Default Response - * @throws ApiError - */ - public getAll(): CancelablePromise<{ - result: Array<{ - id: string; - name: (string | null); - chainId: string; - /** - * A contract or wallet address - */ - backendWalletAddress: string; - allowedContracts: (Array | null); - allowedForwarders: (Array | null); - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/relayer/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create a new meta-transaction relayer - * Create a new meta-transaction relayer - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public create( - requestBody: { - name?: string; - /** - * A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - */ - chain: string; - /** - * The address of the backend wallet to use for relaying transactions. - */ - backendWalletAddress: string; - allowedContracts?: Array; - allowedForwarders?: Array; - }, - ): CancelablePromise<{ - result: { - relayerId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/relayer/create', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke a relayer - * Revoke a relayer - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public revoke( - requestBody: { - id: string; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/relayer/revoke', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Update a relayer - * Update a relayer - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public update( - requestBody: { - id: string; - name?: string; - /** - * A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - */ - chain?: string; - /** - * A contract or wallet address - */ - backendWalletAddress?: string; - allowedContracts?: Array; - allowedForwarders?: Array; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/relayer/update', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Relay a meta-transaction - * Relay an EIP-2771 meta-transaction - * @param relayerId - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public relay( - relayerId: string, - requestBody?: ({ - type: 'forward'; - request: { - from: string; - to: string; - value: string; - gas: string; - nonce: string; - data: string; - chainid?: string; - }; - signature: string; - /** - * A contract or wallet address - */ - forwarderAddress: string; - } | { - type: 'permit'; - request: { - to: string; - owner: string; - spender: string; - value: string; - nonce: string; - deadline: string; - }; - signature: string; - } | { - type: 'execute-meta-transaction'; - request: { - from: string; - to: string; - data: string; - }; - signature: string; - }), - ): CancelablePromise<{ - result: { - /** - * Queue ID - */ - queueId: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/relayer/{relayerId}', - path: { - 'relayerId': relayerId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/TransactionService.ts b/sdk/src/services/TransactionService.ts deleted file mode 100644 index 76f9ef016..000000000 --- a/sdk/src/services/TransactionService.ts +++ /dev/null @@ -1,603 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class TransactionService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all transactions - * Get all transaction requests. - * @param status The status to query: 'queued', 'mined', 'errored', or 'cancelled'. Default: 'queued' - * @param page Specify the page number. - * @param limit Specify the number of results to return per page. - * @returns any Default Response - * @throws ApiError - */ - public getAll( - status: ('queued' | 'mined' | 'cancelled' | 'errored'), - page: number = 1, - limit: number = 100, - ): CancelablePromise<{ - result: { - transactions: Array<{ - queueId: (string | null); - /** - * The current state of the transaction. - */ - status: ('queued' | 'sent' | 'mined' | 'errored' | 'cancelled'); - chainId: (string | null); - fromAddress: (string | null); - toAddress: (string | null); - data: (string | null); - extension: (string | null); - value: (string | null); - nonce: (number | string | null); - gasLimit: (string | null); - gasPrice: (string | null); - maxFeePerGas: (string | null); - maxPriorityFeePerGas: (string | null); - transactionType: (number | null); - transactionHash: (string | null); - queuedAt: (string | null); - sentAt: (string | null); - minedAt: (string | null); - cancelledAt: (string | null); - deployedContractAddress: (string | null); - deployedContractType: (string | null); - errorMessage: (string | null); - sentAtBlockNumber: (number | null); - blockNumber: (number | null); - /** - * The number of retry attempts - */ - retryCount: number; - retryGasValues: (boolean | null); - retryMaxFeePerGas: (string | null); - retryMaxPriorityFeePerGas: (string | null); - signerAddress: (string | null); - accountAddress: (string | null); - accountSalt: (string | null); - accountFactoryAddress: (string | null); - target: (string | null); - sender: (string | null); - initCode: (string | null); - callData: (string | null); - callGasLimit: (string | null); - verificationGasLimit: (string | null); - preVerificationGas: (string | null); - paymasterAndData: (string | null); - userOpHash: (string | null); - functionName: (string | null); - functionArgs: (string | null); - onChainTxStatus: (number | null); - onchainStatus: ('success' | 'reverted' | null); - effectiveGasPrice: (string | null); - cumulativeGasUsed: (string | null); - batchOperations: null; - }>; - totalCount: number; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/transaction/get-all', - query: { - 'page': page, - 'limit': limit, - 'status': status, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get transaction status - * Get the status for a transaction request. - * @param queueId Transaction queue ID - * @returns any Default Response - * @throws ApiError - */ - public status( - queueId: string, - ): CancelablePromise<{ - result: { - queueId: (string | null); - /** - * The current state of the transaction. - */ - status: ('queued' | 'sent' | 'mined' | 'errored' | 'cancelled'); - chainId: (string | null); - fromAddress: (string | null); - toAddress: (string | null); - data: (string | null); - extension: (string | null); - value: (string | null); - nonce: (number | string | null); - gasLimit: (string | null); - gasPrice: (string | null); - maxFeePerGas: (string | null); - maxPriorityFeePerGas: (string | null); - transactionType: (number | null); - transactionHash: (string | null); - queuedAt: (string | null); - sentAt: (string | null); - minedAt: (string | null); - cancelledAt: (string | null); - deployedContractAddress: (string | null); - deployedContractType: (string | null); - errorMessage: (string | null); - sentAtBlockNumber: (number | null); - blockNumber: (number | null); - /** - * The number of retry attempts - */ - retryCount: number; - retryGasValues: (boolean | null); - retryMaxFeePerGas: (string | null); - retryMaxPriorityFeePerGas: (string | null); - signerAddress: (string | null); - accountAddress: (string | null); - accountSalt: (string | null); - accountFactoryAddress: (string | null); - target: (string | null); - sender: (string | null); - initCode: (string | null); - callData: (string | null); - callGasLimit: (string | null); - verificationGasLimit: (string | null); - preVerificationGas: (string | null); - paymasterAndData: (string | null); - userOpHash: (string | null); - functionName: (string | null); - functionArgs: (string | null); - onChainTxStatus: (number | null); - onchainStatus: ('success' | 'reverted' | null); - effectiveGasPrice: (string | null); - cumulativeGasUsed: (string | null); - batchOperations: null; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/transaction/status/{queueId}', - path: { - 'queueId': queueId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all deployment transactions - * Get all transaction requests to deploy contracts. - * @param page Specify the page number for pagination. - * @param limit Specify the number of transactions to return per page. - * @returns any Default Response - * @throws ApiError - */ - public getAllDeployedContracts( - page: number = 1, - limit: number = 10, - ): CancelablePromise<{ - result: { - transactions: Array<{ - queueId: (string | null); - /** - * The current state of the transaction. - */ - status: ('queued' | 'sent' | 'mined' | 'errored' | 'cancelled'); - chainId: (string | null); - fromAddress: (string | null); - toAddress: (string | null); - data: (string | null); - extension: (string | null); - value: (string | null); - nonce: (number | string | null); - gasLimit: (string | null); - gasPrice: (string | null); - maxFeePerGas: (string | null); - maxPriorityFeePerGas: (string | null); - transactionType: (number | null); - transactionHash: (string | null); - queuedAt: (string | null); - sentAt: (string | null); - minedAt: (string | null); - cancelledAt: (string | null); - deployedContractAddress: (string | null); - deployedContractType: (string | null); - errorMessage: (string | null); - sentAtBlockNumber: (number | null); - blockNumber: (number | null); - /** - * The number of retry attempts - */ - retryCount: number; - retryGasValues: (boolean | null); - retryMaxFeePerGas: (string | null); - retryMaxPriorityFeePerGas: (string | null); - signerAddress: (string | null); - accountAddress: (string | null); - accountSalt: (string | null); - accountFactoryAddress: (string | null); - target: (string | null); - sender: (string | null); - initCode: (string | null); - callData: (string | null); - callGasLimit: (string | null); - verificationGasLimit: (string | null); - preVerificationGas: (string | null); - paymasterAndData: (string | null); - userOpHash: (string | null); - functionName: (string | null); - functionArgs: (string | null); - onChainTxStatus: (number | null); - onchainStatus: ('success' | 'reverted' | null); - effectiveGasPrice: (string | null); - cumulativeGasUsed: (string | null); - batchOperations: null; - }>; - totalCount: number; - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/transaction/get-all-deployed-contracts', - query: { - 'page': page, - 'limit': limit, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Retry transaction (synchronous) - * Retry a transaction with updated gas settings. Blocks until the transaction is mined or errors. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public syncRetry( - requestBody: { - /** - * Transaction queue ID - */ - queueId: string; - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - }, - ): CancelablePromise<{ - result: { - /** - * A transaction hash - */ - transactionHash: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/transaction/sync-retry', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Retry failed transaction - * Retry a failed transaction - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public retryFailed( - requestBody: { - /** - * Transaction queue ID - */ - queueId: string; - }, - ): CancelablePromise<{ - result: { - message: string; - status: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/transaction/retry-failed', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Cancel transaction - * Attempt to cancel a transaction by sending a null transaction with a higher gas setting. This transaction is not guaranteed to be cancelled. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public cancel( - requestBody: { - /** - * Transaction queue ID - */ - queueId: string; - }, - ): CancelablePromise<{ - result: { - /** - * Transaction queue ID - */ - queueId: string; - /** - * Response status - */ - status: string; - /** - * Response message - */ - message: string; - /** - * A transaction hash - */ - transactionHash?: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/transaction/cancel', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Send a signed transaction - * Send a signed transaction - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public sendRawTransaction( - chain: string, - requestBody: { - signedTransaction: string; - }, - ): CancelablePromise<{ - result: { - /** - * A transaction hash - */ - transactionHash: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/transaction/{chain}/send-signed-transaction', - path: { - 'chain': chain, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Send a signed user operation - * Send a signed user operation - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public sendSignedUserOp( - chain: string, - requestBody: { - signedUserOp: any; - }, - ): CancelablePromise<({ - result: { - /** - * A transaction hash - */ - userOpHash: string; - }; - } | { - error: { - message: string; - }; - })> { - return this.httpRequest.request({ - method: 'POST', - url: '/transaction/{chain}/send-signed-user-op', - path: { - 'chain': chain, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get transaction receipt - * Get the transaction receipt from a transaction hash. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param transactionHash Transaction hash - * @returns any Default Response - * @throws ApiError - */ - public getTransactionReceipt( - chain: string, - transactionHash: string, - ): CancelablePromise<{ - result: ({ - to?: string; - from?: string; - contractAddress?: (string | null); - transactionIndex?: number; - root?: string; - gasUsed?: string; - logsBloom?: string; - blockHash?: string; - /** - * A transaction hash - */ - transactionHash?: string; - logs?: Array; - blockNumber?: number; - confirmations?: number; - cumulativeGasUsed?: string; - effectiveGasPrice?: string; - byzantium?: boolean; - type?: number; - status?: number; - } | null); - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/transaction/{chain}/tx-hash/{transactionHash}', - path: { - 'chain': chain, - 'transactionHash': transactionHash, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get transaction receipt from user-op hash - * Get the transaction receipt from a user-op hash. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param userOpHash User operation hash - * @returns any Default Response - * @throws ApiError - */ - public useropHashReceipt( - chain: string, - userOpHash: string, - ): CancelablePromise<{ - result: any; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/transaction/{chain}/userop-hash/{userOpHash}', - path: { - 'chain': chain, - 'userOpHash': userOpHash, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get transaction logs - * Get transaction logs for a mined transaction. A tranasction queue ID or hash must be provided. Set `parseLogs` to parse the event logs. - * @param chain A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred. - * @param queueId The queue ID for a mined transaction. - * @param transactionHash The transaction hash for a mined transaction. - * @param parseLogs If true, parse the raw logs as events defined in the contract ABI. (Default: true) - * @returns any Default Response - * @throws ApiError - */ - public getTransactionLogs( - chain: string, - queueId?: string, - transactionHash?: string, - parseLogs?: boolean, - ): CancelablePromise<{ - result: Array<{ - /** - * A contract or wallet address - */ - address: string; - topics: Array; - data: string; - blockNumber: string; - /** - * A transaction hash - */ - transactionHash: string; - transactionIndex: number; - blockHash: string; - logIndex: number; - removed: boolean; - /** - * Event name, only returned when `parseLogs` is true - */ - eventName?: string; - /** - * Event arguments. Only returned when `parseLogs` is true - */ - args?: any; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/transaction/logs', - query: { - 'chain': chain, - 'queueId': queueId, - 'transactionHash': transactionHash, - 'parseLogs': parseLogs, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/WalletCredentialsService.ts b/sdk/src/services/WalletCredentialsService.ts deleted file mode 100644 index 1ac32e4ab..000000000 --- a/sdk/src/services/WalletCredentialsService.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class WalletCredentialsService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Create wallet credentials - * Create a new set of wallet credentials. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public createWalletCredential( - requestBody: { - label: string; - type: 'circle'; - /** - * 32-byte hex string. If not provided, a random one will be generated. - */ - entitySecret?: string; - /** - * Whether this credential should be set as the default for its type. Only one credential can be default per type. - */ - isDefault?: boolean; - }, - ): CancelablePromise<{ - result: { - id: string; - type: string; - label: string; - isDefault: (boolean | null); - createdAt: string; - updatedAt: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/wallet-credentials', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get all wallet credentials - * Get all wallet credentials with pagination. - * @param page Specify the page number. - * @param limit Specify the number of results to return per page. - * @returns any Default Response - * @throws ApiError - */ - public getAllWalletCredentials( - page: number = 1, - limit: number = 100, - ): CancelablePromise<{ - result: Array<{ - id: string; - type: string; - label: (string | null); - isDefault: (boolean | null); - createdAt: string; - updatedAt: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/wallet-credentials', - query: { - 'page': page, - 'limit': limit, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get wallet credential - * Get a wallet credential by ID. - * @param id The ID of the wallet credential to get. - * @returns any Default Response - * @throws ApiError - */ - public getWalletCredential( - id: string, - ): CancelablePromise<{ - result: { - id: string; - type: string; - label: (string | null); - isDefault: boolean; - createdAt: string; - updatedAt: string; - deletedAt: (string | null); - }; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/wallet-credentials/{id}', - path: { - 'id': id, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/src/services/WebhooksService.ts b/sdk/src/services/WebhooksService.ts deleted file mode 100644 index 5e6a0b90a..000000000 --- a/sdk/src/services/WebhooksService.ts +++ /dev/null @@ -1,159 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CancelablePromise } from '../core/CancelablePromise'; -import type { BaseHttpRequest } from '../core/BaseHttpRequest'; - -export class WebhooksService { - - constructor(public readonly httpRequest: BaseHttpRequest) {} - - /** - * Get all webhooks configured - * Get all webhooks configuration data set up on Engine - * @returns any Default Response - * @throws ApiError - */ - public getAll(): CancelablePromise<{ - result: Array<{ - id: number; - url: string; - name: (string | null); - secret?: string; - eventType: string; - active: boolean; - createdAt: string; - }>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/webhooks/get-all', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Create webhook - * Create a webhook to call when a specific Engine event occurs. - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public create( - requestBody: { - /** - * Webhook URL. Non-HTTPS URLs are not supported. - */ - url: string; - name?: string; - eventType: ('queued_transaction' | 'sent_transaction' | 'mined_transaction' | 'errored_transaction' | 'cancelled_transaction' | 'all_transactions' | 'backend_wallet_balance' | 'auth' | 'contract_subscription'); - }, - ): CancelablePromise<{ - result: { - id: number; - url: string; - name: (string | null); - secret?: string; - eventType: string; - active: boolean; - createdAt: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/webhooks/create', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Revoke webhook - * Revoke a Webhook - * @param requestBody - * @returns any Default Response - * @throws ApiError - */ - public revoke( - requestBody: { - id: number; - }, - ): CancelablePromise<{ - result: { - success: boolean; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/webhooks/revoke', - body: requestBody, - mediaType: 'application/json', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Get webhooks event types - * Get the all the webhooks event types - * @returns any Default Response - * @throws ApiError - */ - public getEventTypes(): CancelablePromise<{ - result: Array<('queued_transaction' | 'sent_transaction' | 'mined_transaction' | 'errored_transaction' | 'cancelled_transaction' | 'all_transactions' | 'backend_wallet_balance' | 'auth' | 'contract_subscription')>; - }> { - return this.httpRequest.request({ - method: 'GET', - url: '/webhooks/event-types', - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - - /** - * Test webhook - * Send a test payload to a webhook. - * @param webhookId - * @returns any Default Response - * @throws ApiError - */ - public testWebhook( - webhookId: string, - ): CancelablePromise<{ - result: { - ok: boolean; - status: number; - body: string; - }; - }> { - return this.httpRequest.request({ - method: 'POST', - url: '/webhooks/{webhookId}/test', - path: { - 'webhookId': webhookId, - }, - errors: { - 400: `Bad Request`, - 404: `Not Found`, - 500: `Internal Server Error`, - }, - }); - } - -} diff --git a/sdk/tsconfig.json b/sdk/tsconfig.json deleted file mode 100644 index 8dee5fa2a..000000000 --- a/sdk/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "isolatedModules": true - } -} diff --git a/sdk/yarn.lock b/sdk/yarn.lock deleted file mode 100644 index 2cdcc37fe..000000000 --- a/sdk/yarn.lock +++ /dev/null @@ -1,1545 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.5.5": - version "7.22.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" - integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== - dependencies: - "@babel/highlight" "^7.22.13" - chalk "^2.4.2" - -"@babel/compat-data@^7.22.9": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.2.tgz#6a12ced93455827037bfb5ed8492820d60fc32cc" - integrity sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ== - -"@babel/core@^7.7.7": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.2.tgz#ed10df0d580fff67c5f3ee70fd22e2e4c90a9f94" - integrity sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.0" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-module-transforms" "^7.23.0" - "@babel/helpers" "^7.23.2" - "@babel/parser" "^7.23.0" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.2" - "@babel/types" "^7.23.0" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" - integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== - dependencies: - "@babel/types" "^7.23.0" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-compilation-targets@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" - integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== - dependencies: - "@babel/compat-data" "^7.22.9" - "@babel/helper-validator-option" "^7.22.15" - browserslist "^4.21.9" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-create-class-features-plugin@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" - integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-member-expression-to-functions" "^7.22.15" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-member-expression-to-functions@^7.22.15": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" - integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== - dependencies: - "@babel/types" "^7.23.0" - -"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz#3ec246457f6c842c0aee62a01f60739906f7047e" - integrity sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-optimise-call-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" - integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-plugin-utils@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-replace-supers@^7.22.9": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" - integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.22.15" - "@babel/helper-optimise-call-expression" "^7.22.5" - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" - integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" - integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== - -"@babel/helpers@^7.23.2": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767" - integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.2" - "@babel/types" "^7.23.0" - -"@babel/highlight@^7.22.13": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" - integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" - integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== - -"@babel/plugin-syntax-jsx@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" - integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-typescript@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272" - integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-modules-commonjs@^7.23.0", "@babel/plugin-transform-modules-commonjs@^7.7.5": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz#b3dba4757133b2762c00f4f94590cf6d52602481" - integrity sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ== - dependencies: - "@babel/helper-module-transforms" "^7.23.0" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-simple-access" "^7.22.5" - -"@babel/plugin-transform-typescript@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz#15adef906451d86349eb4b8764865c960eb54127" - integrity sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-typescript" "^7.22.5" - -"@babel/preset-typescript@^7.23.2": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz#c8de488130b7081f7e1482936ad3de5b018beef4" - integrity sha512-u4UJc1XsS1GhIGteM8rnGiIvf9rJpiVgMEeCnwlLA7WJPC+jcXWJAGxYmeqs5hOZD8BbAfnV5ezBOxQbb4OUxA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-syntax-jsx" "^7.22.5" - "@babel/plugin-transform-modules-commonjs" "^7.23.0" - "@babel/plugin-transform-typescript" "^7.22.15" - -"@babel/runtime@^7.7.7": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" - integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.23.2": - version "7.23.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" - integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.0" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.0" - "@babel/types" "^7.23.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" - integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== - dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/source-map@^0.3.3": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" - integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@preconstruct/cli@^2.8.1": - version "2.8.1" - resolved "https://registry.yarnpkg.com/@preconstruct/cli/-/cli-2.8.1.tgz#7d7f9fa32e1bfd355d79062a9ccc5af4c97b3915" - integrity sha512-PX5w+au06iY/QaT+9RLmRlIfavRCRoMTC/krwtNrgPEnubR9e6P+QlywrKmwiEvkzbR9AEzGnRZL8uNRDDMzrQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/core" "^7.7.7" - "@babel/helper-module-imports" "^7.10.4" - "@babel/runtime" "^7.7.7" - "@preconstruct/hook" "^0.4.0" - "@rollup/plugin-alias" "^3.1.1" - "@rollup/plugin-commonjs" "^15.0.0" - "@rollup/plugin-json" "^4.1.0" - "@rollup/plugin-node-resolve" "^11.2.1" - "@rollup/plugin-replace" "^2.4.1" - builtin-modules "^3.1.0" - chalk "^4.1.0" - dataloader "^2.0.0" - detect-indent "^6.0.0" - enquirer "^2.3.6" - estree-walker "^2.0.1" - fast-deep-equal "^2.0.1" - fast-glob "^3.2.4" - fs-extra "^9.0.1" - is-ci "^2.0.0" - is-reference "^1.2.1" - jest-worker "^26.3.0" - magic-string "^0.30.0" - meow "^7.1.0" - ms "^2.1.2" - normalize-path "^3.0.0" - npm-packlist "^2.1.2" - p-limit "^3.0.2" - parse-glob "^3.0.4" - parse-json "^5.1.0" - quick-lru "^5.1.1" - resolve "^1.17.0" - resolve-from "^5.0.0" - rollup "^2.79.1" - semver "^7.3.4" - terser "^5.16.8" - v8-compile-cache "^2.1.1" - zod "^3.21.4" - -"@preconstruct/hook@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@preconstruct/hook/-/hook-0.4.0.tgz#c15dfacfc6e60652a6837209c2fd87f0240b099e" - integrity sha512-a7mrlPTM3tAFJyz43qb4pPVpUx8j8TzZBFsNFqcKcE/sEakNXRlQAuCT4RGZRf9dQiiUnBahzSIWawU4rENl+Q== - dependencies: - "@babel/core" "^7.7.7" - "@babel/plugin-transform-modules-commonjs" "^7.7.5" - pirates "^4.0.1" - source-map-support "^0.5.16" - -"@rollup/plugin-alias@^3.1.1": - version "3.1.9" - resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.9.tgz#a5d267548fe48441f34be8323fb64d1d4a1b3fdf" - integrity sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw== - dependencies: - slash "^3.0.0" - -"@rollup/plugin-commonjs@^15.0.0": - version "15.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-15.1.0.tgz#1e7d076c4f1b2abf7e65248570e555defc37c238" - integrity sha512-xCQqz4z/o0h2syQ7d9LskIMvBSH4PX5PjYdpSSvgS+pQik3WahkQVNWg3D8XJeYjZoVWnIUQYDghuEMRGrmQYQ== - dependencies: - "@rollup/pluginutils" "^3.1.0" - commondir "^1.0.1" - estree-walker "^2.0.1" - glob "^7.1.6" - is-reference "^1.2.1" - magic-string "^0.25.7" - resolve "^1.17.0" - -"@rollup/plugin-json@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" - integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw== - dependencies: - "@rollup/pluginutils" "^3.0.8" - -"@rollup/plugin-node-resolve@^11.2.1": - version "11.2.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" - integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - "@types/resolve" "1.17.1" - builtin-modules "^3.1.0" - deepmerge "^4.2.2" - is-module "^1.0.0" - resolve "^1.19.0" - -"@rollup/plugin-replace@^2.4.1": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" - integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - magic-string "^0.25.7" - -"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - -"@types/estree@*": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.3.tgz#2be19e759a3dd18c79f9f436bd7363556c1a73dd" - integrity sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ== - -"@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - -"@types/minimist@^1.2.0": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.4.tgz#81f886786411c45bba3f33e781ab48bd56bfca2e" - integrity sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ== - -"@types/node@*": - version "20.8.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.9.tgz#646390b4fab269abce59c308fc286dcd818a2b08" - integrity sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg== - dependencies: - undici-types "~5.26.4" - -"@types/normalize-package-data@^2.4.0": - version "2.4.3" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz#291c243e4b94dbfbc0c0ee26b7666f1d5c030e2c" - integrity sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg== - -"@types/resolve@1.17.1": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" - integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== - dependencies: - "@types/node" "*" - -acorn@^8.8.2: - version "8.11.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" - integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== - -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== - -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.21.9: - version "4.22.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" - integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== - dependencies: - caniuse-lite "^1.0.30001541" - electron-to-chromium "^1.4.535" - node-releases "^2.0.13" - update-browserslist-db "^1.0.13" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -builtin-modules@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - -camelcase-keys@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" - integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== - dependencies: - camelcase "^5.3.1" - map-obj "^4.0.0" - quick-lru "^4.0.1" - -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30001541: - version "1.0.30001555" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001555.tgz#e36f4d49e345337d6788f32093867cec8d951789" - integrity sha512-NzbUFKUnJ3DTcq6YyZB6+qqhfD112uR3uoEnkmfzm2wVzUNsFkU7AwBjKQ654Sp5cau0JxhFyRSn/tQZ+XfygA== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -dataloader@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.2.tgz#216dc509b5abe39d43a9b9d97e6e5e473dfbe3e0" - integrity sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g== - -debug@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -decamelize-keys@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" - integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@^1.1.0, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -detect-indent@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" - integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== - -electron-to-chromium@^1.4.535: - version "1.4.569" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz#1298b67727187ffbaac005a7425490d157f3ad03" - integrity sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg== - -enquirer@^2.3.6: - version "2.4.1" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" - integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== - dependencies: - ansi-colors "^4.1.1" - strip-ansi "^6.0.1" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - -estree-walker@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w== - -fast-glob@^3.2.4: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== - dependencies: - reusify "^1.0.4" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -fs-extra@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA== - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w== - dependencies: - is-glob "^2.0.0" - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^7.1.6: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -hard-rejection@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" - integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -ignore-walk@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" - integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== - dependencies: - minimatch "^3.0.4" - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg== - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-glob@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg== - dependencies: - is-extglob "^1.0.0" - -is-glob@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== - -is-reference@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - -jest-worker@^26.3.0: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" - integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^7.0.0" - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -magic-string@^0.25.7: - version "0.25.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" - integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== - dependencies: - sourcemap-codec "^1.4.8" - -magic-string@^0.30.0: - version "0.30.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" - integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.15" - -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== - -map-obj@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" - integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== - -meow@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.1.tgz#7c01595e3d337fcb0ec4e8eed1666ea95903d306" - integrity sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "4.1.0" - normalize-package-data "^2.5.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.13.1" - yargs-parser "^18.1.3" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -minimatch@^3.0.4, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist-options@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" - integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - kind-of "^6.0.3" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -node-releases@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" - integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-bundled@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" - integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^2.1.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-2.2.2.tgz#076b97293fa620f632833186a7a8f65aaa6148c8" - integrity sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg== - dependencies: - glob "^7.1.6" - ignore-walk "^3.0.3" - npm-bundled "^1.1.1" - npm-normalize-package-bin "^1.0.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA== - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^5.0.0, parse-json@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.2.2, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pirates@^4.0.1: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -quick-lru@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" - integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== - -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -redent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== - dependencies: - indent-string "^4.0.0" - strip-indent "^3.0.0" - -regenerator-runtime@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" - integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.10.0, resolve@^1.17.0, resolve@^1.19.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rollup@^2.79.1: - version "2.79.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.2.tgz#f150e4a5db4b121a21a747d762f701e5e9f49090" - integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ== - optionalDependencies: - fsevents "~2.3.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-support@^0.5.16, source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sourcemap-codec@^1.4.8: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.16" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz#a14f64e0954f6e25cc6587bd4f392522db0d998f" - integrity sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw== - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0, supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -terser@^5.16.8: - version "5.22.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.22.0.tgz#4f18103f84c5c9437aafb7a14918273310a8a49d" - integrity sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw== - dependencies: - "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -trim-newlines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" - integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== - -type-fest@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" - integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -v8-compile-cache@^2.1.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" - integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^18.1.3: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zod@^3.21.4: - version "3.22.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" - integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== diff --git a/src/constants/urls.ts b/src/constants/urls.ts new file mode 100644 index 000000000..65466630d --- /dev/null +++ b/src/constants/urls.ts @@ -0,0 +1,17 @@ +export const THIRDWEB_PAY_DOMAIN = + process.env.THIRDWEB_PAY_URL || "pay.thirdweb-dev.com"; + +export const THIRDWEB_INAPP_WALLET_DOMAIN = + process.env.THIRDWEB_IN_APP_WALLET_URL || "embedded-wallet.thirdweb-dev.com"; + +export const THIRDWEB_RPC_DOMAIN = + process.env.THIRDWEB_RPC_URL || "rpc.thirdweb-dev.com"; + +export const THIRDWEB_STORAGE_DOMAIN = + process.env.THIRDWEB_STORAGE_URL || "storage.thirdweb-dev.com"; + +export const THIRDWEB_SOCIAL_API_DOMAIN = + process.env.THIRDWEB_SOCIAL_URL || "social.thirdweb-dev.com"; + +export const THIRDWEB_BUNDLER_DOMAIN = + process.env.THIRDWEB_BUNDLER_URL || "bundler.thirdweb-dev.com"; diff --git a/src/db/apply-migrations.ts b/src/db/apply-migrations.ts new file mode 100644 index 000000000..c90d21fbd --- /dev/null +++ b/src/db/apply-migrations.ts @@ -0,0 +1,49 @@ +import { drizzle } from "drizzle-orm/node-postgres"; +import { migrate } from "drizzle-orm/node-postgres/migrator"; +import pg from "pg"; +import { env } from "../lib/env.js"; +import { initializeLogger } from "../lib/logger.js"; +import * as schema from "./schema.js"; + +const ZEET_ENVIRONMENT = process.env.ZEET_ENVIRONMENT; +// zeet env to run migrations on +const ZEET_ENVS = ["main", "production"]; + +const migrationLogger = initializeLogger("migrations"); + +export async function applyMigrations() { + const canRunMigration = + (ZEET_ENVIRONMENT && ZEET_ENVS.includes(ZEET_ENVIRONMENT)) || + process.env.NODE_ENV === "test" || + env.FORCE_DB_MIGRATION; + // only run migrations on zeet environments that aren't feature branches + if (canRunMigration) { + migrationLogger.info( + "Running migrations on zeet environment:", + ZEET_ENVIRONMENT + ); + + const client = new pg.Client({ + connectionString: env.POSTGRES_CONNECTION_URL, + ssl: { + rejectUnauthorized: false, + }, + }); + + await client.connect(); + + const db = drizzle(client, { schema }); + await migrate(db, { + migrationsFolder: "./drizzle", + }); + + await client.end(); + migrationLogger.info("Migrations complete"); + } else { + migrationLogger.info( + "Not on zeet, or on feature branch, skipping migrations" + ); + } +} + +await applyMigrations(); diff --git a/src/db/connection.ts b/src/db/connection.ts new file mode 100644 index 000000000..5e65b1c9d --- /dev/null +++ b/src/db/connection.ts @@ -0,0 +1,16 @@ +import { drizzle } from "drizzle-orm/node-postgres"; +import pg from "pg"; +import { env } from "../lib/env.js"; +import * as schema from "./schema.js"; + +const primaryDb = drizzle( + new pg.Pool({ + connectionString: env.POSTGRES_CONNECTION_URL, + ssl: { + rejectUnauthorized: false, + }, + }), + { schema } +); + +export const db = primaryDb; diff --git a/src/db/derived-schemas.ts b/src/db/derived-schemas.ts new file mode 100644 index 000000000..610868545 --- /dev/null +++ b/src/db/derived-schemas.ts @@ -0,0 +1,5 @@ +import { createSelectSchema } from "drizzle-zod"; +import { tokens, transactions } from "./schema.js"; + +export const transactionDbEntrySchema = createSelectSchema(transactions); +export const accessTokenDbEntrySchema = createSelectSchema(tokens); diff --git a/src/db/schema.ts b/src/db/schema.ts new file mode 100644 index 000000000..dddeef6b7 --- /dev/null +++ b/src/db/schema.ts @@ -0,0 +1,310 @@ +import { + pgTable, + timestamp, + text, + jsonb, + uniqueIndex, + index, + boolean, + uuid, + json, + primaryKey, + integer, +} from "drizzle-orm/pg-core"; +import { relations, sql } from "drizzle-orm"; +import type { Address, Chain, Hex } from "thirdweb"; +import { + ENGINE_EOA_TYPES, + type ExecutionParamsSerialized, + type ExecutionResultSerialized, + type Permission, + type TransactionParamsSerialized, + type WebhookEventType, +} from "./types.js"; +import type { + EoaCredential, + EoaPlatformIdentifiers, + WalletProviderConfigMap, +} from "../lib/accounts/accounts.js"; + +export const configuration = pgTable("configuration", { + id: text().default("default").primaryKey().notNull(), + chainOverrides: json().default([]).$type().notNull(), + + webhookAuthBearerToken: text(), + + authDomain: text().notNull().default("thirdweb.com"), + authEoaEncryptedJson: text().notNull(), + + accessControlAllowOrigin: json() + .$type() + .default(["https://thirdweb.com/", "https://embed.ipfscdn.io/"]) + .notNull(), + + ipAllowlist: json().array().$type(), + + mtlsCertificateEncrypted: text(), + mtlsPrivateKeyEncrypted: text(), + + walletProviderConfigs: json() + .$type>() + .default({}) + .notNull(), +}); + +export const transactions = pgTable( + "transactions", + { + // id is idempotency key + id: text().notNull(), + // batch index is to identify and deduplicate transactions in the same batch + batchIndex: integer().notNull(), + + clientId: text().notNull().default("PRE_MIGRATION"), + + chainId: text().notNull(), + + from: text().$type
(), /// this is high-level, not the from address of the EOA transaction. for AA, this will be the Smart Account + + transactionParams: jsonb().$type().notNull(), + + transactionHash: text().$type(), + confirmedAt: timestamp({ withTimezone: true }), + confirmedAtBlockNumber: text(), + + enrichedData: jsonb().default([]).notNull(), // store transaction enriched data if available + + executionParams: jsonb().$type().notNull(), // store executor specific parameters + // eg: + // - for erc4337, store signerAddress + // can store overrides like gas, nonce etc + + executionResult: jsonb().$type(), // store executor specific result + // for eg eoa will contain the receipt + // external 4337 will contain the receipt, userophash, gasdata etc + + // functionName: text(), + // functionArgs: text(), + // extension: text(), + // deployedContractAddress: text(), + // deployedContractType: text(), + // ^ these are now enriched data + + // these are now executor specific, and will represent intermediate stages that vary per executor + // queuedAt: timestamp().defaultNow().notNull() + // processedAt: timestamp(), + // sentAt: timestamp(), + // minedAt: timestamp(), + + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + errorMessage: text(), + cancelledAt: timestamp({ withTimezone: true }), + }, + (table) => [ + primaryKey({ columns: [table.id, table.batchIndex] }), + index("transaction_hash_idx").on(table.transactionHash), + index("client_id_idx").on(table.clientId), + index("from_idx").on(table.from), + index("execution_params_idx").using("gin", table.executionParams), + index("execution_result_idx").using("gin", table.executionResult), + ], +); + +export const permissions = pgTable("permissions", { + accountAddress: text().$type
().primaryKey().notNull(), + permissions: text().$type().notNull(), + label: text(), +}); + +export const tokens = pgTable("tokens", { + id: text().primaryKey(), + + tokenMask: text().notNull(), + accountAddress: text().notNull(), + + isAccessToken: boolean().notNull(), + label: text(), + + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + expiresAt: timestamp({ withTimezone: true }).notNull(), + revokedAt: timestamp({ withTimezone: true }), +}); + +export const relayers = pgTable("relayers", { + id: uuid().defaultRandom().primaryKey(), + label: text(), + chainId: text().notNull(), + accountAddress: text().$type
().notNull(), // reconsider tying to accountAddress,fk? + + allowedContracts: jsonb().$type().default([]), + allowedForwarders: jsonb().$type().default([]), +}); + +export const webhooks = pgTable("webhooks", { + id: uuid().defaultRandom().primaryKey(), + label: text(), + url: text().notNull(), + secret: text().notNull(), + eventType: text().$type().notNull(), + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp({ withTimezone: true }) + .notNull() + .$onUpdate(() => new Date()), + revokedAt: timestamp({ withTimezone: true }), +}); + +export const eoaCredentials = pgTable( + "eoa_credentials", + { + id: uuid().defaultRandom().primaryKey(), + type: text().notNull(), + label: text().notNull(), + data: json().$type().notNull(), + isDefault: boolean().notNull().default(false), + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp({ withTimezone: true }) + .notNull() + .$onUpdate(() => new Date()), + deletedAt: timestamp({ withTimezone: true }), + }, + (table) => [ + index("eoa_credentials_type_idx").on(table.type), + uniqueIndex("eoa_credentials_type_is_default_key") + .on(table.type) + .where(sql`${table.isDefault} IS TRUE`), + index("eoa_credentials_deleted_at_not_null_idx") + .on(table.deletedAt) + .where(sql`${table.deletedAt} IS NOT NULL`), + ], +); + +export const eoas = pgTable( + "eoas", + { + address: text().$type
().primaryKey(), + type: text({ enum: ENGINE_EOA_TYPES }).notNull(), + encryptedJson: text(), + label: text().notNull(), + + credentialId: uuid().references(() => eoaCredentials.id, { + onDelete: "set null", + onUpdate: "cascade", + }), + + platformIdentifiers: jsonb().$type(), + + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp({ withTimezone: true }) + .$onUpdate(() => new Date()) + .notNull(), + deletedAt: timestamp({ withTimezone: true }), + }, + (table) => [ + index("eoas_deleted_at_not_null_idx") + .on(table.deletedAt) + .where(sql`${table.deletedAt} IS NOT NULL`), + ], +); + +export const smartAccounts = pgTable( + "smart_accounts", + { + address: text().$type
().notNull(), + signerAddress: text() + .$type
() + .references(() => eoas.address) + .notNull(), + + label: text().notNull(), + factoryAddress: text().$type
().notNull(), + entrypointAddress: text().$type
().notNull(), + accountSalt: text(), + + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp({ withTimezone: true }) + .notNull() + .$onUpdate(() => new Date()), + deletedAt: timestamp({ withTimezone: true }), + }, + (table) => [ + primaryKey({ columns: [table.address, table.signerAddress] }), + index("smart_accounts_signer_address_idx").on(table.signerAddress), + index("smart_accounts_deleted_at_not_null_idx") + .on(table.deletedAt) + .where(sql`${table.deletedAt} IS NOT NULL`), + ], +); + +export const addressSubscriptions = pgTable( + "address_subscriptions", + { + id: uuid().defaultRandom().primaryKey(), + chainId: text().notNull(), + address: text().$type
().notNull(), + conditions: jsonb().array(), + webhookId: uuid().references(() => webhooks.id), + + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp({ withTimezone: true }) + .notNull() + .$onUpdate(() => new Date()), + + deletedAt: timestamp({ withTimezone: true }), + }, + (table) => [ + index("address_subscriptions_deleted_at_not_null_idx") + .on(table.deletedAt) + .where(sql`${table.deletedAt} IS NOT NULL`), + index("address_subscriptions_webhook_id_idx").on(table.webhookId), + index("address_subscriptions_chainId_idx").on(table.chainId), + index("address_subscriptions_address_idx").on(table.address), + ], +); + +export const keypairs = pgTable("keypairs", { + hash: text().primaryKey().notNull(), + publicKey: text().notNull(), + algorithm: text().$type<"RS256" | "ES256" | "PS256">().notNull(), + label: text(), + createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp({ withTimezone: true }) + .notNull() + .$onUpdate(() => new Date()), + deletedAt: timestamp({ withTimezone: true }), +}); + +export const eoasRelations = relations(eoas, ({ one, many }) => ({ + credential: one(eoaCredentials, { + fields: [eoas.credentialId], + references: [eoaCredentials.id], + }), + smartAccounts: many(smartAccounts), +})); + +export const smartAccountsRelations = relations(smartAccounts, ({ one }) => ({ + signer: one(eoas, { + fields: [smartAccounts.signerAddress], + references: [eoas.address], + }), +})); + +export const eoaCredentialsRelations = relations( + eoaCredentials, + ({ many }) => ({ + eoas: many(eoas), + }), +); + +export const addressSubscriptionsRelations = relations( + addressSubscriptions, + ({ one }) => ({ + webhook: one(webhooks, { + fields: [addressSubscriptions.webhookId], + references: [webhooks.id], + }), + }), +); + +export const webhooksRelations = relations(webhooks, ({ many }) => ({ + addressSubscriptions: many(addressSubscriptions), +})); diff --git a/src/db/types.ts b/src/db/types.ts new file mode 100644 index 000000000..02e811d44 --- /dev/null +++ b/src/db/types.ts @@ -0,0 +1,78 @@ +import type { Address, Hex } from "thirdweb"; +import type { + configuration, + keypairs, + permissions, + tokens, + webhooks, +} from "./schema.js"; + +export type ConfigInDb = typeof configuration.$inferSelect; + +export type Permission = "ADMIN" | "OWNER"; +export type PermissionDbEntry = typeof permissions.$inferSelect; +export type KeypairDbEntry = typeof keypairs.$inferSelect; + +export type TokenDbEntry = typeof tokens.$inferSelect; + +export type WebhookEventType = "AUTH" | "TRANSACTION"; +export type WebhookDbEntry = typeof webhooks.$inferSelect; + +export type ExecutionParams4337Serialized = { + type: "AA"; + entrypointAddress: string; + smartAccountAddress: string; + signerAddress: string; +}; + +export const ENGINE_EOA_TYPES = [ + "local", + "aws-kms", + "gcp-kms", + "circle", +] as const; + +export type ExecutionParamsSerialized = ExecutionParams4337Serialized; + +export type RevertDataSerialized = { + errorName: string; + errorArgs: Record; +}; + +export type ExecutionResult4337Serialized = + | { + status: "QUEUED"; + } + | { + status: "FAILED"; + error: string; + } + | { + status: "SUBMITTED"; + monitoringStatus: "WILL_MONITOR" | "CANNOT_MONITOR"; + userOpHash: string; + } + | ({ + status: "CONFIRMED"; + userOpHash: Hex; + transactionHash: Hex; + actualGasCost: string; + actualGasUsed: string; + nonce: string; + } & ( + | { + onchainStatus: "SUCCESS"; + } + | { + onchainStatus: "REVERTED"; + revertData?: RevertDataSerialized; + } + )); + +export type ExecutionResultSerialized = ExecutionResult4337Serialized; + +export type TransactionParamsSerialized = { + to: Address; + data: Hex; + value: string; +}; diff --git a/src/executors/eoa/attempts.ts b/src/executors/eoa/attempts.ts new file mode 100644 index 000000000..e90aabc45 --- /dev/null +++ b/src/executors/eoa/attempts.ts @@ -0,0 +1,272 @@ +import { ResultAsync, errAsync, okAsync } from "neverthrow"; +import { redis } from "../../lib/redis.js"; +import { type NonceDbErr, mapRedisError } from "./nonce.js"; +import SuperJSON from "superjson"; +import { z } from "zod"; +import { evmAddressSchema, hexSchema } from "../../lib/zod.js"; + +// Redis key definitions +const txAttemptKey = ({ + txId, + attemptNo, +}: { + txId: string; + attemptNo?: number; +}) => `tx:attempts:${txId}:${attemptNo ?? ""}`; + +const txCurrentAttemptKey = (txId: string) => `tx:attempts:${txId}:current`; +// Valid error codes from TransactionSendError +export type TransactionSendErrorCode = z.infer< + typeof transactionErrorSchema.shape.code +>; + +// Error object schema +export type TransactionError = { + code: TransactionSendErrorCode; + message: string; +}; + +// Transaction attempt schema +export type TransactionAttempt = z.infer; + +// Zod schema for validation +const transactionErrorSchema = z.object({ + code: z.enum([ + "gas_too_low", + "insufficient_funds", + "nonce_too_low", + "nonce_too_high", + "replacement_underpriced", + "already_known", + "unknown_rpc_error", + "other_engine_error" + ]), + message: z.string(), +}); + +const baseTxAttemptSchema = z.object({ + from: evmAddressSchema, + chainId: z.string(), + to: evmAddressSchema.optional(), + data: hexSchema, + value: z.coerce.bigint().optional(), + nonce: z.number(), + gas: z.coerce.bigint(), + hash: hexSchema, + error: transactionErrorSchema.optional(), +}); + +const legacyFeeSchema = z.object({ + feeType: z.literal("legacy"), + gasPrice: z.coerce.bigint(), // Will be parsed as bigint +}); + +const eip1559FeeSchema = z.object({ + feeType: z.literal("eip1559"), + maxFeePerGas: z.coerce.bigint(), // Will be parsed as bigint + maxPriorityFeePerGas: z.coerce.bigint(), // Will be parsed as bigint +}); + +const txAttemptSchema = z.union([ + baseTxAttemptSchema.merge(legacyFeeSchema), + baseTxAttemptSchema.merge(eip1559FeeSchema), +]); + +/** + * Records a transaction attempt in Redis + * @param txId The transaction ID + * @param attempt The transaction attempt details + * @returns A Result indicating success or failure + */ +export function recordTransactionAttempt( + txId: string, + attempt: TransactionAttempt +): ResultAsync { + return ResultAsync.fromPromise( + redis + .multi() + .incr(txCurrentAttemptKey(txId)) + .get(txCurrentAttemptKey(txId)) + .exec(), + mapRedisError + ).andThen((result) => { + if (!result) { + return errAsync({ + kind: "nonce_db_err", + code: "unknown_redis_err", + } as NonceDbErr); + } + + const [_, innerResult] = result; + + if (!innerResult) { + return errAsync({ + kind: "nonce_db_err", + code: "unknown_redis_err", + } as NonceDbErr); + } + + const [err, currentAttemptStr] = innerResult; + + if (err) { + return errAsync({ + kind: "nonce_db_err", + code: "unknown_redis_err", + } as NonceDbErr); + } + + const currentAttempt = Number(currentAttemptStr); + if (!Number.isFinite(currentAttempt)) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + // Serialize the attempt with SuperJSON to handle bigint values + const serializedAttempt = SuperJSON.stringify(attempt); + + return ResultAsync.fromPromise( + redis.set( + txAttemptKey({ txId, attemptNo: currentAttempt }), + serializedAttempt + ), + mapRedisError + ).map(() => currentAttempt); + }); +} + +/** + * Gets the current attempt number for a transaction + * @param txId The transaction ID + * @returns A Result containing the current attempt number or 0 if not found + */ +export function getCurrentAttemptNumber( + txId: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.get(txCurrentAttemptKey(txId)), + mapRedisError + ).map((value) => Number(value || 0)); +} + +/** + * Gets a specific transaction attempt + * @param txId The transaction ID + * @param attemptNo The attempt number to retrieve + * @returns A Result containing the transaction attempt or null if not found + */ +export function getTransactionAttempt( + txId: string, + attemptNo: number +): ResultAsync { + return ResultAsync.fromPromise( + redis.get(txAttemptKey({ txId, attemptNo })), + mapRedisError + ).andThen((serializedAttempt) => { + if (!serializedAttempt) { + return okAsync(null); + } + + const parsed = SuperJSON.parse(serializedAttempt); + const validationResult = txAttemptSchema.safeParse(parsed); + + if (!validationResult.success) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + return okAsync(SuperJSON.parse(serializedAttempt) as TransactionAttempt); + }); +} + +/** + * Gets the current transaction attempt atomically + * @param txId The transaction ID + * @returns A Result containing the current transaction attempt or null if not found + */ +export function getCurrentTransactionAttempt( + txId: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.eval( + ` + local currentAttempt = redis.call('get', KEYS[1]) + if not currentAttempt or tonumber(currentAttempt) == 0 then + return nil + end + + local attempt = redis.call('get', KEYS[2] .. currentAttempt) + if not attempt then + return nil + end + + return attempt + `, + 2, + txCurrentAttemptKey(txId), + txAttemptKey({ txId }) + ), + mapRedisError + ).andThen((serializedAttempt) => { + if (!serializedAttempt) { + return okAsync(null); + } + + try { + const parsed = SuperJSON.parse(serializedAttempt as string); + const validationResult = txAttemptSchema.safeParse(parsed); + + if (!validationResult.success) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + return okAsync(validationResult.data); + } catch (error) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + source: error instanceof Error ? error : undefined, + } as NonceDbErr); + } + }); +} + +/** + * Gets all transaction attempts for a transaction + * @param txId The transaction ID + * @returns A Result containing an array of all transaction attempts + */ +export function getAllTransactionAttempts( + txId: string +): ResultAsync< + { attemptNumber: number; attempt: TransactionAttempt }[], + NonceDbErr +> { + return getCurrentAttemptNumber(txId).andThen((currentAttempt) => { + if (currentAttempt === 0) { + return okAsync([]); + } + + // Create an array of ResultAsync for each attempt + const attemptResults = Array.from({ length: currentAttempt }, (_, i) => + getTransactionAttempt(txId, i + 1).map((attempt) => ({ + attemptNumber: i + 1, + attempt, + })) + ); + + // Combine all results and handle errors + return ResultAsync.combine(attemptResults).map((attempts) => + attempts.filter( + (a): a is { attemptNumber: number; attempt: TransactionAttempt } => + a !== null + ) + ); + }); +} diff --git a/src/executors/eoa/index.ts b/src/executors/eoa/index.ts new file mode 100644 index 000000000..3ce7840a6 --- /dev/null +++ b/src/executors/eoa/index.ts @@ -0,0 +1,1136 @@ +import { type Job, Queue, UnrecoverableError, Worker } from "bullmq"; +import { err, errAsync, ok, okAsync, ResultAsync, safeTry } from "neverthrow"; +import { keccak256 } from "ox/Hash"; +import SuperJSON from "superjson"; +import { + type Address, + type Chain, + eth_getTransactionCount, + eth_getTransactionReceipt, + getRpcClient, + type Hex, + prepareTransaction, + serializeTransaction, + toSerializableTransaction, +} from "thirdweb"; +import type { TransactionReceipt } from "thirdweb/transaction"; +import { getEngineAccount } from "../../lib/accounts/accounts.js"; +import { getChain } from "../../lib/chain.js"; +import { + type AccountActionErr, + accountActionErrorMapper, + type EngineErr, + isEngineErr, + type RpcErr, +} from "../../lib/errors.js"; +import { initializeLogger } from "../../lib/logger.js"; +import { redis } from "../../lib/redis.js"; +import { thirdwebClient } from "../../lib/thirdweb-client.js"; +import { recordTransactionAttempt } from "./attempts.js"; +import { checkEoaIssues, type EoaIssues, setOutOfGasIssue } from "./issues.js"; +import { + checkMissingNonces, + getNonceState, + incrementEngineNonce, + type NonceDbErr, + popRecycledNonce, + recycleNonce, + resetNonceState, + setConfirmedNonceMax, +} from "./nonce.js"; + +const sendLogger = initializeLogger("executor:eoa:send"); +const confirmLogger = initializeLogger("executor:eoa:confirm"); +const resetLogger = initializeLogger("executor:eoa:reset"); +const healLogger = initializeLogger("executor:eoa:heal"); + +const MAX_IN_FLIGHT = 100; +const MAX_RECYCLED_COUNT = 100; + +type ExecutionRequest = { + id: string; + executionOptions: { + accountAddress: Address; + // add gas overrides + }; + chainId: string; + transactionParams: { + to: Address; + data: Hex; + value: string; + }; +}; + +export type ExecutionResult = { + id: string; + transactionHash: Hex; + chainId: string; +}; + +export type ConfirmationResult = { + id: string; + transactionHash: Hex; + blockNumber: bigint; + gasUsed: bigint; + effectiveGasPrice: bigint; + status: "success" | "reverted"; +}; + +type NonceResetRequest = { + address: Address; + chainId: string; +}; + +type SendJobClearRequest = { + id: string; + attempt: number; +}; + +type NonceHoleHealingRequest = { + address: Address; + chainId: string; +}; + +export type QueueingErr = { + kind: "queue"; + code: + | "eoa:queuing_send_job_failed" + | "eoa:queuing_confirm_job_failed" + | "eoa:queuing_nonce_reset_job_failed" + | "eoa:queuing_send_job_clear_job_failed" + | "eoa:queuing_nonce_hole_healing_job_failed"; + source: Error; +}; + +// Callbacks for confirmation results +const callbacks: ((result: ConfirmationResult) => void)[] = []; + +export function registerCallback( + callback: (result: ConfirmationResult) => void, +) { + confirmLogger.info(`Registered callback ${callback.name}`); + callbacks.push(callback); +} + +export const EOA_SEND_QUEUE_NAME = "executor-eoa-send"; +export const EOA_CONFIRM_QUEUE_NAME = "executor-eoa-confirm"; +export const EOA_NONCE_RESET_QUEUE_NAME = "executor-eoa-nonce_reset"; +export const EOA_SEND_JOB_CLEAR_QUEUE_NAME = "executor-eoa-send_job_clear"; +export const EOA_NONCE_HOLE_HEALING_QUEUE_NAME = + "executor-eoa-nonce_hole_healing"; + +export const eoaSendQueue = new Queue(EOA_SEND_QUEUE_NAME, { + defaultJobOptions: { + attempts: 60, + backoff: { + type: "fixed", + delay: 1000, + }, + }, + connection: redis, +}); + +export const eoaConfirmQueue = new Queue( + EOA_CONFIRM_QUEUE_NAME, + { + defaultJobOptions: { + attempts: 60, + backoff: { + type: "custom", + }, + }, + connection: redis, + }, +); + +export const eoaNonceResetQueue = new Queue( + EOA_NONCE_RESET_QUEUE_NAME, + { + defaultJobOptions: { + attempts: 3, + backoff: { + type: "exponential", + delay: 1000, + }, + }, + connection: redis, + }, +); + +export const eoaSendJobClearQueue = new Queue( + EOA_SEND_JOB_CLEAR_QUEUE_NAME, + { + connection: redis, + }, +); + +export const eoaNonceHoleHealingQueue = new Queue( + EOA_NONCE_HOLE_HEALING_QUEUE_NAME, + { + connection: redis, + }, +); + +export function execute(request: ExecutionRequest) { + return ResultAsync.fromPromise( + eoaSendQueue.add(request.id, request, { + jobId: request.id, + }), + (err) => + ({ + code: "eoa:queuing_send_job_failed", + kind: "queue", + executionOptions: request.executionOptions, + source: err, + }) as QueueingErr, + ); +} + +// Helper function to queue a nonce reset job +function queueNonceReset(address: Address, chainId: string, job: Job) { + const resetJobId = `reset_${address}_${chainId}`; + return ResultAsync.fromPromise( + eoaNonceResetQueue.add( + resetJobId, + { address, chainId }, + { jobId: resetJobId }, + ), + (err) => + ({ + kind: "queue", + code: "eoa:queuing_nonce_reset_job_failed", + source: err, + }) as QueueingErr, + ) + .mapErr((err) => { + job.log( + `[${new Date().toISOString()}] Failed to queue nonce reset: ${err}`, + ); + sendLogger.error("Failed to queue nonce reset", err); + return err; + }) + .andTee(() => { + job.log( + `[${new Date().toISOString()}] Queued nonce reset job ${resetJobId}`, + ); + sendLogger.info("Queued nonce reset job", { address, chainId }); + }); +} + +// Worker dedicated to handling nonce resets in a deduplicated way +export const nonceResetWorker = new Worker( + EOA_NONCE_RESET_QUEUE_NAME, + async (job) => { + const { address, chainId } = job.data; + resetLogger.info("Processing nonce reset", { address, chainId }); + job.log(`[${new Date().toISOString()}] Starting nonce reset`); + + const chain = await getChain(Number(chainId)); + const rpcRequest = getRpcClient({ + chain, + client: thirdwebClient, + }); + + const result = await safeTry(async function* () { + const newNonce = yield* ResultAsync.fromPromise( + eth_getTransactionCount(rpcRequest, { address }), + (err) => + ({ + code: "get_transaction_count_failed", + kind: "rpc", + status: 500, + address, + chainId, + source: err as Error, + }) as RpcErr, + ); + + job.log(`[${new Date().toISOString()}] Fetched new nonce: ${newNonce}`); + resetLogger.info("Fetched new nonce from chain", { + address, + chainId, + nonce: newNonce, + }); + + const resetResult = yield* resetNonceState(address, chainId, newNonce); + + job.log( + `[${new Date().toISOString()}] Successfully reset nonce state with nonce: ${newNonce}`, + ); + resetLogger.info("Successfully reset nonce state", { + address, + chainId, + nonce: newNonce, + }); + + return okAsync(resetResult); + }); + + if (result.isErr()) { + job.log( + `[${new Date().toISOString()}] Failed to reset nonce state: ${ + result.error + }`, + ); + resetLogger.error("Failed to reset nonce state", result.error); + throw result.error.source ?? new Error(result.error.code); + } + + return result.value; + }, + { + connection: redis, + }, +); + +// Worker dedicated to clearing send jobs in a deduplicated way +// We cannot rely on delaying jobs when they fail because this causes queue contention +// instead we insert a new job with the same id and incremented attempt number +// then we error the old job in a way that does not cause it to be retried +// a job cannot remove itself from the queue, so we rely on this worker to do it +export const sendJobClearWorker = new Worker( + EOA_SEND_JOB_CLEAR_QUEUE_NAME, + async (job) => { + const { id, attempt } = job.data; + + const oldJobId = `${id}_attempt-${attempt}`; + const newJobId = `${id}_attempt-${attempt + 1}`; + + const newJob = await eoaSendQueue.getJob(newJobId); + + if (newJob) { + await eoaSendQueue.remove(oldJobId); + return true; + } + + throw new Error( + `Not clearing job ${oldJobId} because new job ${newJobId} does not exist. Will retry`, + ); + }, + { + connection: redis, + }, +); + +// Custom error types for better error handling +export type EoaTransactionError = + | NonceDbErr + | AccountActionErr + | TransactionSendError; + +export type TransactionSendError = { + kind: "transaction_send"; + code: + | "gas_too_low" + | "insufficient_funds" + | "nonce_too_low" + | "nonce_too_high" + | "replacement_underpriced" + | "already_known" + | "unknown_rpc_error"; + status: number; + address: Address; + chainId: string; + nonce?: number; + message: string; + source?: Error; +}; + +export type PreSendCheckFailedErr = { + kind: "pre_send_check_failed"; + code: "too_many_recycled" | "too_many_inflight" | "eoa_issue"; + issues?: EoaIssues; +}; + +// RPC error mapper for transaction errors +function mapTransactionSendError( + error: unknown, + context: { + address: Address; + chainId: string; + nonce?: number; + }, +): TransactionSendError | EngineErr { + if (isEngineErr(error)) { + return error; + } + + const errorMessageAnyCase = + error instanceof Error ? error.message : String(error); + const errorMessage = errorMessageAnyCase.toLowerCase(); + const { address, chainId, nonce } = context; + + // Check for nonce-related errors + if (errorMessage.includes("nonce too low")) { + return { + kind: "transaction_send", + code: "nonce_too_low", + status: 400, + address, + chainId, + nonce, + message: `Nonce too low: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + } + + if (errorMessage.includes("nonce too high")) { + return { + kind: "transaction_send", + code: "nonce_too_high", + status: 400, + address, + chainId, + nonce, + message: `Nonce too high: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + } + + if (errorMessage.includes("replacement transaction underpriced")) { + return { + kind: "transaction_send", + code: "replacement_underpriced", + status: 400, + address, + chainId, + nonce, + message: `Replacement transaction underpriced: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + } + + if (errorMessage.includes("already known")) { + return { + kind: "transaction_send", + code: "already_known", + status: 400, + address, + chainId, + nonce, + message: `Transaction already known: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + } + + // Check for gas-related errors + if (errorMessage.includes("insufficient funds")) { + return { + kind: "transaction_send", + code: "insufficient_funds", + status: 400, + address, + chainId, + nonce, + message: `Insufficient funds: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + } + + if ( + errorMessage.includes("gas too low") || + errorMessage.includes("intrinsic gas") + ) { + return { + kind: "transaction_send", + code: "gas_too_low", + status: 400, + address, + chainId, + nonce, + message: `Gas too low: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + } + + // Default to unknown RPC error + return { + kind: "transaction_send", + code: "unknown_rpc_error", + status: 500, + address, + chainId, + nonce, + message: `RPC error: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; +} + +function syncConfirmedNonce(address: Address, chain: Chain) { + const rpcRequest = getRpcClient({ + chain, + client: thirdwebClient, + }); + + return ResultAsync.fromPromise( + eth_getTransactionCount(rpcRequest, { + address, + }), + (error): RpcErr => ({ + kind: "rpc", + code: "get_transaction_count_failed", + status: 500, + address, + chainId: chain.id.toString(), + source: error instanceof Error ? error : undefined, + }), + ).andThen((fetchedConfirmedNonce) => + setConfirmedNonceMax(address, chain.id.toString(), fetchedConfirmedNonce), + ); +} + +export const nonceHoleHealingWorker = new Worker< + NonceHoleHealingRequest, + boolean +>( + EOA_NONCE_HOLE_HEALING_QUEUE_NAME, + async (job) => { + const { address, chainId } = job.data; + + const chain = getChain(Number(chainId)); + + healLogger.info("Processing nonce hole healing", { + address, + chainId, + }); + + const result = await safeTry(async function* () { + // Verify confirmed nonce from chain + const { confirmedNonce, engineNonce } = yield* syncConfirmedNonce( + address, + chain, + ); + + if (engineNonce - confirmedNonce < MAX_IN_FLIGHT) { + return okAsync(true); + } + + const missingNoncesResult = await checkMissingNonces(address, chainId); + + if (missingNoncesResult.isErr()) { + if (missingNoncesResult.error.code === "too_many_missing_nonces") { + yield* queueNonceReset(address, chainId, job); + return okAsync(true); + } + return errAsync(missingNoncesResult.error); + } + + const missingNonces = missingNoncesResult.value; + const nonceState = yield* getNonceState(address, chainId); + + if ( + nonceState.recycledCount + missingNonces.length > + MAX_RECYCLED_COUNT + ) { + yield* queueNonceReset(address, chainId, job); + return okAsync(true); + } + + for (const nonce of missingNonces) { + yield* recycleNonce(address, chainId, nonce, nonceState.epoch); + } + + return okAsync(true); + }); + + if (result.isErr()) { + healLogger.error("Failed to process nonce hole healing", result.error); + throw result.error.source ?? new Error(result.error.code); + } + + return result.value; + }, + { connection: redis }, +); + +function queueNonceHoleHealing(address: Address, chainId: string, job: Job) { + job.log(`[${new Date().toISOString()}] Queueing nonce hole healing`); + return ResultAsync.fromPromise( + eoaNonceHoleHealingQueue.add( + `heal_${address}_${chainId}`, + { address, chainId }, + { + jobId: `heal_${address}_${chainId}`, + deduplication: { + id: `heal_${address}_${chainId}`, + ttl: 1000 * 60 * 2, // 2 minutes + }, + }, + ), + (error) => + ({ + kind: "queue", + code: "eoa:queuing_nonce_hole_healing_job_failed", + source: error, + }) as QueueingErr, + ).mapErr((error) => { + job.log(`[${new Date().toISOString()}] Failed to queue nonce hole healing`); + healLogger.error("Failed to queue nonce hole healing", error); + return error; + }); +} + +export const sendWorker = new Worker( + EOA_SEND_QUEUE_NAME, + async (job) => { + const { id, executionOptions, chainId, transactionParams } = job.data; + sendLogger.info("Processing transaction", { + id, + chainId, + address: executionOptions.accountAddress, + }); + + job.log(`[${new Date().toISOString()}] Processing transaction`); + + // Get chain and RPC client outside of ResultAsync chains + const chain = await getChain(Number(chainId)); + const rpcRequest = getRpcClient({ + chain, + client: thirdwebClient, + }); + + const accountResult = await getEngineAccount({ + address: executionOptions.accountAddress, + }); + + if (accountResult.isErr()) { + // call error handler with this error + job.log(`[${new Date().toISOString()}] Error: ${accountResult.error}`); + // make sure this send request fails for good + throw new UnrecoverableError("Account not found"); + } + + // Check if it's a valid EOA account + if ("signerAccount" in accountResult.value) { + // const _error: AccountErr = { + // kind: "account", + // code: "account_not_found", + // status: 400, + // address: executionOptions.accountAddress, + // message: `Specified account ${executionOptions.accountAddress} is a smart account, invalid for EOA execution`, + // }; + + // todo: call error handler with this error + throw new UnrecoverableError("Invalid account type"); + } + + // We know this is a regular EOA account now + const { account } = accountResult.value; + const accountAddress = account.address as Address; + + // Prepare transaction + const preparedTransaction = prepareTransaction({ + chain, + client: thirdwebClient, + data: transactionParams.data, + to: transactionParams.to, + value: transactionParams.value ? BigInt(transactionParams.value) : 0n, + nonce: 0, // hardcoding nonce to skip nonce fetching + }); + + // Serialize the transaction + const serialiseableTransactionResult = await ResultAsync.fromPromise( + toSerializableTransaction({ + transaction: preparedTransaction, + from: account.address, + }), + (error): RpcErr => ({ + kind: "rpc", + code: "serialize_transaction_failed", + status: 500, + address: accountAddress, + chainId, + message: `Failed to serialize transaction: ${ + error instanceof Error ? error.message : String(error) + }`, + source: error instanceof Error ? error : undefined, + }), + ); + + if (serialiseableTransactionResult.isErr()) { + // call error handler with this error + job.log( + `[${new Date().toISOString()}] Error: ${ + serialiseableTransactionResult.error + }`, + ); + // let's retry this job + throw serialiseableTransactionResult.error.source instanceof Error + ? serialiseableTransactionResult.error.source + : new Error( + serialiseableTransactionResult.error.message ?? + "Failed to serialize transaction", + ); + } + + const serialisableTransaction = serialiseableTransactionResult.value; + + job.log( + `[${new Date().toISOString()}] Serialised transaction: ${SuperJSON.stringify( + serialisableTransaction, + )}`, + ); + + const precheckResult = await safeTry(async function* () { + const issues = yield* checkEoaIssues(accountAddress, chainId); + + if (issues) { + return errAsync({ + kind: "pre_send_check_failed", + code: "eoa_issue", + issues: issues, + } as PreSendCheckFailedErr); + } + // Get the account - getEngineAccount already returns a Result + // Get nonce state - getNonceState already returns a Result + const nonceState = yield* getNonceState(accountAddress, chainId); + + // If we have too many recycled nonces, reset the state + if (nonceState.recycledCount >= MAX_RECYCLED_COUNT) { + // Queue a nonce reset job + yield* queueNonceReset(accountAddress, chainId, job); + sendLogger.warn("Too many recycled nonces, queued nonce reset", { + id, + chainId, + address: accountAddress, + }); + return errAsync({ + kind: "pre_send_check_failed", + code: "too_many_recycled", + } as PreSendCheckFailedErr); + } + + // Check if we have too many in-flight transactions + if (nonceState.inFlight >= MAX_IN_FLIGHT) { + yield* queueNonceHoleHealing(accountAddress, chainId, job); + return errAsync({ + kind: "pre_send_check_failed", + code: "too_many_inflight", + } as PreSendCheckFailedErr); + } + + if (nonceState.recycledCount > 0) { + const recycledNonceReusult = yield* popRecycledNonce( + accountAddress, + chainId, + MAX_RECYCLED_COUNT, + ); + + if (recycledNonceReusult.status === "success") { + return okAsync({ + nonce: recycledNonceReusult.nonce, + epoch: recycledNonceReusult.epoch, + type: "recycled", + }); + } + + if (recycledNonceReusult.status === "oversized") { + yield* queueNonceReset(accountAddress, chainId, job); + return errAsync({ + kind: "pre_send_check_failed", + code: "too_many_recycled", + } as PreSendCheckFailedErr); + } + + // only other option is empty, so we increment outside the if block anyways + } + + const incrementedNonce = yield* incrementEngineNonce( + accountAddress, + chainId, + ); + + return okAsync({ + nonce: incrementedNonce, + type: "incremented", + epoch: nonceState.epoch, + }); + }); + + if (precheckResult.isErr()) { + if (precheckResult.error.kind === "pre_send_check_failed") { + // delete this job, and queue a new job at the end of the queue + // TODO: QUEUE A NEW JOB AT THE END OF THE QUEUE + throw new UnrecoverableError(precheckResult.error.code); + } + // let's retry with delay because it looks like something else went wrong + const error = + precheckResult.error.source instanceof Error + ? precheckResult.error.source + : new Error( + precheckResult.error.code ?? "Failed to precheck transaction", + ); + sendLogger.error("Failed to precheck transaction", precheckResult.error); + throw error; + } + + const nonceValues = precheckResult.value; + const nonceToUse = precheckResult.value.nonce; + + job.log( + `[${new Date().toISOString()}] Sending transaction with ${ + precheckResult.value.type + } nonce ${nonceToUse}`, + ); + + const sendResult = await ResultAsync.fromPromise( + account.sendTransaction({ + ...serialisableTransaction, + nonce: nonceToUse, + }), + (error) => + mapTransactionSendError(error, { + address: accountAddress, + chainId, + nonce: nonceToUse, + }), + ); + + const serialisedTransaction = serializeTransaction({ + transaction: serialisableTransaction, + }); + const computedTransactionHash = keccak256(serialisedTransaction); + + if (sendResult.isErr()) { + const error = sendResult.error; + if (error.kind === "transaction_send") { + await safeTry(async function* () { + if (error.code === "nonce_too_low") { + let receivedReceipt: TransactionReceipt | undefined = undefined; + try { + receivedReceipt = await eth_getTransactionReceipt(rpcRequest, { + hash: computedTransactionHash, + }); + } catch (e) { + if (e instanceof Error && e.message.includes("not found")) { + // do nothing + } else { + return errAsync( + accountActionErrorMapper({ + code: "get_transaction_receipt_failed", + }), + ); + } + } + + if (receivedReceipt) { + yield* queueConfirmationJob({ + id, + transactionHash: computedTransactionHash, + chainId, + }); + + return okAsync({ + transactionHash: computedTransactionHash, + }); + } + + // since nonce too low, no need to recycle nonce, but let's sync the confirmed nonce + yield* syncConfirmedNonce(accountAddress, chain); + return okAsync(null); + } + + if (error.code === "already_known") { + yield* queueConfirmationJob({ + id, + transactionHash: computedTransactionHash, + chainId, + }); + + return okAsync({ + transactionHash: computedTransactionHash, + }); + } + + if (error.code === "nonce_too_high") { + yield* queueNonceHoleHealing(accountAddress, chainId, job); + return okAsync(null); + } + + if (error.code === "replacement_underpriced") { + yield* queueNonceHoleHealing(accountAddress, chainId, job); + return okAsync(null); + } + + if (error.code === "insufficient_funds") { + yield* setOutOfGasIssue( + accountAddress, + chainId, + serialisableTransaction.gas * + (serialisableTransaction.gasPrice ?? + serialisableTransaction.maxFeePerGas ?? + 0n), + ); + } + + yield* recycleNonce( + accountAddress, + chainId, + nonceToUse, + nonceValues.epoch, + ); + return okAsync(null); + }); + } + } + + const feeType = + typeof serialisableTransaction.maxFeePerGas !== "undefined" + ? "eip1559" + : "legacy"; + + const feeData = + feeType === "eip1559" + ? { + feeType: "eip1559" as const, + maxFeePerGas: serialisableTransaction.maxFeePerGas as bigint, + maxPriorityFeePerGas: + serialisableTransaction.maxPriorityFeePerGas as bigint, + } + : { + feeType: "legacy" as const, + gasPrice: serialisableTransaction.gasPrice as bigint, + }; + + await recordTransactionAttempt(id, { + chainId, + data: serialisableTransaction.data, + from: accountAddress, + hash: computedTransactionHash, + to: serialisableTransaction.to as Address | undefined, + gas: serialisableTransaction.gas, + nonce: nonceToUse, + value: serialisableTransaction.value, + error: sendResult.isErr() + ? sendResult.error.kind === "transaction_send" + ? sendResult.error + : { code: "other_engine_error", message: sendResult.error.code } + : undefined, + ...feeData, + }); + + if (sendResult.isOk()) { + const transactionResponse = sendResult.value; + const transactionHash = transactionResponse.transactionHash; + + job.log( + `[${new Date().toISOString()}] Transaction sent successfully with hash ${transactionHash} and nonce ${nonceToUse}`, + ); + + sendLogger.info("Transaction sent successfully", { + id, + chainId, + transactionHash, + nonce: nonceToUse, + }); + + await queueConfirmationJob({ + id, + transactionHash, + chainId, + }); + + return true; + } + + throw new Error("Failed to send transaction"); + }, + { + connection: redis, + settings: { + backoffStrategy: (attemptsMade: number) => { + if (attemptsMade === 1) return 2000; // First check after 2s + if (attemptsMade <= 11) return 10000; // Every 10s for first ~2min + if (attemptsMade <= 23) return 30000; // Every 30s until ~5min mark + return 60000; // Every 1min thereafter + }, + }, + }, +); + +function queueConfirmationJob({ + id, + transactionHash, + chainId, +}: { + id: string; + transactionHash: Hex; + chainId: string; +}) { + return ResultAsync.fromPromise( + eoaConfirmQueue.add(transactionHash, { + id, + transactionHash, + chainId, + }), + (error): QueueingErr => ({ + kind: "queue", + code: "eoa:queuing_confirm_job_failed", + source: error as Error, + }), + ); +} + +export const confirmWorker = new Worker( + EOA_CONFIRM_QUEUE_NAME, + async (job) => { + const { id, transactionHash, chainId } = job.data; + + confirmLogger.info("Confirming transaction", { + id, + transactionHash, + chainId, + }); + job.log( + `[${new Date().toISOString()}] Confirming transaction ${transactionHash}`, + ); + + // Get chain outside of ResultAsync chains + const chain = getChain(Number(chainId)); + const rpcClient = getRpcClient({ + chain, + client: thirdwebClient, + }); + + // Get transaction receipt + const result = await ResultAsync.fromPromise( + eth_getTransactionReceipt(rpcClient, { hash: transactionHash }), + (error): RpcErr => { + const errorMessage = + error instanceof Error ? error.message : String(error); + + confirmLogger.debug("Transaction receipt not available yet", { + id, + transactionHash, + chainId, + error: errorMessage, + attempt: job.attemptsMade + 1, + }); + + return { + kind: "rpc", + code: "get_transaction_receipt_failed", + status: 404, + transactionHash, + message: `Transaction receipt not found: ${errorMessage}`, + source: error instanceof Error ? error : undefined, + }; + }, + ).andThen((receipt) => { + // If receipt is null, the transaction hasn't been mined yet + if (!receipt) { + job.log( + `[${new Date().toISOString()}] Transaction not confirmed yet, attempt ${ + job.attemptsMade + 1 + }/60`, + ); + + return err({ + kind: "rpc", + code: "get_transaction_receipt_failed", + status: 404, + transactionHash, + message: "Transaction not mined yet", + } as RpcErr); + } + + // Check if the transaction was successful or reverted + const status = receipt.status ? "success" : "reverted"; + + const confirmationResult: ConfirmationResult = { + id, + transactionHash, + blockNumber: receipt.blockNumber, + gasUsed: receipt.gasUsed, + effectiveGasPrice: receipt.effectiveGasPrice, + status, + }; + + job.log( + `[${new Date().toISOString()}] Transaction confirmed with status ${status} at block ${ + receipt.blockNumber + }`, + ); + + confirmLogger.info("Transaction confirmed", { + id, + transactionHash, + status, + blockNumber: receipt.blockNumber, + }); + + // Notify callbacks + for (const callback of callbacks) { + try { + callback(confirmationResult); + } catch (cbError) { + confirmLogger.error("Error in confirmation callback", cbError, { + id, + transactionHash, + }); + } + } + + return ok( + SuperJSON.serialize(confirmationResult) + .json as unknown as ConfirmationResult, + ); + }); + + return result.match( + // Success path + (success) => success, + // Error path + (error) => { + // Check if we've reached the maximum retry attempts + if (job.attemptsMade >= 59) { + confirmLogger.error( + "Failed to confirm transaction after maximum attempts", + { + id, + transactionHash, + chainId, + error, + }, + ); + + job.log( + `[${new Date().toISOString()}] Failed to confirm transaction after maximum attempts`, + ); + + // Return a placeholder result with reverted status after max attempts + return { + id, + transactionHash, + blockNumber: 0n, + gasUsed: 0n, + effectiveGasPrice: 0n, + status: "reverted" as const, + }; + } + + // For all other attempts, throw the error to trigger a retry + throw new Error(error.message || "Failed to confirm transaction"); + }, + ); + }, + { + connection: redis, + settings: { + backoffStrategy: (attemptsMade: number) => { + if (attemptsMade === 1) return 2000; // First check after 2s + if (attemptsMade <= 11) return 10000; // Every 10s for first ~2min + if (attemptsMade <= 23) return 30000; // Every 30s until ~5min mark + return 60000; // Every 1min thereafter + }, + }, + }, +); + +confirmWorker.on("ready", () => { + confirmLogger.info("worker ready"); +}); + +confirmWorker.on("error", (err) => { + confirmLogger.error("worker error", err); +}); diff --git a/src/executors/eoa/issues.ts b/src/executors/eoa/issues.ts new file mode 100644 index 000000000..de40169ac --- /dev/null +++ b/src/executors/eoa/issues.ts @@ -0,0 +1,223 @@ +import { eth_getBalance, getRpcClient, type Address } from "thirdweb"; +import { okAsync, ResultAsync } from "neverthrow"; +import { redis } from "../../lib/redis.js"; +import { getChain } from "../../lib/chain.js"; +import { z } from "zod"; +import { thirdwebClient } from "../../lib/thirdweb-client.js"; +import { accountActionErrorMapper, type EngineErr } from "../../lib/errors.js"; + +// Key for tracking EOA issues +const eoaIssuesKey = ({ + address, + chainId, +}: { + address: Address; + chainId: string; +}) => `eoa-issues:${address}:${chainId}`; + +// Issue types +export const EOA_ISSUE_CODES = ["out_of_gas"] as const; +export type EoaIssueCode = (typeof EOA_ISSUE_CODES)[number]; + +// Stale time constants (in milliseconds) +export const ISSUE_STALE_TIMES: Record = { + out_of_gas: 60 * 1000, // 1 minute +}; + +export const outOfGasIssueSchema = z.object({ + type: z.literal("out_of_gas"), + timestamp: z.coerce.number(), + threshold: z.coerce.bigint(), +}); + +export const eoaIssueSchema = z.discriminatedUnion("type", [ + outOfGasIssueSchema, +]); + +type EoaIssue = z.infer; + +export type EoaIssues = { + [key in EoaIssueCode]?: Extract & { + isStale: boolean; + }; +}; + +export type EoaIssueDbErr = { + kind: "eoa_issue_db_err"; + code: "unknown_redis_err" | "corruption_err"; + source?: Error; +}; + +export const mapRedisError = (error: unknown): EoaIssueDbErr => ({ + kind: "eoa_issue_db_err", + code: "unknown_redis_err", + source: error instanceof Error ? error : undefined, +}); + +/** + * Sets an out of gas issue for an EOA wallet with the current timestamp and threshold + * + * @param address The account address + * @param chainId The chain ID + * @param threshold The balance threshold below which the wallet is considered out of gas + * @returns A Result indicating success or failure + */ +export function setOutOfGasIssue( + address: Address, + chainId: string, + threshold: bigint +): ResultAsync { + const timestamp = Date.now(); + const issueData = JSON.stringify({ + timestamp, + threshold: threshold.toString(), + }); + + return ResultAsync.fromPromise( + redis.hset(eoaIssuesKey({ address, chainId }), "out_of_gas", issueData), + mapRedisError + ).map(() => true); +} + +/** + * Gets all issues for an EOA wallet and marks which ones are stale + * + * @param address The account address + * @param chainId The chain ID + * @returns A Result containing the issues or null if no issues + */ +export function getEoaIssues( + address: Address, + chainId: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.hgetall(eoaIssuesKey({ address, chainId })), + mapRedisError + ).map((result) => { + if (!result || Object.keys(result).length === 0) { + return null; + } + + const now = Date.now(); + const issues: EoaIssues = {}; + + for (const [issueType, issueDataStr] of Object.entries(result)) { + const issue = JSON.parse(issueDataStr); + issue.type = issueType as EoaIssueCode; + + const parsedIssue = eoaIssueSchema.safeParse(issue); + + if (!parsedIssue.success) { + continue; + } + + const isStale = + now - parsedIssue.data.timestamp > + ISSUE_STALE_TIMES[parsedIssue.data.type]; + + issues[parsedIssue.data.type] = { + ...parsedIssue.data, + isStale, + }; + } + return Object.keys(issues).length > 0 ? issues : null; + }); +} + +/** + * Removes an issue for an EOA wallet + * + * @param address The account address + * @param chainId The chain ID + * @param issueType The type of issue to remove + * @returns A Result indicating success or failure + */ +export function removeEoaIssue( + address: Address, + chainId: string, + issueType: EoaIssueCode +): ResultAsync { + return ResultAsync.fromPromise( + redis.hdel(eoaIssuesKey({ address, chainId }), issueType), + mapRedisError + ).map((count) => count > 0); +} + +/** + * Checks for issues on a wallet chain, fetches issues, and refreshes stale ones + * + * @param address The account address + * @param chainId The chain ID + * @returns A Result containing the issues or null if no issues + */ +export function checkEoaIssues(address: Address, chainId: string) { + return getEoaIssues(address, chainId).andThen((issues) => { + if (!issues) { + return okAsync(null); + } + + // Check for stale issues and refresh them if needed + const refreshPromises: Array< + ResultAsync + > = []; + + for (const issueKey of Object.keys(issues)) { + const issue = issues[issueKey as EoaIssueCode]; + + if (issue?.isStale) { + // For each stale issue, check if it still exists + switch (issue.type) { + case "out_of_gas": + if (issue.threshold) { + refreshPromises.push( + checkOutOfGasIssue(address, chainId, issue.threshold) + ); + } + break; + // Add more cases for other issue types + } + } + } + + if (refreshPromises.length === 0) { + return okAsync(issues); + } + + // Wait for all refresh operations to complete + return ResultAsync.combine(refreshPromises).andThen(() => { + // Get the updated issues + return getEoaIssues(address, chainId); + }); + }); +} + +/** + * Checks if an EOA wallet has an out of gas issue + * + * @param address The account address + * @param chainId The chain ID + * @param threshold The balance threshold below which the wallet is considered out of gas + * @returns A Result indicating if the issue exists + */ +export function checkOutOfGasIssue( + address: Address, + chainId: string, + threshold: bigint +): ResultAsync { + return ResultAsync.fromPromise( + (async () => { + const chain = await getChain(Number(chainId)); + const rpcRequest = getRpcClient({ chain, client: thirdwebClient }); + return eth_getBalance(rpcRequest, { address }); + })(), + accountActionErrorMapper({ chainId, address, code: "get_balance_failed" }) + ).andThen((balance) => { + if (balance <= threshold) { + // If the issue exists, update the timestamp + return setOutOfGasIssue(address, chainId, threshold); + } + + // If the issue doesn't exist, remove it + return removeEoaIssue(address, chainId, "out_of_gas"); + }); +} diff --git a/src/executors/eoa/nonce.ts b/src/executors/eoa/nonce.ts new file mode 100644 index 000000000..b843bb70f --- /dev/null +++ b/src/executors/eoa/nonce.ts @@ -0,0 +1,544 @@ +import type { Address } from "thirdweb"; +import { errAsync, okAsync, ResultAsync } from "neverthrow"; +import { redis } from "../../lib/redis.js"; +import { randomUUID } from "node:crypto"; + +const engineNonceKey = ({ + address, + chainId, +}: { + address: Address; + chainId: string; +}) => `nonce:${address}:${chainId}`; + +const confirmedNonceKey = ({ + address, + chainId, +}: { + address: Address; + chainId: string; +}) => `nonce-confirmed:${address}:${chainId}`; + +const recycledNoncesKey = ({ + address, + chainId, +}: { + address: Address; + chainId: string; +}) => `nonce-recycled:${address}:${chainId}`; + +const epochKey = ({ + address, + chainId, +}: { + address: Address; + chainId: string; +}) => `nonce-epoch:${address}:${chainId}`; + +// Key for tracking in-flight nonces (nonces that have been used but not yet confirmed) +const inflightNoncesKey = ({ + address, + chainId, +}: { + address: Address; + chainId: string; +}) => `inflight:nonces:${address}:${chainId}`; + +export type NonceDbErr = { + kind: "nonce_db_err"; + code: "unknown_redis_err" | "corruption_err" | "too_many_missing_nonces"; + source?: Error; + missingNonces?: number[]; +}; + +export const mapRedisError = (error: unknown): NonceDbErr => ({ + kind: "nonce_db_err", + code: "unknown_redis_err", + source: error instanceof Error ? error : undefined, +}); + +type RecycledNonceResult = + | { status: "success"; nonce: number; epoch: string } + | { status: "empty" } + | { status: "oversized"; count: number }; + +/** + * Records a transaction that was just sent with a specific nonce + * Maps the nonce to a transaction ID in the in-flight nonces hashmap + * + * @param address The account address + * @param chainId The chain ID + * @param nonce The nonce used for the transaction + * @param txId The transaction ID + * @returns A Result indicating success or failure + */ +export function recordInflightNonce( + address: Address, + chainId: string, + nonce: number, + txId: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.hset( + inflightNoncesKey({ address, chainId }), + nonce.toString(), + txId + ), + mapRedisError + ).map(() => true); +} + +/** + * Removes a nonce from the in-flight nonces hashmap when a transaction is confirmed + * + * @param address The account address + * @param chainId The chain ID + * @param nonce The nonce to remove + * @returns A Result indicating success or failure + */ +export function removeInflightNonce( + address: Address, + chainId: string, + nonce: number +): ResultAsync { + return ResultAsync.fromPromise( + redis.hdel(inflightNoncesKey({ address, chainId }), nonce.toString()), + mapRedisError + ).map((count) => count > 0); +} + +/** + * Gets all in-flight nonces for an account on a specific chain + * + * @param address The account address + * @param chainId The chain ID + * @returns A Result containing a map of nonce to txId + */ +export function getInflightNonces( + address: Address, + chainId: string +): ResultAsync, NonceDbErr> { + return ResultAsync.fromPromise( + redis.hgetall(inflightNoncesKey({ address, chainId })), + mapRedisError + ).map((result) => { + const nonceMap = new Map(); + + for (const [nonceStr, txId] of Object.entries(result)) { + const nonce = Number(nonceStr); + if (Number.isFinite(nonce)) { + nonceMap.set(nonce, txId); + } + } + + return nonceMap; + }); +} + +/** + * Checks for missing nonces between confirmed and engine nonce + * Returns a list of missing nonces if any are found + * If more than 100 nonces are missing, returns an error + * + * @param address The account address + * @param chainId The chain ID + * @returns A Result containing an array of missing nonces or an error if too many are missing + */ +export function checkMissingNonces( + address: Address, + chainId: string +): ResultAsync { + const MAX_MISSING_NONCES = 100; + + return ResultAsync.fromPromise( + redis.eval( + ` + local engineNonceKey = KEYS[1] + local confirmedNonceKey = KEYS[2] + local inflightNoncesKey = KEYS[3] + + local engineNonce = tonumber(redis.call('get', engineNonceKey) or '0') + local confirmedNonce = tonumber(redis.call('get', confirmedNonceKey) or '0') + + -- Get all in-flight nonces + local inflightNonces = redis.call('hkeys', inflightNoncesKey) + local inflightSet = {} + + -- Convert to a set for O(1) lookups + for i, nonceStr in ipairs(inflightNonces) do + inflightSet[tonumber(nonceStr)] = true + end + + -- Find missing nonces + local missingNonces = {} + for nonce = confirmedNonce + 1, engineNonce do + if not inflightSet[nonce] then + table.insert(missingNonces, nonce) + -- If we have too many missing nonces, return early + if #missingNonces > tonumber(ARGV[1]) then + return 'too_many_missing' + end + end + end + + return missingNonces + `, + 3, + engineNonceKey({ address, chainId }), + confirmedNonceKey({ address, chainId }), + inflightNoncesKey({ address, chainId }), + MAX_MISSING_NONCES.toString() + ), + mapRedisError + ).andThen((result) => { + if (result === 'too_many_missing') { + return errAsync({ + kind: "nonce_db_err", + code: "too_many_missing_nonces", + } as NonceDbErr); + } + + try { + // The result will already be an array + const missingNonces = result as number[]; + return okAsync(missingNonces); + } catch (error) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + source: error instanceof Error ? error : undefined, + } as NonceDbErr); + } + }); +} + + +export function popRecycledNonce( + address: Address, + chainId: string, + maxSize: number +): ResultAsync { + return ResultAsync.fromPromise( + redis.eval( + ` + local count = redis.call('zcard', KEYS[1]) + if count >= tonumber(ARGV[1]) then + return "oversized:" .. count + end + + local epoch = redis.call('get', KEYS[2]) + if not epoch then + return "empty" + end + + local first = redis.call('zrange', KEYS[1], 0, 0) + if #first == 0 then + return "empty" + end + + redis.call('zrem', KEYS[1], first[1]) + return "success:" .. first[1] .. ':' .. epoch + `, + 2, + recycledNoncesKey({ address, chainId }), + epochKey({ address, chainId }), + maxSize.toString() + ), + mapRedisError + ).andThen((result) => { + if (!result) + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + + const parts = (result as string).split(":"); + + if (parts[0] === "oversized") { + return okAsync({ + status: "oversized", + count: Number(parts[1]), + } as RecycledNonceResult); + } + + if (parts[0] === "empty") { + return okAsync({ status: "empty" } as RecycledNonceResult); + } + + if (parts[0] === "success") { + const nonceStr = parts[1]; + const epoch = parts[2]; + const nonce = Number(nonceStr); + + if (!Number.isFinite(nonce) || !epoch) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + return okAsync({ + status: "success", + nonce, + epoch, + } as RecycledNonceResult); + } + + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + }); +} + +export function resetNonceState( + address: Address, + chainId: string, + newNonce: number +): ResultAsync { + return ResultAsync.fromPromise( + redis + .multi() + .set(epochKey({ address, chainId }), randomUUID().toString()) + .set(engineNonceKey({ address, chainId }), newNonce) + .set(confirmedNonceKey({ address, chainId }), newNonce) + .del(recycledNoncesKey({ address, chainId })) + .del(inflightNoncesKey({ address, chainId })) // Also clear in-flight nonces on reset + .exec(), + mapRedisError + ).andThen((result) => { + if (!result || result.some(([err]) => err)) { + return errAsync({ + kind: "nonce_db_err", + code: "unknown_redis_err", + } as NonceDbErr); + } + return okAsync(true as const); + }); +} + +export function getNonceState( + address: Address, + chainId: string +): ResultAsync< + { + engineNonce: number; + confirmedNonce: number; + recycledCount: number; + epoch: string; + inFlight: number; + }, + NonceDbErr +> { + return ResultAsync.fromPromise( + redis.eval( + ` + local engineNonce = redis.call('get', KEYS[1]) or '0' + local confirmedNonce = redis.call('get', KEYS[2]) or '0' + local recycledCount = redis.call('zcard', KEYS[3]) + local epoch = redis.call('get', KEYS[4]) + local inflightCount = redis.call('hlen', KEYS[5]) + + -- Initialize epoch if it doesn't exist + if not epoch then + epoch = ARGV[1] -- UUID passed in + redis.call('set', KEYS[4], epoch) + end + + return engineNonce .. ':' .. confirmedNonce .. ':' .. recycledCount .. ':' .. epoch .. ':' .. inflightCount + `, + 5, + engineNonceKey({ address, chainId }), + confirmedNonceKey({ address, chainId }), + recycledNoncesKey({ address, chainId }), + epochKey({ address, chainId }), + inflightNoncesKey({ address, chainId }), + randomUUID() + ), + mapRedisError + ).andThen((result) => { + const [engineStr, confirmedStr, recycledStr, epoch, inflightStr] = ( + result as string + ).split(":"); + const engineNonce = Number(engineStr); + const confirmedNonce = Number(confirmedStr); + const recycledCount = Number(recycledStr); + const inflightCount = Number(inflightStr); + + if ( + !Number.isFinite(engineNonce) || + !Number.isFinite(confirmedNonce) || + !Number.isFinite(recycledCount) || + !Number.isFinite(inflightCount) || + !epoch + ) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + return okAsync({ + engineNonce, + confirmedNonce, + recycledCount, + epoch, + inFlight: inflightCount, + }); + }); +} + +export function recycleNonce( + address: Address, + chainId: string, + nonce: number, + nonceEpoch: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.eval( + ` + local currentEpoch = redis.call('get', KEYS[1]) + if not currentEpoch or currentEpoch ~= ARGV[2] then + return 0 + end + + redis.call('zadd', KEYS[2], ARGV[1], ARGV[1]) + return 1 + `, + 2, + epochKey({ address, chainId }), + recycledNoncesKey({ address, chainId }), + nonce.toString(), + nonceEpoch + ), + mapRedisError + ).map((result) => result === 1); +} + +export function setEngineNonceMax( + address: Address, + chainId: string, + newValue: number +): ResultAsync { + return ResultAsync.fromPromise( + redis.eval( + ` + local current = redis.call('get', KEYS[1]) + if not current or tonumber(current) < tonumber(ARGV[1]) then + redis.call('set', KEYS[1], ARGV[1]) + return tonumber(ARGV[1]) + end + return tonumber(current) + `, + 1, + engineNonceKey({ address, chainId }), + newValue.toString() + ), + mapRedisError + ).andThen((result) => { + const engineNonce = Number(result); + if (!Number.isFinite(engineNonce)) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + return okAsync(engineNonce); + }); +} + +/** + * Sets the confirmed nonce to max(passed_value, existing_value) + * + * Also removes all recycled nonces that are less than the new confirmed nonce. + * Also removes all in-flight nonces that are less than the new confirmed nonce. + * + * Lastly, it sets the engine nonce to max(passed_value, existing_engine_nonce). + * This is because engineNonce should always be >= confirmedNonce. + * + * @returns the current confirmed nonce and the current engine nonce stored in redis as a result of this operation. + */ +export function setConfirmedNonceMax( + address: Address, + chainId: string, + newValue: number +): ResultAsync<{ confirmedNonce: number; engineNonce: number }, NonceDbErr> { + return ResultAsync.fromPromise( + redis.eval( + ` + local confirmed = redis.call('get', KEYS[1]) + local engine = redis.call('get', KEYS[2]) + + if not confirmed or tonumber(confirmed) < tonumber(ARGV[1]) then + redis.call('set', KEYS[1], ARGV[1]) + confirmed = ARGV[1] + else + confirmed = confirmed + end + + if not engine or tonumber(engine) < tonumber(ARGV[1]) then + redis.call('set', KEYS[2], ARGV[1]) + engine = ARGV[1] + else + engine = engine + end + + -- Remove all recycled nonces less than confirmed nonce + redis.call('zremrangebyscore', KEYS[3], 0, tonumber(confirmed) - 1) + + -- Remove all in-flight nonces less than confirmed nonce + local inflightKeys = redis.call('hkeys', KEYS[4]) + for i, nonceStr in ipairs(inflightKeys) do + local nonce = tonumber(nonceStr) + if nonce < tonumber(confirmed) then + redis.call('hdel', KEYS[4], nonceStr) + end + end + + return confirmed .. ':' .. engine + `, + 4, + confirmedNonceKey({ address, chainId }), + engineNonceKey({ address, chainId }), + recycledNoncesKey({ address, chainId }), + inflightNoncesKey({ address, chainId }), + newValue.toString() + ), + mapRedisError + ).andThen((result) => { + const [confirmedStr, engineStr] = (result as string).split(":"); + const confirmedNonce = Number(confirmedStr); + const engineNonce = Number(engineStr); + + if (!Number.isFinite(confirmedNonce) || !Number.isFinite(engineNonce)) { + return errAsync({ + kind: "nonce_db_err", + code: "corruption_err", + } as NonceDbErr); + } + + return okAsync({ confirmedNonce, engineNonce }); + }); +} + +// Get/Set engine nonce +export function getEngineNonce( + address: Address, + chainId: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.get(engineNonceKey({ address, chainId })), + mapRedisError + ).map((value) => Number(value || 0)); +} + +export function incrementEngineNonce( + address: Address, + chainId: string +): ResultAsync { + return ResultAsync.fromPromise( + redis.incr(engineNonceKey({ address, chainId })), + mapRedisError + ); +} diff --git a/src/executors/execute/execute.ts b/src/executors/execute/execute.ts new file mode 100644 index 000000000..057c88ad0 --- /dev/null +++ b/src/executors/execute/execute.ts @@ -0,0 +1,639 @@ +import { randomUUID } from "node:crypto"; +import { LRUCache } from "lru-cache"; +import { errAsync, okAsync, ResultAsync, safeTry } from "neverthrow"; +import SuperJSON from "superjson"; +import { + type Address, + type Chain, + getAddress, + type Hex, + type ThirdwebClient, + ZERO_ADDRESS, +} from "thirdweb"; +import type { Account } from "thirdweb/wallets"; +import { db } from "../../db/connection.js"; +import { transactions } from "../../db/schema.js"; +import type { + ExecutionParamsSerialized, + TransactionParamsSerialized, +} from "../../db/types.js"; +import { getEngineAccount } from "../../lib/accounts/accounts.js"; +import { getChainResult } from "../../lib/chain.js"; +import { + type AccountErr, + buildTransactionDbEntryErr, + type EngineErr, + mapDbError, + type ValidationErr, +} from "../../lib/errors.js"; +import { + type ExecutionRequest as AsyncBundlerExecutionRequest, + execute as executeExternalBundlerAsync, +} from "../external-bundler-async/index.js"; +import type { EncodedExecutionRequest } from "../types.js"; +import "./external-bundler-confirm-handler.js"; +import "./external-bundler-send-handler.js"; +import { resolve as resolve_aa } from "../../executors/execute/resolution/aa.js"; + +import { isZkSyncChainResult } from "../../lib/result-wrapped/thirdweb-sdk.js"; +import { + type CreateRestrictedSignedTokenResult, + createRestrictedSignedToken, + isStoredToken, +} from "./vault-helper.js"; + +type AsyncBundlerExecutionRequestOptions = + AsyncBundlerExecutionRequest["executionOptions"]; + +// Define what we cache - the address info needed to create accounts +type CachedExecutionAccountInfo = + | { + type: "EOA"; + address: Address; + } + | { + type: "ERC4337"; + signerAddress: Address; + smartAccountAddress: Address; + factoryAddress: Address; + entrypointAddress: Address; + accountSalt: string | null; + } + | { + type: "zksync"; + accountAddress: Address; + }; + +// Create an LRU cache for the account resolution info +export const executionAccountCache = new LRUCache< + string, + CachedExecutionAccountInfo +>({ + max: 10_000, // Store up to 10_000 resolution results + ttl: 1000 * 60 * 60 * 24 * 7, // 7 day cache expiration +}); + +// Generate a comprehensive cache key that encodes all request parameters +function generateExecutionAccountCacheKey( + request: EncodedExecutionRequest +): string { + switch (request.executionOptions.type) { + case "auto": + return `auto_${request.executionOptions.from}:${request.executionOptions.chainId}`; + case "ERC4337": { + const options = request.executionOptions; + return [ + `type:${options.type}`, + `signer:${options.signerAddress}`, + `smartAddr:${ + "smartAccountAddress" in options + ? options.smartAccountAddress + : "unspecified" + }`, + `entrypoint:${options.entrypointAddress ?? "unspecified"}`, + `factory:${options.factoryAddress ?? "unspecified"}`, + `salt:${ + "accountSalt" in options ? options.accountSalt : "unspecified" + }`, + `chain:${options.chainId}`, + ].join("_"); + } + case "zksync": { + return `AA:zksync_${request.executionOptions.accountAddress}:${request.executionOptions.chainId}`; + } + case "eoa": { + return `eoa_${request.executionOptions.address}`; + } + } +} + +export type ExecutionCredentials = { + vaultAccessToken?: string; + + // thirdweb credentials + thirdwebSecretKey?: string; + thirdwebClientId?: string; + thirdwebServiceKey?: string; +}; + +type ResolvedExecutionAccount_AA = { + type: "ERC4337"; + signerAccount: Account; + smartAccountDetails: { + factoryAddress: Address; + entrypointAddress: Address; + address: Address; + } & { accountSalt: string | null | undefined }; +}; + +type ResolvedExecutionAccount_zksync = { + type: "zksync"; + zkEoaAccount: Account; +}; + +type ResolvedExecutionAccount_EOA = { + type: "EOA"; + account: Account; +}; + +type ResolvedExecutionAccount = + | ResolvedExecutionAccount_AA + | ResolvedExecutionAccount_zksync + | ResolvedExecutionAccount_EOA; + +/** + * Resolves the appropriate accounts needed for transaction execution from the provided request. + * This function handles multiple scenarios including vault authentication, smart account resolution, + * and account prediction with various degrees of provided information. + * + * @param request - The encoded execution request containing authentication and account details + * @param credentials - Credentials for authentication, including optional vault access token + * + * @returns A ResultAsync that resolves to either: + * - `{ signerAccount, smartAccountDetails }` for smart account transactions + * - `signerAccount`: The EOA account that will sign transactions + * - `smartAccountDetails`: Contains address, factory, entrypoint and optional salt + * - `{ account }` for direct EOA transactions + * - `{ zkEoaAccount }` for zkSync account transactions + * + * The function returns errors (not throws) in these cases: + * - AccountErr: When provided signerAddress is a smart account (not allowed as signer) + * - AccountErr: When a smart account address is an EOA (not allowed as smart account) + * - ValidationErr: When using zkSync execution on a non-zkSync chain + */ +export function getExecutionAccountFromRequest({ + client, + credentials, + request, +}: { + request: EncodedExecutionRequest; + credentials: ExecutionCredentials; + client: ThirdwebClient; +}): ResultAsync { + return safeTry(async function* () { + const cacheKey = generateExecutionAccountCacheKey(request); + const cachedInfo = executionAccountCache.get(cacheKey); + + // console.timeLog("execute", "cache fetched"); + + if (cachedInfo) { + // console.log("DEBUG CACHED", cachedInfo); + // console.timeLog("execute", "cache hit"); + + // Reconstruct the account objects from cached info + switch (cachedInfo.type) { + case "EOA": { + // Get the EOA account (light operation since we know it exists) + const engineAccountResult = yield* getEngineAccount({ + address: cachedInfo.address, + vaultAccessToken: credentials.vaultAccessToken, + }); + + if ("signerAccount" in engineAccountResult) { + return errAsync({ + kind: "account", + code: "account_not_found", + message: `Account not found: ${cachedInfo.address}. Provided signer address is a smart account. Smart account must not be used as a signer.`, + status: 400, + } as AccountErr); + } + + return okAsync({ + type: "EOA", + account: engineAccountResult.account, + } as ResolvedExecutionAccount); + } + + case "zksync": { + const engineAccountResult = yield* getEngineAccount({ + address: cachedInfo.accountAddress, + vaultAccessToken: credentials.vaultAccessToken, + }); + + if ("signerAccount" in engineAccountResult) { + // This should never happen with cached valid data + return errAsync({ + kind: "account", + code: "account_not_found", + message: `Account not found: ${cachedInfo.accountAddress}. Provided account address is an ERC4337 smart account. ERC4337 Smart Account cannot be used for zksync AA`, + status: 400, + } as AccountErr); + } + + return okAsync({ + type: "zksync", + zkEoaAccount: engineAccountResult.account, + } as ResolvedExecutionAccount); + } + + case "ERC4337": { + // For smart account, get the signer EOA + const signerAccount = yield* getEngineAccount({ + address: cachedInfo.signerAddress, + vaultAccessToken: credentials.vaultAccessToken, + }); + + if ("signerAccount" in signerAccount) { + // This should never happen with cached valid data + return errAsync({ + kind: "account", + code: "account_not_found", + message: `Invalid cached data: ${cachedInfo.signerAddress}. Signer address is a smart account.`, + status: 400, + } as AccountErr); + } + + // Return the reconstructed result + return okAsync({ + type: "ERC4337", + signerAccount: signerAccount.account, + smartAccountDetails: { + address: cachedInfo.smartAccountAddress, + factoryAddress: cachedInfo.factoryAddress, + entrypointAddress: cachedInfo.entrypointAddress, + accountSalt: cachedInfo.accountSalt, + }, + } as ResolvedExecutionAccount); + } + } + } + + // console.timeLog("execute", "cache miss, before full resolution"); + + // Not in cache, run the full resolution logic + const result = yield* getExecutionAccountFromRequest_uncached({ + request, + credentials, + client, + }); + + // console.timeLog("execute", "cache miss, after full resolution"); + + // console.log("DEBUG CACHE MISS", result); + + // Cache the resolution info for future use + switch (result.type) { + case "EOA": { + executionAccountCache.set(cacheKey, { + type: "EOA", + address: result.account.address as Address, + }); + break; + } + case "zksync": { + executionAccountCache.set(cacheKey, { + type: "zksync", + accountAddress: result.zkEoaAccount.address as Address, + }); + break; + } + case "ERC4337": { + executionAccountCache.set(cacheKey, { + type: "ERC4337", + signerAddress: result.signerAccount.address as Address, + smartAccountAddress: result.smartAccountDetails.address, + factoryAddress: result.smartAccountDetails.factoryAddress, + entrypointAddress: result.smartAccountDetails.entrypointAddress, + accountSalt: result.smartAccountDetails.accountSalt ?? null, + }); + break; + } + } + + return okAsync(result); + }); +} + +function getExecutionAccountFromRequest_uncached({ + request, + credentials, + client, +}: { + request: EncodedExecutionRequest; + credentials: ExecutionCredentials; + client: ThirdwebClient; +}): ResultAsync { + return safeTry(async function* () { + const chain = yield* getChainResult(request.executionOptions.chainId); + // in case of a vault access token credential, skip storage lookup because these accounts are never stored in the DB + const shouldSkipStorageLookup = !!credentials.vaultAccessToken; + + switch (request.executionOptions.type) { + case "auto": { + { + const engineAccountResponse = yield* getEngineAccount({ + address: request.executionOptions.from, + vaultAccessToken: credentials.vaultAccessToken, + }); + + if ("signerAccount" in engineAccountResponse) { + return okAsync({ + type: "ERC4337" as const, + signerAccount: engineAccountResponse.signerAccount, + smartAccountDetails: engineAccountResponse.smartAccountDetails, + }); + } + + const isZkChain = yield* isZkSyncChainResult(chain); + + if (isZkChain) { + return okAsync({ + type: "zksync" as const, + zkEoaAccount: engineAccountResponse.account, + }); + } + + const aaResolution = yield* resolve_aa({ + options: { + chainId: request.executionOptions.chainId, + signerAddress: engineAccountResponse.account.address as Address, + type: "ERC4337", + sponsorGas: true, + }, + chain, + credentials, + client, + skipStorageLookup: shouldSkipStorageLookup, + }); + + return okAsync({ + type: "ERC4337" as const, + signerAccount: engineAccountResponse.account, + smartAccountDetails: aaResolution.smartAccountDetails, + } as ResolvedExecutionAccount); + + // return okAsync({ + // type: "EOA" as const, + // account: engineAccountResponse.account, + // }); + } + } + case "ERC4337": { + { + const resolved = yield* resolve_aa({ + options: request.executionOptions, + chain, + credentials, + client, + skipStorageLookup: shouldSkipStorageLookup, + }); + + return okAsync({ + type: "ERC4337" as const, + ...resolved, + }); + } + } + case "zksync": { + const isThisZkSyncChain = yield* isZkSyncChainResult(chain); + if (!isThisZkSyncChain) { + return errAsync({ + kind: "validation", + code: "invalid_chain", + message: `Invalid chain ID: ${request.executionOptions.chainId}. AA:zksync execution is only supported on zkSync chains.`, + status: 400, + } satisfies ValidationErr as ValidationErr); + } + const engineAccountResponse = yield* getEngineAccount({ + address: request.executionOptions.accountAddress, + vaultAccessToken: credentials.vaultAccessToken, + }); + + // we expected to receive an eoa account but got a signer, which is invalid + if ("signerAccount" in engineAccountResponse) { + return errAsync({ + kind: "account", + code: "account_not_found", + message: + "Provided account address is an ERC4337 smart account. ERC4337 Smart Account cannot be used for zksync AA", + status: 400, + } as AccountErr); + } + + return okAsync({ + type: "zksync" as const, + zkEoaAccount: engineAccountResponse.account, + }); + } + case "eoa": { + const engineAccountResponse = yield* getEngineAccount({ + address: request.executionOptions.address, + vaultAccessToken: credentials.vaultAccessToken, + }); + + if ("account" in engineAccountResponse) { + return okAsync({ + type: "EOA" as const, + account: engineAccountResponse.account, + }); + } + + return errAsync({ + kind: "account", + code: "account_not_found", + message: + "Provided account address is an ERC4337 smart account. ERC4337 Smart Account cannot be used for EOA execution", + status: 400, + } as AccountErr); + } + } + }); +} + +export function execute({ + request, + credentials, + client, +}: { + request: EncodedExecutionRequest; + credentials: ExecutionCredentials; + client: ThirdwebClient; +}) { + return safeTry(async function* () { + // console.time("execute"); + const resolutionResponse = yield* getExecutionAccountFromRequest({ + client, + credentials, + request, + }); + + const chain = yield* getChainResult(request.executionOptions.chainId); + + // console.timeLog("execute", "getExecutionAccountFromRequest"); + + switch (resolutionResponse.type) { + case "EOA": { + return errAsync({ + kind: "account", + code: "account_not_found", + message: "EOA execution is not supported yet", + status: 500, + } as EngineErr); + } + case "ERC4337": { + return okAsync( + yield* executeAA({ + chain, + client, + credentials, + options: resolutionResponse, + request, + }) + ); + } + case "zksync": { + return errAsync({ + kind: "account", + code: "account_not_found", + message: "zksync AA execution is not supported yet", + status: 500, + } as EngineErr); + } + } + }); +} + +function executeAA({ + chain, + client, + credentials, + options, + request, +}: { + options: ResolvedExecutionAccount_AA; + request: EncodedExecutionRequest; + credentials: ExecutionCredentials; + chain: Chain; + client: ThirdwebClient; +}) { + return safeTry(async function* () { + const executionOptions = { + signer: options.signerAccount, + accountSalt: + "accountSalt" in options.smartAccountDetails + ? options.smartAccountDetails.accountSalt ?? undefined + : undefined, + accountFactoryAddress: options.smartAccountDetails.factoryAddress, + entrypointAddress: options.smartAccountDetails.entrypointAddress, + smartAccountAddress: options.smartAccountDetails.address, + sponsorGas: + "sponsorGas" in request.executionOptions + ? request.executionOptions.sponsorGas + : true, + }; + + const resolvedTransactionParams = request.params.map((tx) => ({ + value: tx.value ?? 0n, + data: tx.data ?? ("0x" as Hex), + to: tx.to ?? (ZERO_ADDRESS as Address), + })); + + const idempotencyKey = + request.executionOptions.idempotencyKey ?? randomUUID().toString(); + + let restrictedTokenInfo: CreateRestrictedSignedTokenResult | null = null; + + if ( + credentials.vaultAccessToken && + isStoredToken(credentials.vaultAccessToken) + ) { + // Convert stored token to restricted signed token with specific permissions + const restrictedTokenResult = yield* createRestrictedSignedToken({ + storedToken: credentials.vaultAccessToken, + chainId: request.executionOptions.chainId, + chain, // Pass the chain object directly + thirdwebClient: client, + entrypointAddress: executionOptions.entrypointAddress, + smartAccountAddress: executionOptions.smartAccountAddress, + transactionParams: resolvedTransactionParams, + }); + + // console.timeLog("execute", "after signed token"); + + restrictedTokenInfo = restrictedTokenResult; + } + + // Execute using the appropriate executor + // For async executor, we need to convert the execution options to the format it expects + const asyncExecutionOptions: AsyncBundlerExecutionRequestOptions = { + signerAddress: executionOptions.signer.address as Address, + entrypointAddress: executionOptions.entrypointAddress, + accountFactoryAddress: executionOptions.accountFactoryAddress, + sponsorGas: executionOptions.sponsorGas, + smartAccountAddress: executionOptions.smartAccountAddress, + accountSalt: executionOptions.accountSalt, + + thirdwebClientId: credentials.thirdwebClientId, + thirdwebServiceKey: credentials.thirdwebServiceKey, + }; + + // Add vault token and nonce data if available (from restricted token) + if (restrictedTokenInfo) { + asyncExecutionOptions.vaultAccessToken = restrictedTokenInfo.signedToken; + asyncExecutionOptions.preallocatedNonce = + restrictedTokenInfo.preallocatedNonce; + asyncExecutionOptions.nonceSeed = restrictedTokenInfo.nonceSeed; + } + + // console.timeLog("execute", "before calling async executor"); + + // Execute using the async executor + const asyncResult = await executeExternalBundlerAsync({ + id: idempotencyKey, + executionOptions: asyncExecutionOptions, + chainId: request.executionOptions.chainId, + transactionParams: resolvedTransactionParams, + }); + + // console.timeLog("execute", "after calling async executor"); + + // Handle errors from the async executor + if (asyncResult.isErr()) { + return errAsync(asyncResult.error); + } + + const executionParams: ExecutionParamsSerialized = { + type: "AA" as const, + entrypointAddress: options.smartAccountDetails.entrypointAddress, + smartAccountAddress: options.smartAccountDetails.address, + signerAddress: getAddress(options.signerAccount.address), + }; + + const dbTransactionEntry = yield* ResultAsync.fromPromise( + db + .insert(transactions) + .values({ + id: idempotencyKey, + batchIndex: 0, + chainId: request.executionOptions.chainId, + transactionParams: SuperJSON.serialize(resolvedTransactionParams) + .json as TransactionParamsSerialized[], + executionParams, + clientId: credentials.thirdwebClientId, + executionResult: { + status: "QUEUED", + }, + from: executionParams.smartAccountAddress as Address, + }) + .returning(), + mapDbError + ).mapErr((e) => + buildTransactionDbEntryErr({ + error: e, + executionParams, + executionResult: { + status: "QUEUED", + }, + }) + ); + // console.timeEnd("execute"); + + return okAsync({ + executionResult: { + status: "QUEUED", + }, + transactions: dbTransactionEntry, + executionOptions: options, + }); + }); +} diff --git a/src/executors/execute/external-bundler-confirm-handler.ts b/src/executors/execute/external-bundler-confirm-handler.ts new file mode 100644 index 000000000..802efde58 --- /dev/null +++ b/src/executors/execute/external-bundler-confirm-handler.ts @@ -0,0 +1,69 @@ +import SuperJSON from "superjson"; +import { db } from "../../db/connection.js"; +import { transactions } from "../../db/schema.js"; +import { registerCallback, type ConfirmationResult } from "../external-bundler"; +import { registerCallback as registerExternalBundlerAsyncConfirmCallback } from "../external-bundler-async"; +import type { + ExecutionResult4337Serialized, + RevertDataSerialized, +} from "../../db/types.js"; +import { and, eq } from "drizzle-orm"; +import { initializeLogger } from "../../lib/logger.js"; + +const confirmLogger = initializeLogger( + "executor:external-bundler:confirm-handler" +); + +// not using neverthrow here, this handler response doesn't go to the user +export async function externalBundlerConfirmHandler( + result: ConfirmationResult +) { + const executionResult: ExecutionResult4337Serialized = + result.onchainStatus === "REVERTED" + ? { + status: "CONFIRMED", + onchainStatus: "REVERTED", + revertData: result.revertData + ? (SuperJSON.serialize(result.revertData) + .json as unknown as RevertDataSerialized) + : undefined, + actualGasCost: result.actualGasCost.toString(), + actualGasUsed: result.actualGasUsed.toString(), + nonce: result.nonce.toString(), + userOpHash: result.userOpHash, + transactionHash: result.transactionHash, + } + : { + status: "CONFIRMED", + onchainStatus: "SUCCESS", + transactionHash: result.transactionHash, + actualGasCost: result.actualGasCost.toString(), + actualGasUsed: result.actualGasUsed.toString(), + nonce: result.nonce.toString(), + userOpHash: result.userOpHash, + }; + + try { + await db + .update(transactions) + .set({ + confirmedAt: new Date(), + transactionHash: result.transactionHash, + confirmedAtBlockNumber: result.blockNumber.toString(), + executionResult, + errorMessage: + result.onchainStatus === "REVERTED" + ? result.revertData?.errorName + : undefined, + }) + // 4337 transactions always create a single transaction in the db, with batchIndex 0 + .where( + and(eq(transactions.id, result.id), eq(transactions.batchIndex, 0)) + ); + } catch (err) { + confirmLogger.error("Failed to write confirmed transaction to DB", err); + } +} + +registerCallback(externalBundlerConfirmHandler); +registerExternalBundlerAsyncConfirmCallback(externalBundlerConfirmHandler); diff --git a/src/executors/execute/external-bundler-send-handler.ts b/src/executors/execute/external-bundler-send-handler.ts new file mode 100644 index 000000000..ccb041edf --- /dev/null +++ b/src/executors/execute/external-bundler-send-handler.ts @@ -0,0 +1,51 @@ +import type { Job } from "bullmq"; +import { and, eq } from "drizzle-orm"; +import { db } from "../../db/connection.js"; +import { transactions } from "../../db/schema.js"; +import { initializeLogger } from "../../lib/logger.js"; +import { type SendResult, sendWorker } from "../external-bundler-async"; + +const sendLogger = initializeLogger("executor:external-bundler:send-handler"); + +// This handler is called when a UserOp is sent by the async executor +// It updates the transaction record with the userOpHash +export async function externalBundlerSendHandler( + _job: Job, // Unused parameter but required by BullMQ + result: SendResult, +) { + const userOpHash = result.status === "QUEUED" ? result.userOpHash : undefined; + const executionResult = + result.status === "QUEUED" + ? ({ + status: "SUBMITTED", + monitoringStatus: "WILL_MONITOR", + userOpHash: result.userOpHash, + } as const) + : ({ + status: "FAILED", + error: result.error, + } as const); + try { + await db + .update(transactions) + .set({ + executionResult, + }) + // 4337 transactions always create a single transaction in the db, with batchIndex 0 + .where( + and(eq(transactions.id, result.id), eq(transactions.batchIndex, 0)), + ); + + sendLogger.info( + `Updated transaction ${result.id} with userOpHash ${userOpHash}`, + ); + } catch (err) { + sendLogger.error("Failed to update transaction with userOpHash", err, { + id: result.id, + userOpHash: userOpHash, + }); + } +} + +// Register the send handler with the async executor's send worker +sendWorker.on("completed", externalBundlerSendHandler); diff --git a/src/executors/execute/resolution/aa.ts b/src/executors/execute/resolution/aa.ts new file mode 100644 index 000000000..8b65396a4 --- /dev/null +++ b/src/executors/execute/resolution/aa.ts @@ -0,0 +1,189 @@ +import * as z from "zod"; +import type { aaExecutionOptionsSchema } from "../../types"; +import { errAsync, okAsync, safeTry } from "neverthrow"; +import { getEngineAccount } from "../../../lib/accounts/accounts"; +import type { AccountErr } from "../../../lib/errors"; +import { + DEFAULT_ACCOUNT_FACTORY_V0_7, + ENTRYPOINT_ADDRESS_v0_7, +} from "thirdweb/wallets/smart"; +import { + isHex, + stringToHex, + type Address, + type Chain, + type ThirdwebClient, +} from "thirdweb"; +import { + getContractResult, + predictAccountAddressResult, +} from "../../../lib/result-wrapped/thirdweb-sdk"; +import type { ExecutionCredentials } from "../execute"; + +type AAExecutionOptions = z.infer; + +function tryResolveSmartAccountDetailsFromStorage({ + signerAddress, + smartAccountAddress, +}: { + smartAccountAddress: Address; + signerAddress: Address; +}) { + return safeTry(async function* () { + // Try to find smart account in DB + const smartAccountResult = await getEngineAccount({ + address: smartAccountAddress, + signerAddress: signerAddress, + }); + + if (smartAccountResult.isErr()) { + // it's okay if the account was not found, but return any other received errors + if (smartAccountResult.error.code !== "account_not_found") { + return errAsync(smartAccountResult.error); + } + + // we tried to look in db but did not find a smart account registered to this EOA, return null + return okAsync(null); + } + + // let's make sure that we received a smart account and not and EOA + if ("account" in smartAccountResult.value) { + return errAsync({ + kind: "account", + code: "account_not_found", + message: `Account not found: ${smartAccountAddress}. Provided smart account address is an EOA. EOA must not be used as a smart account.`, + status: 400, + } as AccountErr); + } + // we found the smart account, let's use it + return okAsync({ + address: smartAccountResult.value.smartAccountDetails.address, + factoryAddress: + smartAccountResult.value.smartAccountDetails.factoryAddress, + entrypointAddress: + smartAccountResult.value.smartAccountDetails.entrypointAddress, + accountSalt: + smartAccountResult.value.smartAccountDetails.accountSalt ?? undefined, + }); + }); +} + +export function resolve({ + options, + chain, + credentials, + client, + skipStorageLookup, +}: { + options: AAExecutionOptions; + chain: Chain; + credentials: ExecutionCredentials; + client: ThirdwebClient; + skipStorageLookup?: boolean; +}) { + return safeTry(async function* () { + const engineSignerAccountResponse = yield* getEngineAccount({ + address: options.signerAddress, + vaultAccessToken: credentials.vaultAccessToken, + }); + + // we expected to receive an eoa account but got a signer, which is invalid + if ("signerAccount" in engineSignerAccountResponse) { + return errAsync({ + kind: "account", + code: "account_not_found", + message: `Account not found: ${options.signerAddress}. Provided signer address is a smart account. Smart account must not be used as a signer.`, + status: 400, + } as AccountErr); + } + + const signerAccount = engineSignerAccountResponse.account; + + // if only from is provided, we use it to fetch an account + // we either get only account, or a signer + smartAccount + + // if from was not provided, then we know signerAddress was provided + // but a smartAccountAddress may or may not be provided + // if smart account address was provided, there are two cases: + // + // 1. Smart Account is registered to this EOA in the DB. + // In which case we can fetch all data about the smart account + // + // 2. Smart Account is not registered to this EOA in the DB. + // In which case we need to rely on executionOptions to contain all data, + // and if not we defer to default values + + if ("smartAccountAddress" in options && options.smartAccountAddress) { + // the simplest case is if the request contains all the data we need: entrypointAddress, factoryAddress + if (options.entrypointAddress && options.factoryAddress) { + // good to go! let's just send provided execution options + return okAsync({ + signerAccount, + smartAccountDetails: { + address: options.smartAccountAddress, + factoryAddress: options.factoryAddress, + entrypointAddress: options.entrypointAddress, + accountSalt: undefined, + }, + }); + } + + // we don't have all values, so look in storage before falling back to defaults + const storedSmartAccountDetails = skipStorageLookup + ? null + : yield* tryResolveSmartAccountDetailsFromStorage({ + signerAddress: options.signerAddress, + smartAccountAddress: options.smartAccountAddress, + }); + + const resolvedSmartAccountDetails = storedSmartAccountDetails ?? { + accountSalt: undefined, + entrypointAddress: + options.entrypointAddress ?? (ENTRYPOINT_ADDRESS_v0_7 as Address), + address: options.smartAccountAddress, + factoryAddress: + options.factoryAddress ?? (DEFAULT_ACCOUNT_FACTORY_V0_7 as Address), + }; + + return okAsync({ + signerAccount, + smartAccountDetails: resolvedSmartAccountDetails, + }); + } + + // smart account address was not provided, but we have the signer eoa + // user has selected AA execution, so we use the provided factory and salt values, or assume defaults to get the execution options + const factoryAddress = + options.factoryAddress ?? (DEFAULT_ACCOUNT_FACTORY_V0_7 as Address); + + const accountSalt = options.accountSalt; + + const factoryContract = yield* getContractResult({ + address: factoryAddress, + chain, + client, + }); + + const saltHex = + accountSalt && isHex(accountSalt) + ? accountSalt + : stringToHex(accountSalt ?? ""); + + const predictedSmartAccountAddress = yield* predictAccountAddressResult({ + adminSigner: signerAccount.address as Address, + contract: factoryContract, + data: saltHex, + }); + + return okAsync({ + signerAccount, + smartAccountDetails: { + address: predictedSmartAccountAddress as Address, + factoryAddress, + entrypointAddress: + options.entrypointAddress ?? (ENTRYPOINT_ADDRESS_v0_7 as Address), + accountSalt: options.accountSalt, + }, + }); + }); +} diff --git a/src/executors/execute/vault-helper.ts b/src/executors/execute/vault-helper.ts new file mode 100644 index 000000000..dd1a5cc1f --- /dev/null +++ b/src/executors/execute/vault-helper.ts @@ -0,0 +1,320 @@ +// src/executor/external-bundler-async/vault-token-helper.ts + +import { + createSignedAccessToken, + SIGNED_TOKEN_PREFIX, + STORED_TOKEN_PREFIX, +} from "../../lib/vault-sdk/sdk.js"; +import { vaultClient } from "../../lib/vault-client.js"; +import { + getContract, + encode, + prepareContractCall, + type Address, + type Hex, + type ThirdwebClient, + type ThirdwebContract, + type Chain, + type PreparedTransaction, +} from "thirdweb"; +import { ResultAsync, errAsync, okAsync, safeTry } from "neverthrow"; +import type { + PolicyComponent, + Rule, + UserOperationV06Rules, + UserOperationV07Rules, +} from "../../lib/vault-sdk/types.js"; +import type { RpcErr, CryptoErr } from "../../lib/errors.js"; + +// Function to generate a random uint192 for nonce generation +export function generateRandomUint192(): bigint { + const rand1 = BigInt(Math.floor(Math.random() * 0x100000000)); + const rand2 = BigInt(Math.floor(Math.random() * 0x100000000)); + const rand3 = BigInt(Math.floor(Math.random() * 0x100000000)); + const rand4 = BigInt(Math.floor(Math.random() * 0x100000000)); + const rand5 = BigInt(Math.floor(Math.random() * 0x100000000)); + const rand6 = BigInt(Math.floor(Math.random() * 0x100000000)); + return ( + (rand1 << BigInt(160)) | + (rand2 << BigInt(128)) | + (rand3 << BigInt(96)) | + (rand4 << BigInt(64)) | + (rand5 << BigInt(32)) | + rand6 + ); +} + +// Interface for the function parameters +export interface CreateRestrictedSignedTokenParams { + storedToken: string; + chainId: string; + chain: Chain; // Pass the chain object directly + thirdwebClient: ThirdwebClient; + entrypointAddress: Address; + smartAccountAddress: Address; + transactionParams: { + to: Address; + data: Hex; + value?: bigint; + }[]; +} + +// Interface for the result +export interface CreateRestrictedSignedTokenResult { + signedToken: string; + preallocatedNonce: bigint; + nonceSeed: bigint; + encodedCalldata: Hex; +} + +// Helper to check if a token is a stored token +export function isStoredToken(token?: string): boolean { + return !!token && token.startsWith(STORED_TOKEN_PREFIX); +} + +// Helper to check if a token is a signed token +export function isSignedToken(token?: string): boolean { + return !!token && token.startsWith(SIGNED_TOKEN_PREFIX); +} + +// Function selectors for entrypoint contracts +// const FN_SELECTOR = "0x35567e1a" as const; // getNonce function selector +// const FN_INPUTS = [ +// { type: "address", name: "sender" }, +// { type: "uint192", name: "key" }, +// ] as const; +// const FN_OUTPUTS = [{ type: "uint256", name: "nonce" }] as const; + +// Helper function similar to prepareBatchExecute but adapted for our use case +function prepareBatchExecute(args: { + accountContract: ThirdwebContract; + transactions: { + to: Address; + data: Hex; + value?: bigint; + }[]; +}): PreparedTransaction { + return prepareContractCall({ + contract: args.accountContract, + method: "function executeBatch(address[], uint256[], bytes[])", + params: [ + args.transactions.map((tx) => tx.to), + args.transactions.map((tx) => tx.value || 0n), + args.transactions.map((tx) => tx.data), + ], + }); +} + +// Helper function to prepare a single execute transaction +function prepareExecute(args: { + accountContract: ThirdwebContract; + transaction: { + to: Address; + data: Hex; + value?: bigint; + }; +}): PreparedTransaction { + return prepareContractCall({ + contract: args.accountContract, + method: "function execute(address, uint256, bytes)", + params: [ + args.transaction.to, + args.transaction.value || 0n, + args.transaction.data, + ], + }); +} + +/** + * Helper function to encode transactions into the expected calldata format + * This matches how the SDK formats calldata for both single and batch transactions + */ +function encodeTransactionsAsync( + transactions: { to: Address; data: Hex; value?: bigint }[], + smartAccountAddress: Address, + chain: Chain, + client: ThirdwebClient, +): ResultAsync { + if (transactions.length === 0) { + return errAsync({ + kind: "rpc", + code: "encode_transaction_failed", + status: 400, + message: "No transactions provided to encode", + } as RpcErr); + } + + // Get the smart account contract + const accountContract = getContract({ + address: smartAccountAddress, + chain, + client, + }); + + // Use different encoding approaches based on number of transactions + let executeTx; + let firstTransaction = transactions[0]; + if (transactions.length === 1 && firstTransaction) { + // For single transaction + executeTx = prepareExecute({ + accountContract, + transaction: firstTransaction, + }); + } else { + // For multiple transactions + executeTx = prepareBatchExecute({ + accountContract, + transactions, + }); + } + + // Encode the transaction + return ResultAsync.fromPromise( + encode(executeTx), + (e) => + ({ + kind: "rpc", + code: "encode_transaction_failed", + status: 500, + message: + e instanceof Error ? e.message : "Failed to encode transaction", + source: e instanceof Error ? e : undefined, + }) as RpcErr, + ); +} + +/** + * Creates a restricted signed token from a stored token, limiting permissions to exactly one transaction + * with a specific nonce and calldata + */ +export function createRestrictedSignedToken({ + storedToken, + // chainId, + chain, + thirdwebClient, + // entrypointAddress, + smartAccountAddress, + transactionParams, +}: CreateRestrictedSignedTokenParams): ResultAsync< + CreateRestrictedSignedTokenResult, + RpcErr | CryptoErr +> { + return safeTry(async function* () { + // console.time("createRestrictedSignedToken"); + + // 1. Create contract instance (using the passed chain object) + // const entrypointContract = getContract({ + // address: entrypointAddress, + // chain, + // client: thirdwebClient, + // }); + + // 2. Generate random nonce key + // const nonceSeed = generateRandomUint192(); + + // // console.timeLog("createRestrictedSignedToken", "before allocating nonce"); + + // // 3. Get pre-allocated nonce + // const preallocatedNonce = yield* ResultAsync.fromPromise( + // readContract({ + // contract: entrypointContract, + // method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const, + // params: [smartAccountAddress, nonceSeed], + // }), + // (e) => + // ({ + // kind: "rpc", + // code: "read_contract_failed", + // status: 500, + // message: + // e instanceof Error + // ? e.message + // : "Failed to get pre-allocated nonce", + // source: e instanceof Error ? e : undefined, + // chainId, + // address: smartAccountAddress, + // }) as RpcErr, + // ); + + const nonceSeed = generateRandomUint192(); + const preallocatedNonce = nonceSeed << 64n; + + // console.timeLog( + // "createRestrictedSignedToken", + // "after allocating nonce, before encoding", + // ); + + // 4. Encode the transactions + const encodedCalldata = yield* encodeTransactionsAsync( + transactionParams, + smartAccountAddress, + chain, + thirdwebClient, + ); + + // console.timeLog( + // "createRestrictedSignedToken", + // "after encoding, before signing", + // ); + + // 5. Create rules for the policies + const nonceRule: Rule = { pattern: `^${preallocatedNonce}$` }; + const callDataRule: Rule = { pattern: `(?i)^${encodedCalldata}$` }; + + // 6. Create UserOp rules for both v0.6 and v0.7 + const userOpV06Rules: UserOperationV06Rules = { + nonce: nonceRule, + callData: callDataRule, + }; + + const userOpV07Rules: UserOperationV07Rules = { + nonce: nonceRule, + callData: callDataRule, + }; + + // 7. Create the policies + const additionalPolicies: PolicyComponent[] = [ + { + type: "eoa:signStructuredMessage", + structuredPatterns: { + useropV06: userOpV06Rules, + useropV07: userOpV07Rules, + }, + }, + ]; + + // 8. Create the signed token with specific policies (24 hour expiry) + const expiryTimestamp = Math.floor(Date.now() / 1000) + 60 * 60 * 24; + + const signedToken = yield* ResultAsync.fromPromise( + createSignedAccessToken({ + vaultClient, + baseAccessToken: storedToken, + additionalPolicies, + expiryTimestamp, + }), + (e) => + ({ + kind: "crypto", + code: "encryption_failed", + status: 500, + message: + e instanceof Error + ? e.message + : "Failed to create signed access token", + source: e instanceof Error ? e : undefined, + }) as CryptoErr, + ); + + // console.timeLog("createRestrictedSignedToken", "after signing"); + // console.timeEnd("createRestrictedSignedToken"); + + // Return the final result + return okAsync({ + signedToken, + preallocatedNonce, + nonceSeed, + encodedCalldata, + }); + }); +} diff --git a/src/executors/external-bundler-async/index.ts b/src/executors/external-bundler-async/index.ts new file mode 100644 index 000000000..d24f5e9b0 --- /dev/null +++ b/src/executors/external-bundler-async/index.ts @@ -0,0 +1,708 @@ +// notes +import { DelayedError, Queue, UnrecoverableError, Worker } from "bullmq"; +import { errAsync, okAsync, ResultAsync } from "neverthrow"; +import SuperJSON, { type SuperJSONResult } from "superjson"; +import { + type AbiParameterToPrimitiveType, + type Address, + type Hex, + parseEventLogs, + prepareEvent, + type ThirdwebClient, +} from "thirdweb"; +import { userOperationRevertReasonEvent } from "thirdweb/extensions/erc4337"; +import { isContractDeployed } from "thirdweb/utils"; +import { + bundleUserOp, + createAndSignUserOp, + getUserOpReceiptRaw, +} from "thirdweb/wallets/smart"; +import { decodeErrorResult } from "viem"; +import { getEngineAccount } from "../../lib/accounts/accounts.js"; +import { getChain } from "../../lib/chain.js"; +import { env } from "../../lib/env.js"; +import { + accountActionErrorMapper, + prettyPrintError, + type RpcErr, +} from "../../lib/errors.js"; +import { initializeLogger } from "../../lib/logger.js"; +import { redis } from "../../lib/redis.js"; +import { getThirdwebClient } from "../../lib/thirdweb-client.js"; +import { + clearAccountDeploying, + isAccountDeploying, + setAccountDeploying, +} from "./state.js"; + +// todo: export these from SDK +export type PostOpRevertReasonEventFilters = Partial<{ + userOpHash: AbiParameterToPrimitiveType<{ + type: "bytes32"; + name: "userOpHash"; + indexed: true; + }>; + sender: AbiParameterToPrimitiveType<{ + type: "address"; + name: "sender"; + indexed: true; + }>; +}>; + +function postOpRevertReasonEvent(filters: PostOpRevertReasonEventFilters = {}) { + return prepareEvent({ + signature: + "event PostOpRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason)", + filters, + }); +} + +const sendLogger = initializeLogger("executor:external-bundler-async:send"); + +const confirmLogger = initializeLogger( + "executor:external-bundler-async:confirm", +); + +export type ExecutionRequest = { + id: string; + executionOptions: { + signerAddress: Address; + entrypointAddress: Address; + accountFactoryAddress: Address; + sponsorGas: boolean; + smartAccountAddress: Address; + accountSalt: string | undefined; + + // vault-specific fields + vaultAccessToken?: string; + preallocatedNonce?: bigint; + nonceSeed?: bigint; + + //thirdweb credentials + thirdwebClientId: string | undefined; + thirdwebServiceKey: string | undefined; + }; + chainId: string; + transactionParams: { + to: Address; + data: Hex; + value?: bigint; + }[]; +}; + +type SendResultBase = { + id: string; + chainId: string; + accountAddress: Address; +}; + +type SendResultQueued = SendResultBase & { + status: "QUEUED"; + userOpHash: Hex; +}; + +type SendResultFailed = SendResultBase & { + status: "FAILED"; + error: string; +}; + +export type SendResult = SendResultQueued | SendResultFailed; + +export type ConfirmationResult = { + id: string; + userOpHash: Hex; + transactionHash: Hex; + actualGasCost: bigint; + actualGasUsed: bigint; + nonce: bigint; + blockNumber: bigint; +} & ( + | { + onchainStatus: "SUCCESS"; + } + | { + onchainStatus: "REVERTED"; + revertData?: { + errorName: string; + errorArgs: Record; + }; + } +); + +const callbacks: ((result: ConfirmationResult) => void)[] = []; + +export function registerCallback( + callback: (result: ConfirmationResult) => void, +) { + confirmLogger.info(`Registered callback ${callback.name}`); + callbacks.push(callback); +} + +export type QueueingErr = { + kind: "queue"; + code: + | "external_bundler:queuing_confirm_job_failed" + | "external_bundler:queuing_send_job_failed"; + executionOptions: ExecutionRequest["executionOptions"]; + userOpHash: Hex; + source: Error; + status: 500; + message?: string; +}; + +export const EXTERNAL_BUNDLER_SEND_QUEUE_NAME = + "executor_external-bundler-async_send"; +export const EXTERNAL_BUNDLER_CONFIRM_QUEUE_NAME = + "executor_external-bundler-async_confirm"; + +export const externalBundlerSendQueue = new Queue( + EXTERNAL_BUNDLER_SEND_QUEUE_NAME, + { + defaultJobOptions: { + attempts: 60, + backoff: { + type: "custom", + }, + }, + connection: redis, + }, +); + +await externalBundlerSendQueue.setGlobalConcurrency( + env.SEND_TRANSACTION_QUEUE_CONCURRENCY, +); + +type ConfirmJobData = SendResultQueued & { + thirdwebClientId: string; + thirdwebServiceKey: string; +}; + +export const externalBundlerConfirmQueue = new Queue( + EXTERNAL_BUNDLER_CONFIRM_QUEUE_NAME, + { + defaultJobOptions: { + attempts: 100, + backoff: { + type: "custom", + }, + }, + connection: redis, + }, +); + +await externalBundlerConfirmQueue.setGlobalConcurrency( + env.CONFIRM_TRANSACTION_QUEUE_CONCURRENCY, +); + +export function execute(request: ExecutionRequest) { + const { executionOptions, id } = request; + + return ResultAsync.fromPromise( + externalBundlerSendQueue.add( + id, + SuperJSON.serialize(request) as unknown as ExecutionRequest, + ), + (err) => + ({ + kind: "queue", + code: "external_bundler:queuing_send_job_failed", + source: err, + executionOptions, + }) as QueueingErr, + ); +} + +export const sendWorker = new Worker( + EXTERNAL_BUNDLER_SEND_QUEUE_NAME, + async (job): Promise => { + const parsedData = SuperJSON.deserialize( + job.data as unknown as SuperJSONResult, + ) as ExecutionRequest; + const { executionOptions, id, chainId, transactionParams } = parsedData; + + let thirdwebClient: ThirdwebClient; + + if ( + executionOptions.thirdwebClientId && + executionOptions.thirdwebServiceKey + ) { + thirdwebClient = getThirdwebClient({ + clientId: executionOptions.thirdwebClientId, + serviceKey: executionOptions.thirdwebServiceKey, + }); + } else { + // throw new UnrecoverableError( + // "No thirdweb credentials provided, unable to send transaction", + // ); + return { + id, + chainId, + accountAddress: executionOptions.smartAccountAddress, + status: "FAILED", + error: + "Did not receive thirdweb credentials, unable to send transaction", + }; + } + + const chain = getChain(Number(chainId)); + + const account = await getEngineAccount({ + address: executionOptions.signerAddress, + vaultAccessToken: executionOptions.vaultAccessToken, + }); + + if (account.isErr()) { + // throw new UnrecoverableError("Failed to get engine account"); + return { + id, + chainId, + accountAddress: executionOptions.smartAccountAddress, + status: "FAILED", + error: "Failed to get engine account", + }; + } + + if ("signerAccount" in account.value) { + return { + id, + chainId, + accountAddress: executionOptions.smartAccountAddress, + status: "FAILED", + error: + "Failed to get admin EOA account to smart account, received smart account", + }; + // throw new UnrecoverableError( + // "Failed to get admin EOA account, received smart account", + // ); + } + + const signerAccount = account.value.account; + + // check if account is deployed + const isDeployed = await isContractDeployed({ + address: executionOptions.smartAccountAddress, + chain, + client: thirdwebClient, + }); + + sendLogger.info( + `Account ${executionOptions.smartAccountAddress} is deployed: ${isDeployed}`, + ); + + if (!isDeployed) { + // check if account is deploying + const isDeployingResult = await isAccountDeploying( + executionOptions.smartAccountAddress, + chainId, + ); + + if (isDeployingResult.isErr()) { + throw new Error( + "Unable to check if account is deploying redis error, will retry", + ); + } + + if (isDeployingResult.value) { + // delay so it retries + sendLogger.info( + `Account is deploying at ${isDeployingResult.value}, will retry`, + ); + await job.moveToDelayed(Date.now() + 5000, job.token); + throw new DelayedError( + `Account is deploying at ${isDeployingResult.value}, will retry`, + ); + } + } + + // redclaring a top level variable, because typescript does not automatically narrow in on preallocatedNonce being non-undefined if it's an object field + const preallocatedNonce = executionOptions.preallocatedNonce; + + const signedUserOp = await ResultAsync.fromPromise( + createAndSignUserOp({ + adminAccount: signerAccount, + client: thirdwebClient, + waitForDeployment: false, + isDeployedOverride: isDeployed, + smartWalletOptions: { + // if we don't provide a factory address, SDK uses thirdweb's default account factory + // user might be using a custom factory, and they might not provide one, so executor entrypoint should try to infer it + factoryAddress: executionOptions.accountFactoryAddress, + chain: chain, + sponsorGas: executionOptions.sponsorGas, + overrides: { + accountSalt: executionOptions.accountSalt, + accountAddress: executionOptions.smartAccountAddress, + entrypointAddress: executionOptions.entrypointAddress, + getAccountNonce: preallocatedNonce + ? async () => preallocatedNonce + : undefined, + }, + }, + transactions: transactionParams.map((tx) => ({ + to: tx.to, + data: tx.data, + value: tx.value, + chain: chain, + client: thirdwebClient, + })), + }), + accountActionErrorMapper({ + code: "sign_userop_failed", + }), + ); + + if (signedUserOp.isErr()) { + sendLogger.error( + "Failed to sign user operation, will retry", + signedUserOp.error, + signedUserOp.error.source, + { + chainId, + id, + }, + ); + if (signedUserOp.error.kind === "validation") { + return { + id, + chainId, + accountAddress: executionOptions.smartAccountAddress, + status: "FAILED", + error: signedUserOp.error.message ?? "Unknown error", + }; + } + job.log( + `Error while signing user operation. ${prettyPrintError(signedUserOp.error.source)}`, + ); + throw new Error("Failed to sign user operation, will retry"); + } + + const userOpHash = await ResultAsync.fromPromise( + bundleUserOp({ + userOp: signedUserOp.value, + options: { + chain: chain, + client: thirdwebClient, + entrypointAddress: executionOptions.entrypointAddress, + }, + }), + accountActionErrorMapper({ + code: "bundle_userop_failed", + }), + ); + + if (userOpHash.isErr()) { + job.log( + `[${new Date().toISOString()}] Failed to bundle user operation, will retry, error: ${SuperJSON.stringify( + userOpHash.error, + )}`, + ); + sendLogger.error( + "Failed to bundle user operation, will retry", + userOpHash.error, + { + chainId, + id, + }, + ); + throw new Error("Failed to bundle user operation, will retry"); + } + + const confirmJobResult = await ResultAsync.fromPromise( + externalBundlerConfirmQueue.add( + userOpHash.value, + { + status: "QUEUED", + userOpHash: userOpHash.value, + chainId: chain.id.toString(), + accountAddress: executionOptions.smartAccountAddress, + id: id, + + // thirdweb credentials + thirdwebClientId: executionOptions.thirdwebClientId, + thirdwebServiceKey: executionOptions.thirdwebServiceKey, + }, + { + jobId: id, + }, + ), + (err) => + ({ + code: "external_bundler:queuing_confirm_job_failed", + kind: "queue", + executionOptions, + source: err, + userOpHash: userOpHash.value, + }) as QueueingErr, + ); + + if (confirmJobResult.isErr()) { + throw new UnrecoverableError("Failed to queue confirm job"); + } + + if (!isDeployed) { + await setAccountDeploying( + executionOptions.smartAccountAddress, + chainId, + id, + ); + } + + return { + id: id, + accountAddress: executionOptions.smartAccountAddress, + chainId: chain.id.toString(), + userOpHash: userOpHash.value, + status: "QUEUED", + }; + }, + { + connection: redis, + concurrency: env.SEND_TRANSACTION_WORKER_CONCURRENCY, + settings: { + backoffStrategy: (attemptsMade: number) => { + if (attemptsMade === 1) return 2000; // First check after 2s + if (attemptsMade <= 11) return 10000; // Every 10s for first ~2min + if (attemptsMade <= 23) return 30000; // Every 30s until ~5min mark + return 60000; // Every 1min thereafter + }, + }, + }, +); + +type ConfirmationError = { + transactionHash: Hex; + actualGasCost: bigint; + actualGasUsed: bigint; + nonce: bigint; + blockNumber: bigint; + revertData?: { + errorName: string; + errorArgs: Record; + }; +}; + +function isConfirmationError(err: unknown): err is ConfirmationError { + return typeof err === "object" && err !== null && "transactionHash" in err; +} + +export function confirm(options: ConfirmJobData) { + const chain = getChain(Number(options.chainId)); + + let thirdwebClient: ThirdwebClient; + + if (options.thirdwebClientId && options.thirdwebServiceKey) { + thirdwebClient = getThirdwebClient({ + clientId: options.thirdwebClientId, + serviceKey: options.thirdwebServiceKey, + }); + } else { + throw new UnrecoverableError( + "No thirdweb credentials provided, unable to send transaction", + ); + } + + return ResultAsync.fromPromise( + getUserOpReceiptRaw({ + userOpHash: options.userOpHash, + chain, + client: thirdwebClient, + }), + (e) => + ({ + kind: "rpc", + code: "get_userop_receipt_failed", + status: 500, + message: + e instanceof Error + ? e.message + : "Failed to get user operation receipt in EXTERNAL_BUNDLER:CONFIRM", + source: e, + }) as RpcErr, + ).andThen((res) => { + if (!res) { + return okAsync(undefined); + } + const extractedReceipt = { + transactionHash: res.receipt.transactionHash, + actualGasCost: res.actualGasCost, + actualGasUsed: res.actualGasUsed, + nonce: res.nonce, + blockNumber: res.receipt.blockNumber, + }; + + if (res.success === false) { + // this was a revert, let's parse the events + const logs = parseEventLogs({ + events: [userOperationRevertReasonEvent(), postOpRevertReasonEvent()], + logs: res.logs, + }); + + const revertReason = logs[0]?.args.revertReason; + + const fallbackError = errAsync({ + ...extractedReceipt, + } as ConfirmationError); + + if (!revertReason) { + return fallbackError; + } + + // let's try to decode the revert reason + try { + const { abiItem, args, errorName } = decodeErrorResult({ + data: revertReason, + }); + + if (!args || args.length === 0) { + return fallbackError; + } + + const namedArgs: Record = + "inputs" in abiItem && abiItem.inputs.length === args.length + ? Object.fromEntries( + abiItem.inputs.map((input, i) => [input.name, args[i]]), + ) + : Object.fromEntries(args.map((arg, i) => [`arg${i}`, arg])); + + return errAsync({ + ...extractedReceipt, + revertData: { + errorName: errorName, + errorArgs: namedArgs, + }, + } as ConfirmationError); + } catch {} + + return fallbackError; + } + return okAsync({ + onchainStatus: "success", + ...extractedReceipt, + }); + }); +} + +export const confirmWorker = new Worker( + EXTERNAL_BUNDLER_CONFIRM_QUEUE_NAME, + async (job): Promise => { + const { + status, + userOpHash, + chainId, + id, + accountAddress, + thirdwebClientId, + thirdwebServiceKey, + } = job.data; + + const result = await confirm({ + status, + userOpHash, + chainId, + id, + accountAddress, + thirdwebClientId, + thirdwebServiceKey, + }); + + if (result.isErr()) { + if (isConfirmationError(result.error)) { + const res = { + onchainStatus: "REVERTED", + userOpHash: job.data.userOpHash, + id, + ...result.error, + } satisfies ConfirmationResult; + + await clearAccountDeploying(accountAddress, chainId); + + for (const cb of callbacks) { + cb(res); + } + + return res; + } + // not a revert, but an unexpected RPC error + confirmLogger.error("Failed to confirm user operation", result.error, { + chainId, + userOpHash, + }); + + job.log( + `[${new Date().toISOString()}] Unexpected RPC error confirming user operation`, + ); + + throw new Error("Failed to confirm user operation"); + } + if (!result.value) { + job.log( + `[${new Date().toISOString()}] Did not get receipt yet. Will retry`, + ); + + if (job.attemptsMade === 60) { + job.log( + `[${new Date().toISOString()}] Unable to confirm user operation after 60 attempts. Will not retry.`, + ); + + confirmLogger.error( + "Failed to confirm user operation after 60 attempts", + { + chainId, + userOpHash, + }, + ); + } + throw new Error("Failed to confirm user operation"); + } + + job.log( + `[${new Date().toISOString()}] Confirmed user operation with transaction hash ${ + result.value.transactionHash + }`, + ); + + const res = { + ...result.value, + onchainStatus: "SUCCESS", + userOpHash: job.data.userOpHash, + blockNumber: result.value.blockNumber, + id, + } satisfies ConfirmationResult; + + for (const cb of callbacks) { + cb(res); + } + + await clearAccountDeploying(accountAddress, chainId); + return SuperJSON.serialize(res).json as unknown as ConfirmationResult; + }, + { + connection: redis, + concurrency: env.CONFIRM_TRANSACTION_WORKER_CONCURRENCY, + maxStalledCount: 10, // some tolerance for stalling, there's no penalty on the confirmation worker + settings: { + backoffStrategy: (attemptsMade: number) => { + if (attemptsMade === 1) return 2000; // First check after 2s + if (attemptsMade <= 11) return 10000; // Every 10s for first ~2min + if (attemptsMade <= 23) return 30000; // Every 30s until ~5min mark + return 60000; // Every 1min thereafter + }, + }, + }, +); + +confirmWorker.on("ready", () => { + confirmLogger.info("worker ready"); +}); + +confirmWorker.on("failed", async (job) => { + if (!job) { + return; + } + + const wasFinalAttempt = job.opts.attempts === job.attemptsMade; + + if (wasFinalAttempt) { + await clearAccountDeploying(job.data.accountAddress, job.data.chainId); + } +}); diff --git a/src/executors/external-bundler-async/state.ts b/src/executors/external-bundler-async/state.ts new file mode 100644 index 000000000..b34f77c5d --- /dev/null +++ b/src/executors/external-bundler-async/state.ts @@ -0,0 +1,44 @@ +import type { Address } from "thirdweb"; +import { redis } from "../../lib/redis.js"; +import { ResultAsync } from "neverthrow"; + +const accountDeployingKey = (address: Address, chainId: string) => + `account-deploying:${address}:${chainId}`; + +type RedisErr = { + kind: "redis"; + code: "unknown_redis_err"; + source?: Error; +}; + +export function setAccountDeploying( + address: Address, + chainId: string, + transactionId: string +) { + return ResultAsync.fromPromise( + redis.set(accountDeployingKey(address, chainId), transactionId), + (err) => + ({ + kind: "redis", + code: "unknown_redis_err", + source: err, + } as RedisErr) + ); +} + +export function isAccountDeploying(address: Address, chainId: string) { + return ResultAsync.fromPromise( + redis.get(accountDeployingKey(address, chainId)), + (err) => + ({ kind: "redis", code: "unknown_redis_err", source: err } as RedisErr) + ); +} + +export function clearAccountDeploying(address: Address, chainId: string) { + return ResultAsync.fromPromise( + redis.del(accountDeployingKey(address, chainId)), + (err) => + ({ kind: "redis", code: "unknown_redis_err", source: err } as RedisErr) + ); +} diff --git a/src/executors/external-bundler/index.ts b/src/executors/external-bundler/index.ts new file mode 100644 index 000000000..808492a51 --- /dev/null +++ b/src/executors/external-bundler/index.ts @@ -0,0 +1,403 @@ +// notes +import { Queue, Worker } from "bullmq"; +import { errAsync, okAsync, ResultAsync } from "neverthrow"; +import { + parseEventLogs, + prepareEvent, + type AbiParameterToPrimitiveType, + type Address, + type Chain, + type Hex, + type ThirdwebClient, +} from "thirdweb"; +import type { Account } from "thirdweb/wallets"; +import { + bundleUserOp, + createAndSignUserOp, + getUserOpReceiptRaw, +} from "thirdweb/wallets/smart"; +import { accountActionErrorMapper, type RpcErr } from "../../lib/errors.js"; +import { getChain } from "../../lib/chain.js"; +import { thirdwebClient } from "../../lib/thirdweb-client.js"; +import { redis } from "../../lib/redis.js"; +import { initializeLogger } from "../../lib/logger.js"; + +import { userOperationRevertReasonEvent } from "thirdweb/extensions/erc4337"; +import { decodeErrorResult } from "viem"; +import SuperJSON from "superjson"; + +// todo: export these from SDK +export type PostOpRevertReasonEventFilters = Partial<{ + userOpHash: AbiParameterToPrimitiveType<{ + type: "bytes32"; + name: "userOpHash"; + indexed: true; + }>; + sender: AbiParameterToPrimitiveType<{ + type: "address"; + name: "sender"; + indexed: true; + }>; +}>; + +function postOpRevertReasonEvent(filters: PostOpRevertReasonEventFilters = {}) { + return prepareEvent({ + signature: + "event PostOpRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason)", + filters, + }); +} + +const confirmLogger = initializeLogger("executor:external-bundler:confirm"); + +type ExecutionRequest = { + id: string; + executionOptions: { + signer: Account; + entrypointAddress: Address; + accountFactoryAddress: Address; + sponsorGas: boolean; + smartAccountAddress: Address; + accountSalt: string | undefined; + }; + chain: Chain; + transactionParams: { + to: Address; + data: Hex; + value?: bigint; + }[]; + client: ThirdwebClient; +}; + +type ExecutionResult = { + id: string; + userOpHash: Hex; + chainId: string; +}; + +export type ConfirmationResult = { + id: string; + userOpHash: Hex; + transactionHash: Hex; + actualGasCost: bigint; + actualGasUsed: bigint; + nonce: bigint; + blockNumber: bigint; +} & ( + | { + onchainStatus: "SUCCESS"; + } + | { + onchainStatus: "REVERTED"; + revertData?: { + errorName: string; + errorArgs: Record; + }; + } +); + +const callbacks: ((result: ConfirmationResult) => void)[] = []; + +export function registerCallback( + callback: (result: ConfirmationResult) => void, +) { + confirmLogger.info(`Registered callback ${callback.name}`); + callbacks.push(callback); +} + +export type QueueingErr = { + kind: "queue"; + code: + | "external_bundler:queuing_confirm_job_failed" + | "external_bundler:queuing_send_job_failed"; + executionOptions: ExecutionRequest["executionOptions"]; + userOpHash: Hex; + source: Error; +}; + +export const EXTERNAL_BUNDLER_SEND_QUEUE_NAME = + "executor_external-bundler_send"; +export const EXTERNAL_BUNDLER_CONFIRM_QUEUE_NAME = + "executor_external-bundler_confirm"; + +export const externalBundlerConfirmQueue = new Queue( + EXTERNAL_BUNDLER_CONFIRM_QUEUE_NAME, + { + defaultJobOptions: { + attempts: 60, + backoff: { + type: "custom", + }, + }, + connection: redis, + }, +); + +export function execute(request: ExecutionRequest) { + const { executionOptions, transactionParams, client, chain } = request; + + return ResultAsync.fromPromise( + createAndSignUserOp({ + adminAccount: executionOptions.signer, + client, + waitForDeployment: false, + smartWalletOptions: { + // if we don't provide a factory address, SDK uses thirdweb's default account factory + // user might be using a custom factory, and they might not provide one, so executor entrypoint should try to infer it + factoryAddress: executionOptions.accountFactoryAddress, + chain: chain, + sponsorGas: executionOptions.sponsorGas, + overrides: { + accountSalt: executionOptions.accountSalt, + accountAddress: executionOptions.smartAccountAddress, + entrypointAddress: executionOptions.entrypointAddress, + }, + }, + transactions: transactionParams.map((tx) => ({ + to: tx.to, + data: tx.data, + value: tx.value, + chain: chain, + client: client, + })), + }), + accountActionErrorMapper({ + code: "sign_userop_failed", + }), + ) + .andThen((signedUserOp) => + ResultAsync.fromPromise( + bundleUserOp({ + userOp: signedUserOp, + options: { + chain: chain, + client: client, + entrypointAddress: executionOptions.entrypointAddress, + }, + }), + accountActionErrorMapper({ + code: "bundle_userop_failed", + }), + ), + ) + .andThen((userOpHash) => + ResultAsync.fromPromise( + externalBundlerConfirmQueue.add( + userOpHash, + { + userOpHash, + chainId: chain.id.toString(), + id: request.id, + }, + { + jobId: request.id, + }, + ), + (err) => + ({ + code: "external_bundler:queuing_confirm_job_failed", + kind: "queue", + executionOptions, + source: err, + userOpHash, + }) as QueueingErr, + ), + ); +} + +type ConfirmationError = { + transactionHash: Hex; + actualGasCost: bigint; + actualGasUsed: bigint; + nonce: bigint; + blockNumber: bigint; + revertData?: { + errorName: string; + errorArgs: Record; + }; +}; + +function isConfirmationError(err: unknown): err is ConfirmationError { + return typeof err === "object" && err !== null && "transactionHash" in err; +} + +export function confirm(options: ExecutionResult) { + const chain = getChain(Number(options.chainId)); + return ResultAsync.fromPromise( + getUserOpReceiptRaw({ + userOpHash: options.userOpHash, + chain, + client: thirdwebClient, + }), + (e) => + ({ + kind: "rpc", + code: "get_userop_receipt_failed", + status: 500, + message: + e instanceof Error + ? e.message + : "Failed to get user operation receipt in EXTERNAL_BUNDLER:CONFIRM", + source: e, + }) as RpcErr, + ) + + .andThen((res) => { + if (!res) { + return okAsync(undefined); + } + + const extractedReceipt = { + transactionHash: res.receipt.transactionHash, + actualGasCost: res.actualGasCost, + actualGasUsed: res.actualGasUsed, + nonce: res.nonce, + blockNumber: res.receipt.blockNumber, + }; + + if (res.success === false) { + // this was a revert, let's parse the events + const logs = parseEventLogs({ + events: [userOperationRevertReasonEvent(), postOpRevertReasonEvent()], + logs: res.logs, + }); + + const revertReason = logs[0]?.args.revertReason; + + const fallbackError = errAsync({ + ...extractedReceipt, + } as ConfirmationError); + + if (!revertReason) { + return fallbackError; + } + + // let's try to decode the revert reason + try { + const { abiItem, args, errorName } = decodeErrorResult({ + data: revertReason, + }); + + if (!args || args.length === 0) { + return fallbackError; + } + + const namedArgs: Record = + "inputs" in abiItem && abiItem.inputs.length === args.length + ? Object.fromEntries( + abiItem.inputs.map((input, i) => [input.name, args[i]]), + ) + : Object.fromEntries(args.map((arg, i) => [`arg${i}`, arg])); + + return errAsync({ + ...extractedReceipt, + revertData: { + errorName: errorName, + errorArgs: namedArgs, + }, + } as ConfirmationError); + } catch {} + + return fallbackError; + } + return okAsync({ + onchainStatus: "success", + ...extractedReceipt, + }); + }); +} + +export const confirmWorker = new Worker( + EXTERNAL_BUNDLER_CONFIRM_QUEUE_NAME, + async (job): Promise => { + const { userOpHash, chainId, id } = job.data; + const result = await confirm({ userOpHash, chainId, id }); + + if (result.isErr()) { + if (isConfirmationError(result.error)) { + const res = { + onchainStatus: "REVERTED", + userOpHash: job.data.userOpHash, + id, + ...result.error, + } satisfies ConfirmationResult; + + for (const cb of callbacks) { + cb(res); + } + + return res; + } + // not a revert, but an unexpected RPC error + confirmLogger.error("Failed to confirm user operation", result.error, { + chainId, + userOpHash, + }); + + job.log( + `[${new Date().toISOString()}] Unexpected RPC error confirming user operation`, + ); + + throw new Error("Failed to confirm user operation"); + } + if (!result.value) { + job.log( + `[${new Date().toISOString()}] Did not get receipt yet. Will retry`, + ); + + if (job.attemptsMade === 60) { + job.log( + `[${new Date().toISOString()}] Unable to confirm user operation after 60 attempts. Will not retry.`, + ); + + confirmLogger.error( + "Failed to confirm user operation after 60 attempts", + { + chainId, + userOpHash, + }, + ); + } + throw new Error("Failed to confirm user operation"); + } + + job.log( + `[${new Date().toISOString()}] Confirmed user operation with transaction hash ${ + result.value.transactionHash + }`, + ); + + const res = { + ...result.value, + onchainStatus: "SUCCESS", + userOpHash: job.data.userOpHash, + blockNumber: result.value.blockNumber, + id, + } satisfies ConfirmationResult; + + for (const cb of callbacks) { + cb(res); + } + + return SuperJSON.serialize(res).json as unknown as ConfirmationResult; + }, + { + connection: redis, + settings: { + backoffStrategy: (attemptsMade: number) => { + if (attemptsMade === 1) return 2000; // First check after 2s + if (attemptsMade <= 11) return 10000; // Every 10s for first ~2min + if (attemptsMade <= 23) return 30000; // Every 30s until ~5min mark + return 60000; // Every 1min thereafter + }, + }, + }, +); + +confirmWorker.on("ready", () => { + confirmLogger.info("worker ready"); +}); + +confirmWorker.on("error", (err) => { + confirmLogger.error("worker error", err); +}); diff --git a/src/executors/test/add-jobs.ts b/src/executors/test/add-jobs.ts new file mode 100644 index 000000000..a3102937c --- /dev/null +++ b/src/executors/test/add-jobs.ts @@ -0,0 +1,29 @@ +import { testQueue } from "./index.js"; + +async function addJobs() { + // Create a new queue instance + try { + // Add 5 success jobs + for (let i = 1; i <= 10; i++) { + await testQueue.add(`pass-${i}`, { action: "pass", value: i }); + } + + // Add 1 failure job + await testQueue.add("fail-1", { action: "fail", value: 100 }); + + // Add 5 more success jobs + for (let i = 11; i <= 20; i++) { + await testQueue.add(`pass-${i}`, { action: "pass", value: i }); + } + } finally { + await testQueue.close(); + } +} + +// Run the function and exit +addJobs() + .then(() => process.exit(0)) + .catch((err) => { + console.error("Error adding jobs:", err); + process.exit(1); + }); diff --git a/src/executors/test/index.ts b/src/executors/test/index.ts new file mode 100644 index 000000000..f1e44d4f0 --- /dev/null +++ b/src/executors/test/index.ts @@ -0,0 +1,34 @@ +import { Queue } from "bullmq"; +import { redis } from "../../lib/redis.js"; + +// Define job data type +export type TestJobData = { + action: "pass" | "fail"; + value: number; +}; + +// Define job result type +export type TestJobResult = { + status: "passed" | "failed"; + message: string; + attempts: number; +}; + +// Queue name constant +export const TEST_QUEUE_NAME = "executor_test"; + +// Create the queue +export const testQueue = new Queue( + TEST_QUEUE_NAME, + { + defaultJobOptions: { + attempts: 10, // Allow up to 10 attempts + backoff: { + type: "custom", // Use custom backoff strategy + }, + }, + connection: redis, + } +); + +await testQueue.setGlobalConcurrency(10000); \ No newline at end of file diff --git a/src/executors/test/worker.ts b/src/executors/test/worker.ts new file mode 100644 index 000000000..c52da9644 --- /dev/null +++ b/src/executors/test/worker.ts @@ -0,0 +1,102 @@ +import { type Job, Worker } from "bullmq"; +import { TEST_QUEUE_NAME, type TestJobData, type TestJobResult } from "./index.js"; +import { redis } from "../../lib/redis.js"; +import { sleep } from "bun"; + +// Helper function to format time +function formatTime(): string { + const now = new Date(); + return now.toLocaleTimeString("en-US", { + hour12: false, + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); +} + +// Create the worker +export const testWorker = new Worker( + TEST_QUEUE_NAME, + async (job: Job) => { + const { action, value } = job.data; + const timeStr = formatTime(); + + console.log( + `[${timeStr}] Starting to process job ${job.id}, attempt ${ + job.attemptsMade + 1 + }` + ); + + // Sleep for a while before processing + const sleepTime = 2000; // 2 seconds + console.log( + `[${timeStr}] Sleeping for ${sleepTime / 1000} seconds for job ${ + job.id + }...` + ); + await sleep(sleepTime); + + const afterSleepTimeStr = formatTime(); + console.log( + `[${afterSleepTimeStr}] Done sleeping, now processing job ${ + job.id + }, attempt ${job.attemptsMade + 1}` + ); + + // Process based on action + if (action === "pass") { + console.log(`[${afterSleepTimeStr}] Job ${job.id} passed successfully`); + return { + status: "passed", + message: "pass", + value: value, + attempts: job.attemptsMade + 1, + }; + } + + if (action === "fail") { + // Check if we've reached the retry limit (5 attempts) + if (job.attemptsMade >= 5) { + console.log( + `[${afterSleepTimeStr}] Job ${job.id} failed after ${ + job.attemptsMade + 1 + } attempts, giving up` + ); + return { + status: "failed", + message: `Failed after ${job.attemptsMade + 1} attempts`, + value: value, + attempts: job.attemptsMade + 1, + }; + } + + console.error( + `[${afterSleepTimeStr}] Job ${job.id} failed, will retry (attempt ${ + job.attemptsMade + 1 + })` + ); + throw new Error(`Intentional failure on attempt ${job.attemptsMade + 1}`); + } + + throw new Error(`Unknown action: ${action}`); + }, + { + connection: redis, + settings: { + // Always return 0 for backoff to test immediate retries + backoffStrategy: () => { + return 1000; // Always return 0 to test immediate retry behavior + }, + }, + concurrency: 5, + } +); + +// Set up event handlers for the worker +testWorker.on("ready", () => { + console.log("Test worker ready"); +}); + +testWorker.on("error", (err) => { + console.error("Test worker error", err); +}); diff --git a/src/executors/types.ts b/src/executors/types.ts new file mode 100644 index 000000000..1a3f1d4f2 --- /dev/null +++ b/src/executors/types.ts @@ -0,0 +1,229 @@ +import * as z from "zod"; +import { transactionDbEntrySchema } from "../db/derived-schemas.js"; +import { evmAddressSchema, exampleEvmAddress, hexSchema } from "../lib/zod.js"; +import { wrapResponseSchema } from "../server/schemas/shared-api-schemas.js"; + +// Example BigInt value for OpenAPI documentation +const exampleBigInt = "123456789012345678901234567890"; + +export const bigIntSchema = z + .string() + .refine( + (value) => { + try { + // Check if the string is a valid integer (no decimals, letters, etc.) + // and can be converted to a BigInt + BigInt(value); + return true; + } catch { + return false; + } + }, + { + message: "Input must be a valid integer string convertible to BigInt", + } + ) + .transform((value) => BigInt(value)) // Transform the string to BigInt + .openapi({ + description: + "A string representing an integer that is transformed into a BigInt", + example: exampleBigInt, + type: "string", // OpenAPI type (input is still a string) + format: "bigint", // Custom format to indicate it's a BigInt + }); + +export const serialisedBigIntSchema = z.string().openapi({ + description: + "A string representing an bigint response, safe to parse with BigInt", + example: exampleBigInt, + type: "string", // OpenAPI type (input is still a string) + format: "bigint", // Custom format to indicate it's a BigInt +}); + +export const transactionBodySchema = z.object({ + to: evmAddressSchema.optional().openapi({ + description: "The address of the contract to send the transaction to", + }), + data: hexSchema + .openapi({ + description: "The data of the transaction", + }) + .optional(), + value: bigIntSchema.optional().openapi({ + description: "The value of the transaction", + }), +}); + +const baseExecutionOptionsSchema = { + idempotencyKey: z + .string() + .openapi({ + description: + "The idempotency key of the transaction. Transaction requests sent with the same idempotency key will be de-duplicated. If not provided, a randomUUID will be generated. This is also used as the ID of a queued/stored transaction.", + example: "40aebdb3-f4f6-477e-a870-cb2cb90c96a3", + }) + .optional(), + chainId: z.string().openapi({ + description: "The chain id of the transaction", + }), +}; + +// AA Execution Options +export const aaExecutionOptionsSchema = z + .object({ + type: z.literal("ERC4337").openapi({ + example: "ERC4337", + }), + signerAddress: evmAddressSchema.openapi({ + description: + "The address of the engine managed account which can send transactions from your smart account", + }), + sponsorGas: z.boolean().default(true), + factoryAddress: evmAddressSchema.optional().openapi({ + description: + "The address of the smart account factory. Defaults to thirdweb default v0.7 Account Factory. Only specify this if you are using a custom account factory.", + }), + entrypointAddress: evmAddressSchema.optional().openapi({ + description: + "The address of the entrypoint contract. Defaults to the v0.7 entrypoint for the chain. Only specify this if you want to specify a different version.", + }), + + smartAccountAddress: evmAddressSchema.optional().openapi({ + description: + "The address of the smart account to send the transaction from. Either specify this, or the salt. If not specified, the inferred smart account will be with null salt. If both are specified, the salt will be ignored.", + }), + + accountSalt: z.string().optional().openapi({ + description: + "The salt of the smart account to send the transaction from. Only specify this if you want to specify a custom salt. If omitted, and smart account address is not provided, the inferred smart account will be with null salt. If a smart account address is provided, the salt will be ignored.", + }), + }) + .extend(baseExecutionOptionsSchema) + .openapi({ + ref: "aaExecutionOptions", + title: "ERC4337 Execution (Smart Account)", + }); + +export const aaZksyncExecutionOptionsSchema = z + .object({ + type: z.literal("zksync"), + accountAddress: evmAddressSchema.openapi({ + description: + "The EOA address of the account to send the zksync native AA transaction from.", + }), + sponsorGas: z.boolean().default(true), + }) + .extend(baseExecutionOptionsSchema) + .openapi({ + description: + "Uses zkSync native AA for execution. This type of execution is only available on zkSync chains.", + ref: "aaZksyncExecutionOptions", + title: "AA:zksync Execution Options", + }); + +export const autoExecutionOptionsSchema = z + .object({ + type: z + .literal("auto") + .default("auto" as const) + .openapi({ + description: + "This is the default, a `type` does not need to be specified", + }), + from: evmAddressSchema.openapi({ + description: + "The address of the account to send the transaction from. Can be the address of a smart account or an EOA.", + }), + }) + .extend(baseExecutionOptionsSchema) + .openapi({ + ref: "autoExecutionOptions", + title: "Auto-determine Best Execution Options", + description: + 'This is the default execution option. If you do not specify an execution type, and only specify a "from" string, engine will automatically determine the most optimal options for you. If you would like to specify granular options about execution strategy choose one of the other `executionOptions` type and provide them.', + }); + +export const EXECUTION_OPTIONS_EXAMPLE = { + chainId: "84532", + from: exampleEvmAddress, +} as const; + +export const eoaExecutionOptionsSchema = z + .object({ + type: z.literal("eoa"), + address: evmAddressSchema, + }) + .extend(baseExecutionOptionsSchema); + +const executionRequestSchema = z.object({ + executionOptions: z + .union([ + autoExecutionOptionsSchema, + aaExecutionOptionsSchema, + aaZksyncExecutionOptionsSchema, + eoaExecutionOptionsSchema, + ]) + .openapi({ + description: + "Use a specific execution type and provide options to configure engine's execution strategy. The default execution option is `auto`, (doesn't need to be specified) which will automatically determine the most optimal options for you. If you would like to specify granular options about execution strategy choose one of the other `executionOptions` type and provide them.", + example: EXECUTION_OPTIONS_EXAMPLE, + }), +}); + +/** + * Builds a schema for an execution request. + * Takes a schema for the shape of your transaction parameters, and returns a schema for an execution request. + * Optionally allows extending the final schema with additional fields. + * + * @param paramsSchema - The schema of the transaction parameters. + * @param extensionSchema - An optional ZodObject schema to merge into both branches of the final union schema. + * @returns A schema for an execution request, potentially extended. + */ +export function buildExecutionRequestSchema< + T extends z.ZodSchema, + // biome-ignore lint/complexity/noBannedTypes: sorry, we must + E extends z.ZodRawShape = {} // Default to empty shape if no extension +>( + paramsSchema: T, + extensionSchema: z.ZodObject = z.object({}) as z.ZodObject +): // // Return type reflects the union of two objects, each extended with Base, TxParams, and Extension +z.ZodObject< + z.objectUtil.extendShape< + // 3. Extend with Extension shape E + z.objectUtil.extendShape< + // 2. Extend with Base shape + (typeof executionRequestSchema)["shape"], + { params: T } // Add transactionParams schema T + >, + E // Shape from extensionSchema + > +> { + return executionRequestSchema + .merge(z.object({ params: paramsSchema })) + .merge(extensionSchema); +} + +export const encodedExecutionRequestSchema = buildExecutionRequestSchema( + z.array(transactionBodySchema) +).openapi({ + example: { + params: [ + { + to: exampleEvmAddress, + data: "0x", + value: "0", + }, + ], + executionOptions: EXECUTION_OPTIONS_EXAMPLE, + }, +}); + +export type EncodedExecutionRequest = z.infer< + typeof encodedExecutionRequestSchema +>; + +export const transactionResponseSchema = wrapResponseSchema( + z.object({ + transactions: z.array(transactionDbEntrySchema), + }) +); diff --git a/src/executors/workers.ts b/src/executors/workers.ts new file mode 100644 index 000000000..280c85642 --- /dev/null +++ b/src/executors/workers.ts @@ -0,0 +1,16 @@ +import { sendWorker as externalBundlerAsyncSendWorker } from "./external-bundler-async"; +import { confirmWorker as externalBundlerAsyncConfirmWorker } from "./external-bundler-async"; + +import { confirmWorker as externalBundlerSyncConfirmWorker } from "./external-bundler"; + +export { + externalBundlerAsyncSendWorker, + externalBundlerAsyncConfirmWorker, + externalBundlerSyncConfirmWorker, +}; + +export async function closeAllWorkers() { + await externalBundlerAsyncSendWorker.close(); + await externalBundlerAsyncConfirmWorker.close(); + await externalBundlerSyncConfirmWorker.close(); +} diff --git a/src/index.ts b/src/index.ts index 81f647e57..e0fe7b1b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,75 +1,30 @@ -import "./polyfill"; -import "./tracer"; +import "./lib/datadog.js"; +import "zod-openapi/extend"; -import { initServer } from "./server"; -import { env } from "./shared/utils/env"; -import { logger } from "./shared/utils/logger"; -import { initWorker } from "./worker"; -import { CancelRecycledNoncesQueue } from "./worker/queues/cancel-recycled-nonces-queue"; -import { MineTransactionQueue } from "./worker/queues/mine-transaction-queue"; -import { NonceResyncQueue } from "./worker/queues/nonce-resync-queue"; -import { ProcessEventsLogQueue } from "./worker/queues/process-event-logs-queue"; -import { ProcessTransactionReceiptsQueue } from "./worker/queues/process-transaction-receipts-queue"; -import { PruneTransactionsQueue } from "./worker/queues/prune-transactions-queue"; -import { SendTransactionQueue } from "./worker/queues/send-transaction-queue"; -import { SendWebhookQueue } from "./worker/queues/send-webhook-queue"; +import "./db/apply-migrations.js"; +import "./lib/vault-client.js"; +import { initiateCacheClearTask } from "./lib/cache.js"; +import { initiateEngineServer } from "./server/engine.js"; -const main = async () => { - if (env.ENGINE_MODE === "server_only") { - initServer(); - } else if (env.ENGINE_MODE === "worker_only") { - initWorker(); - } else { - initServer(); - initWorker(); - } -}; - -main(); - -// Adding handlers for `uncaughtException` & `unhandledRejection` -// Needs to be root level of your application to ensure it -// catches any unhandledRejections or uncaughtException that occur throughout -// entire codebase +initiateCacheClearTask(); -process.on("uncaughtException", (err) => { - logger({ - message: "Uncaught Exception", - service: "server", - level: "error", - error: err, - }); -}); +// start the metrics server +import "./server/metrics.js"; +import { defaultLogger } from "./lib/logger.js"; +import { closeAllWorkers } from "./executors/workers.js"; -process.on("unhandledRejection", (err) => { - logger({ - message: "Unhandled Rejection", - service: "server", - level: "error", - error: err, - }); -}); - -process.on("SIGINT", () => gracefulShutdown("SIGINT")); -process.on("SIGTERM", () => gracefulShutdown("SIGTERM")); +// start the engine server +initiateEngineServer(); const gracefulShutdown = async (signal: NodeJS.Signals) => { - logger({ - level: "info", - service: "server", - message: `Received ${signal}, closing server...`, - }); + defaultLogger.info(`Received ${signal}, closing server...`); // Gracefully close workers to minimize stalled jobs. // Source: https://docs.bullmq.io/guide/going-to-production#gracefully-shut-down-workers - await SendWebhookQueue.q.close(); - await ProcessEventsLogQueue.q.close(); - await ProcessTransactionReceiptsQueue.q.close(); - await SendTransactionQueue.q.close(); - await MineTransactionQueue.q.close(); - await CancelRecycledNoncesQueue.q.close(); - await PruneTransactionsQueue.q.close(); - await NonceResyncQueue.q.close(); + await closeAllWorkers(); process.exit(0); }; + +process.on("SIGINT", () => gracefulShutdown("SIGINT")); +process.on("SIGTERM", () => gracefulShutdown("SIGTERM")); diff --git a/src/lib/access-tokens.ts b/src/lib/access-tokens.ts new file mode 100644 index 000000000..790e53950 --- /dev/null +++ b/src/lib/access-tokens.ts @@ -0,0 +1,37 @@ +import { LRUCache } from "lru-cache"; +import { ResultAsync, err, ok, okAsync } from "neverthrow"; +import { db } from "../db/connection.js"; +import type { TokenDbEntry } from "../db/types.js"; +import { type AccessTokenErr, type DbErr, mapDbError } from "./errors.js"; + +const accessTokenCache = new LRUCache({ + max: 1024, +}); + +export function getAccessToken( + id: string, +): ResultAsync { + const cached = accessTokenCache.get(id); + if (cached) { + return okAsync(cached); + } + + return ResultAsync.fromPromise( + db.query.tokens.findFirst({ + where: (tokens, { eq }) => eq(tokens.id, id), + }), + mapDbError, + ) + .andTee((token) => { + token && accessTokenCache.set(id, token ?? null); + }) + .andThen((token) => + token + ? ok(token) + : err({ + kind: "access_token", + code: "token_not_found", + status: 400, + } as AccessTokenErr), + ); +} diff --git a/src/lib/accounts/accounts.ts b/src/lib/accounts/accounts.ts new file mode 100644 index 000000000..f9ca6f1db --- /dev/null +++ b/src/lib/accounts/accounts.ts @@ -0,0 +1,469 @@ +import * as z from "zod"; +import { + gcpAccountConfigSchema, + gcpAccountCreateParamsSchema, + gcpAccountCredentialSchema, + gcpPlatformIdentifiersSchema, + provisionGcpKmsAccount, +} from "./gcp/gcp.js"; +import { + encryptedJsonToAccount, + localAccountCreateParamsSchema, + localPlatformIdentifiersSchema, + provisionLocalAccount, +} from "./local.js"; +import { + circleAccountConfigSchema, + circleAccountCreateParamsSchema, + circleAccountCredentialSchema, + circlePlatformIdentifiersSchema, + provisionCircleAccount, +} from "./circle/circle.js"; +import { + awsAccountConfigSchema, + awsAccountCreateParamsSchema, + awsAccountCredentialSchema, + awsPlatformIdentifiersSchema, + provisionAwsKmsAccount, +} from "./aws/aws.js"; + +import { config } from "../config.js"; +import { err, errAsync, ok, okAsync, ResultAsync, safeTry } from "neverthrow"; +import { + mapDbError, + type AccountErr, + type EoaCredentialErr, + type LocalAccountErr, + type WalletProviderConfigErr, +} from "../errors.js"; +import { db } from "../../db/connection.js"; +import { thirdwebClient } from "../thirdweb-client.js"; +import { baseAccountResponseSchema } from "./base-schemas.js"; +import type { Address } from "thirdweb"; +import type { InferSelectModel } from "drizzle-orm"; +import type { eoas } from "../../db/schema.js"; +import { getAwsKmsAccount } from "./aws/get-aws-account.js"; +import { getGcpKmsAccount } from "./gcp/get-gcp-account.js"; +import { getCircleAccount } from "./circle/get-circle-account.js"; +import type { ENGINE_EOA_TYPES } from "../../db/types.js"; +import { getVaultAccount } from "./vault/get-vault-account.js"; +import { vaultClient } from "../vault-client.js"; + +export type EngineEoaType = (typeof ENGINE_EOA_TYPES)[number]; + +export type EoaPlatformIdentifiers = z.infer< + typeof accountPlatformIdentifiersSchema +>; + +export const accountPlatformIdentifiersSchema = z.discriminatedUnion("type", [ + awsPlatformIdentifiersSchema, + gcpPlatformIdentifiersSchema, + circlePlatformIdentifiersSchema, + localPlatformIdentifiersSchema, +]); + +export const accountCreateSchema = z.discriminatedUnion("type", [ + gcpAccountCreateParamsSchema, + localAccountCreateParamsSchema, + circleAccountCreateParamsSchema, + awsAccountCreateParamsSchema, +]); + +type CreateAccountParams = z.infer; + +export const accountCredentialSchema = z.discriminatedUnion("type", [ + gcpAccountCredentialSchema, + awsAccountCredentialSchema, + circleAccountCredentialSchema, +]); + +export type EoaCredential = z.infer; + +export const accountConfigSchema = z.discriminatedUnion("type", [ + gcpAccountConfigSchema, + awsAccountConfigSchema, + circleAccountConfigSchema, +]); + +type WalletProviderConfigFlat = z.infer; + +export type WalletProviderConfigMap = { + [K in WalletProviderConfigFlat["type"]]: Extract< + WalletProviderConfigFlat, + { type: K } + >; +}; + +export function getWalletProviderConfig< + T extends WalletProviderConfigFlat["type"], +>(params: { type: T }) { + const typeConfig = config.walletProviderConfigs[params.type]; + + if (!typeConfig) { + switch (params.type) { + case "aws-kms": { + return err({ + kind: "wallet_provider_config", + code: "missing_aws_kms_config", + } as WalletProviderConfigErr); + } + case "gcp-kms": { + return err({ + kind: "wallet_provider_config", + code: "missing_gcp_kms_config", + } as WalletProviderConfigErr); + } + case "circle": { + return err({ + kind: "wallet_provider_config", + code: "missing_circle_config", + } as WalletProviderConfigErr); + } + } + } + + return ok(typeConfig as Extract); +} + +export function provisionAccount(params: CreateAccountParams) { + return safeTry(async function* () { + if (params.type === "local") { + return ok(yield* provisionLocalAccount(params)); + } + + const credential = yield* ResultAsync.fromPromise( + db.query.eoaCredentials.findFirst({ + where: (credentials, { eq }) => eq(credentials.id, params.credentialId), + }), + mapDbError, + ); + + switch (params.type) { + case "aws-kms": { + const awsConfig = yield* getWalletProviderConfig({ + type: "aws-kms", + }); + + if (!credential || credential.data.type !== "aws-kms") { + return err({ + kind: "eoa_credential", + code: "credential_not_found", + message: `Credential not found: ${params.credentialId}`, + status: 400, + } as EoaCredentialErr); + } + + return ok( + yield* provisionAwsKmsAccount({ + config: awsConfig, + credentials: credential.data, + params: params, + client: thirdwebClient, + }), + ); + } + case "gcp-kms": { + const gcpConfig = yield* getWalletProviderConfig({ + type: "gcp-kms", + }); + + if (!credential || credential.data.type !== "gcp-kms") { + return err({ + kind: "eoa_credential", + code: "credential_not_found", + message: `Credential not found: ${params.credentialId}`, + status: 400, + } as EoaCredentialErr); + } + + return ok( + yield* provisionGcpKmsAccount({ + config: gcpConfig, + credentials: credential.data, + params: params, + client: thirdwebClient, + }), + ); + } + case "circle": { + const circleConfig = yield* getWalletProviderConfig({ + type: "circle", + }); + + if (!credential || credential.data.type !== "circle") { + return err({ + kind: "eoa_credential", + code: "credential_not_found", + message: `Credential not found: ${params.credentialId}`, + status: 400, + } as EoaCredentialErr); + } + + return ok( + yield* provisionCircleAccount({ + config: circleConfig, + credentials: credential.data, + params: params, + client: thirdwebClient, + }), + ); + } + } + }); +} + +export function getSmartAccountDbEntry(params: { + address: Address; + signerAddress?: Address; +}) { + return safeTry(async function* () { + const smartAccounts = yield* ResultAsync.fromPromise( + db.query.smartAccounts.findMany({ + where: (sa, { eq, and }) => + and( + eq(sa.address, params.address), + params.signerAddress + ? eq(sa.signerAddress, params.signerAddress) + : undefined, + ), + with: { + signer: { + with: { + credential: true, + }, + }, + }, + }), + mapDbError, + ); + + if (smartAccounts.length > 1) { + return errAsync({ + kind: "account", + code: "could_not_disambiguate", + } as AccountErr); + } + + const [smartAccount] = smartAccounts; + return okAsync(smartAccount); + }); +} + +export function getEoaDbEntry(params: { address: Address }) { + return safeTry(async function* () { + const eoa = yield* ResultAsync.fromPromise( + db.query.eoas.findFirst({ + where: (eoa, { eq }) => eq(eoa.address, params.address), + with: { + credential: true, + }, + }), + mapDbError, + ); + + return okAsync(eoa); + }); +} + +type EoaDbEntryWithCredential = InferSelectModel & { + credential: { + data: EoaCredential | null; + } | null; +}; + +export function eoaDbEntryToAccount({ + eoa, + // encryptionPassword, +}: { + eoa: EoaDbEntryWithCredential; + // encryptionPassword?: string; +}) { + return safeTry(async function* () { + switch (eoa.type) { + case "local": { + const encryptedJson = eoa.encryptedJson; + + if (!encryptedJson) { + return err({ + kind: "local_account", + code: "account_decryption_failed", + message: "Encrypted JSON is missing", + } as LocalAccountErr); + } + + return okAsync( + yield* encryptedJsonToAccount({ + json: encryptedJson, + // encryptionPassword, + }), + ); + } + case "aws-kms": { + const credential = eoa.credential?.data; + + if (!credential || credential.type !== "aws-kms") { + return errAsync({ + kind: "eoa_credential", + code: "credential_not_found", + message: `Credential not found or is not an aws-kms credential: ${eoa.address}`, + status: 400, + } as EoaCredentialErr); + } + + const platformIdentifiers = eoa.platformIdentifiers; + + if (!platformIdentifiers || platformIdentifiers.type !== "aws-kms") { + return errAsync({ + kind: "account", + code: "invalid_platform_identifiers", + status: 500, + } as AccountErr); + } + + return okAsync( + yield* getAwsKmsAccount({ + client: thirdwebClient, + keyId: platformIdentifiers.awsKmsArn, + credentials: credential, + }), + ); + } + case "gcp-kms": { + const credential = eoa.credential?.data; + + if (!credential || credential.type !== "gcp-kms") { + return errAsync({ + kind: "eoa_credential", + code: "credential_not_found", + message: `Credential not found or is not a gcp-kms credential: ${eoa.address}`, + status: 400, + } as EoaCredentialErr); + } + + const platformIdentifiers = eoa.platformIdentifiers; + + if (!platformIdentifiers || platformIdentifiers.type !== "gcp-kms") { + return errAsync({ + kind: "account", + code: "invalid_platform_identifiers", + status: 500, + } as AccountErr); + } + + return okAsync( + yield* getGcpKmsAccount({ + client: thirdwebClient, + respourcePath: platformIdentifiers.gcpKmsResourcePath, + clientOptions: { + credentials: { + client_email: credential.email, + private_key: credential.privateKey, + }, + }, + }), + ); + } + case "circle": { + const credential = eoa.credential?.data; + + if (!credential || credential.type !== "circle") { + return errAsync({ + kind: "eoa_credential", + code: "credential_not_found", + message: `Credential not found or is not a circle credential: ${eoa.address}`, + status: 400, + } as EoaCredentialErr); + } + + const platformIdentifiers = eoa.platformIdentifiers; + + if (!platformIdentifiers || platformIdentifiers.type !== "circle") { + return errAsync({ + kind: "account", + code: "invalid_platform_identifiers", + status: 500, + } as AccountErr); + } + + const circleConfig = yield* getWalletProviderConfig({ + type: "circle", + }); + + return okAsync( + yield* getCircleAccount({ + client: thirdwebClient, + walletId: platformIdentifiers.circleWalletId, + apiKey: circleConfig.apiKey, + entitySecret: credential.entitySecret, + }), + ); + } + } + }); +} + +export function getEngineAccount(params: { + address: Address; + signerAddress?: Address; + vaultAccessToken?: string; + // encryptionPassword?: string; +}) { + return safeTry(async function* () { + if (params.vaultAccessToken) { + return okAsync({ + account: getVaultAccount({ + address: params.signerAddress ?? params.address, + auth: { + accessToken: params.vaultAccessToken, + }, + thirdwebClient: thirdwebClient, + vaultClient: vaultClient, + }), + }); + } + + const [smartAccountDetails, eoaDetails] = yield* ResultAsync.combine([ + getSmartAccountDbEntry({ + address: params.address, + signerAddress: params.signerAddress, + }), + getEoaDbEntry({ address: params.address }), + ]); + + if (eoaDetails) { + const account = yield* eoaDbEntryToAccount({ + eoa: eoaDetails, + // encryptionPassword: params.encryptionPassword, + }); + + return okAsync({ + account, + }); + } + if (smartAccountDetails) { + const signerAccount = yield* eoaDbEntryToAccount({ + eoa: smartAccountDetails.signer, + // encryptionPassword: params.encryptionPassword, + }); + + return okAsync({ + signerAccount: signerAccount, + smartAccountDetails: smartAccountDetails, + }); + } + + return errAsync({ + kind: "account", + code: "account_not_found", + message: `Account not found: ${params.signerAddress ?? params.address}`, + status: 400, + } as AccountErr); + }); +} + +export const accountResponseSchema = z.discriminatedUnion("type", [ + gcpPlatformIdentifiersSchema.merge(baseAccountResponseSchema), + awsPlatformIdentifiersSchema.merge(baseAccountResponseSchema), + circlePlatformIdentifiersSchema.merge(baseAccountResponseSchema), + localPlatformIdentifiersSchema.merge(baseAccountResponseSchema), +]); diff --git a/src/lib/accounts/aws/aws.ts b/src/lib/accounts/aws/aws.ts new file mode 100644 index 000000000..d0a25e078 --- /dev/null +++ b/src/lib/accounts/aws/aws.ts @@ -0,0 +1,220 @@ +import * as z from "zod"; +import { err, ok, ResultAsync, safeTry } from "neverthrow"; +import { CreateKeyCommand, KMSClient } from "@aws-sdk/client-kms"; +import type { Account } from "thirdweb/wallets"; +import type { ThirdwebClient } from "thirdweb"; +import type { AwsKmsErr } from "../../errors.js"; +import { getAwsKmsAccount } from "./get-aws-account.js"; +import { + baseAccountCreateSchema, + baseCredentialIdSchema, +} from "../base-schemas.js"; + +const type = z.literal("aws-kms"); + +export const awsPlatformIdentifiersSchema = z.object({ + awsKmsArn: z.string().openapi({ + description: "The ARN of the AWS KMS key", + example: + "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + }), + type, +}); + +export const awsAccountCreateParamsSchema = z + .object({ type }) + .merge(baseAccountCreateSchema) + .merge(baseCredentialIdSchema); + +export const awsAccountCredentialSchema = z.object({ + accessKeyId: z.string().openapi({ + description: "The access key ID of the AWS account", + example: "AKIA1234567890123456", + }), + secretAccessKey: z.string().openapi({ + description: "The secret access key of the AWS account", + example: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + }), + type, +}); + +export const awsAccountConfigSchema = z.object({ + region: z.string().openapi({ + description: "The default AWS region of the AWS account", + example: "us-east-1", + }), + type, +}); + +type ApiError = { + name?: string; + message?: string; + Code?: string; + $metadata?: { + httpStatusCode?: number; + }; +}; + +const isAwsApiError = (error: unknown): error is ApiError => { + return ( + typeof error === "object" && + error !== null && + ("Code" in error || "$metadata" in error) + ); +}; + +export const mapAwsError = ( + error: unknown, + code: AwsKmsErr["code"], + defaultMessage: string, +): AwsKmsErr => { + if (isAwsApiError(error)) { + const statusCode = error.$metadata?.httpStatusCode ?? 500; + const errorCode = error.Code; + + // Map AWS error codes to our error codes + const mappedCode: AwsKmsErr["code"] = + errorCode === "UnauthorizedException" + ? "unauthorized" + : errorCode === "ThrottlingException" + ? "rate_limit_exceeded" + : errorCode === "KMSInvalidStateException" + ? "invalid_key_state" + : code; + + return { + kind: "aws_kms", + code: mappedCode, + status: statusCode, + message: error.message ?? defaultMessage, + source: error, + } as AwsKmsErr; + } + + return { + kind: "aws_kms", + code, + status: 500, + message: error instanceof Error ? error.message : defaultMessage, + source: error instanceof Error ? error : undefined, + }; +}; + +export function provisionAwsKmsAccount({ + config, + credentials, + client: thirdwebClient, +}: { + params: z.infer; + config: z.infer; + credentials: z.infer; + client: ThirdwebClient; +}): ResultAsync< + { + account: Account; + platformIdentifiers: z.infer; + }, + AwsKmsErr +> { + return safeTry(async function* () { + const kmsClient = new KMSClient({ + region: config.region, + credentials: { + accessKeyId: credentials.accessKeyId, + secretAccessKey: credentials.secretAccessKey, + }, + }); + + const keyResponse = yield* ResultAsync.fromPromise( + kmsClient.send( + new CreateKeyCommand({ + Description: "thirdweb Engine AWS KMS Backend Wallet", + KeyUsage: "SIGN_VERIFY", + KeySpec: "ECC_SECG_P256K1", + MultiRegion: false, + }), + ), + (error) => + mapAwsError( + error, + "key_creation_failed", + "Failed to create AWS KMS key", + ), + ); + + if (!keyResponse.KeyMetadata?.Arn) { + return err({ + kind: "aws_kms", + code: "key_creation_failed", + status: 500, + message: "Failed to create AWS KMS key - no ARN returned", + } as AwsKmsErr); + } + + const awsKmsArn = keyResponse.KeyMetadata.Arn; + const { keyId } = splitAwsKmsArn(awsKmsArn); + + const account = yield* getAwsKmsAccount({ + client: thirdwebClient, + keyId, + credentials: { + accessKeyId: credentials.accessKeyId, + secretAccessKey: credentials.secretAccessKey, + }, + }); + + return ok({ + account, + platformIdentifiers: { + type: "aws-kms" as const, + awsKmsArn, + }, + }); + }); +} + +/** + * Split an AWS KMS ARN into its parts. + */ +export function splitAwsKmsArn(arn: string) { + // arn:aws:kms:::key/ + const parts = arn.split(":"); + if (parts.length < 6) { + throw new Error("Invalid AWS KMS ARN"); + } + + const keyIdPart = parts[5]; + if (!keyIdPart) { + throw new Error("Invalid AWS KMS ARN"); + } + + const keyId = keyIdPart.split("/")[1]; + if (!keyId) { + throw new Error("Invalid AWS KMS ARN"); + } + const keyIdExtension = parts.slice(6).join(":"); + + const region = parts[3]; + const accountId = parts[4]; + + if (!region || !accountId) { + throw new Error("Invalid AWS KMS ARN"); + } + + return { + region, + accountId, + keyId: `${keyId}${keyIdExtension ? `:${keyIdExtension}` : ""}`, + }; +} + +/** + * Get an AWS KMS ARN from its parts. + */ +export function getAwsKmsArn(options: { + region: string; + accountId: string; + keyId: string; +}) { + return `arn:aws:kms:${options.region}:${options.accountId}:key/${options.keyId}`; +} diff --git a/src/lib/accounts/aws/get-aws-account.ts b/src/lib/accounts/aws/get-aws-account.ts new file mode 100644 index 000000000..1e7486ef2 --- /dev/null +++ b/src/lib/accounts/aws/get-aws-account.ts @@ -0,0 +1,159 @@ +import { ok, ResultAsync, safeTry } from "neverthrow"; +import type { TypedData } from "ox"; +import type { Address, Hex, ThirdwebClient } from "thirdweb"; +import { + eth_sendRawTransaction, + getRpcClient, + keccak256, + serializeTransaction, +} from "thirdweb"; + +import type { Account } from "thirdweb/wallets"; +import type { SignableMessage } from "viem"; +import { getChain } from "../../chain.js"; +import type { AwsKmsErr, RpcErr } from "../../errors.js"; +import type { + SendTransactionOptions, + SendTransactionResult, + SignTransactionOptions, +} from "../transaction-types.js"; +import { mapAwsError } from "./aws.js"; +import { KmsSigner } from "aws-kms-signer"; +import { hashMessage } from "thirdweb/utils"; +import { getSignPayload } from "ox/TypedData"; + +export function getAwsKmsAccount({ + keyId, + credentials, + client, +}: { + keyId: string; + credentials: { + accessKeyId: string; + secretAccessKey: string; + }; + client: ThirdwebClient; +}): ResultAsync { + return safeTry(async function* () { + const signer = new KmsSigner(keyId, { + credentials, + }); + + // Get address + const addressResult = yield* ResultAsync.fromPromise( + signer.getAddress(), + (error) => + mapAwsError( + error, + "address_retrieval_failed", + "Failed to get address from KMS key", + ), + ); + + const address = `0x${addressResult}` as Address; + + async function signTransaction(tx: SignTransactionOptions): Promise { + try { + const serializedTx = serializeTransaction({ transaction: tx }); + const txHash = keccak256(serializedTx); + const signature = await signer.sign( + Buffer.from(txHash.slice(2), "hex"), + ); + + const r = `0x${signature.r.toString("hex")}` as Hex; + const s = `0x${signature.s.toString("hex")}` as Hex; + const v = BigInt(signature.v); + const yParity: 0 | 1 = signature.v % 2 === 0 ? 1 : 0; + + return serializeTransaction({ + transaction: tx, + signature: { r, s, v, yParity }, + }); + } catch (error) { + throw mapAwsError( + error, + "signature_failed", + "Could not sign transaction", + ); + } + } + + async function sendTransaction( + tx: SendTransactionOptions, + ): SendTransactionResult { + let signature: Hex; + try { + signature = await signTransaction(tx); + } catch (error) { + // signTransaction only throws a mapped AwsErr + // biome-ignore lint/complexity/noUselessCatch: better for readability + throw error; + } + + const rpcRequest = getRpcClient({ + client: client, + chain: await getChain(tx.chainId), + }); + + try { + const transactionHash = await eth_sendRawTransaction( + rpcRequest, + signature, + ); + return { transactionHash }; + } catch (error) { + throw { + kind: "rpc", + code: "send_transaction_failed", + status: 500, + message: + error instanceof Error ? error.message : "RPC request failed", + source: error instanceof Error ? error : undefined, + } as RpcErr; + } + } + + async function signMessage({ + message, + }: { + message: SignableMessage; + }): Promise { + try { + const messageHash = hashMessage(message); + const signature = await signer.sign( + Buffer.from(messageHash.slice(2), "hex"), + ); + return `0x${signature.toString()}`; + } catch (error) { + throw mapAwsError(error, "signature_failed", "Could not sign message"); + } + } + + async function signTypedData< + const typedData extends TypedData.TypedData | Record, + primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, + >(_typedData: TypedData.Definition): Promise { + try { + const typedDataHash = getSignPayload(_typedData); + const signature = await signer.sign( + Buffer.from(typedDataHash.slice(2), "hex"), + ); + return `0x${signature.toString()}`; + } catch (error) { + throw mapAwsError( + error, + "signature_failed", + "Could not sign typed data", + ); + } + } + + return ok({ + address, + sendTransaction, + signMessage, + signTypedData: signTypedData as Account["signTypedData"], + signTransaction, + } satisfies Account); + }); +} diff --git a/src/lib/accounts/base-schemas.ts b/src/lib/accounts/base-schemas.ts new file mode 100644 index 000000000..2ef0d0853 --- /dev/null +++ b/src/lib/accounts/base-schemas.ts @@ -0,0 +1,55 @@ +import * as z from "zod"; +import { timestampsSchema, evmAddressSchema } from "../zod.js"; + +export const baseAccountCreateSchema = z.object({ + label: z.string().openapi({ + description: "The label of the account", + }), +}); + +export const baseCredentialIdSchema = z.object({ + credentialId: z.string().uuid().openapi({ + description: + "The ID of the credential used to create the account. Only not present for local accounts.", + example: "1e87e873-3ca4-411b-bfdc-4657bac4802e", + }), +}); + +export const smartAccountSchema = z.object({ + address: evmAddressSchema, + signerAddress: evmAddressSchema.openapi({ + description: "The address of the signer account", + }), + factoryAddress: evmAddressSchema.openapi({ + description: "The address of the factory contract", + }), + entrypointAddress: evmAddressSchema.openapi({ + description: "The address of the entry point contract", + }), + accountSalt: z.string().openapi({ + description: + "The salt used to generate the account address. Default smart accounts are created with a null salt. Smart account address is deterministically generated from the signer address, factory address and salt.", + example: "any", + }), +}); + +export const smartAccountResponseSchema = + smartAccountSchema.merge(timestampsSchema); + +export const baseAccountResponseSchema = z + .object({ + address: evmAddressSchema, + label: z.string().openapi({ + description: "The label of the account", + }), + credentialId: z.string().openapi({ + description: + "The ID of the credential used to create the account. Only not present for local accounts.", + example: "1e87e873-3ca4-411b-bfdc-4657bac4802e", + }), + smartAccounts: z.array(smartAccountResponseSchema).openapi({ + description: + "The smart accounts associated with the account. Engine will automatically create a default smart account with your newly created account", + }), + }) + .merge(timestampsSchema); diff --git a/src/lib/accounts/circle/circle.ts b/src/lib/accounts/circle/circle.ts new file mode 100644 index 000000000..07cdf4cae --- /dev/null +++ b/src/lib/accounts/circle/circle.ts @@ -0,0 +1,214 @@ +import * as z from "zod"; +import { initiateDeveloperControlledWalletsClient } from "@circle-fin/developer-controlled-wallets"; +import { err, ok, ResultAsync, safeTry } from "neverthrow"; +import type { Account } from "thirdweb/wallets"; +import type { ThirdwebClient } from "thirdweb"; +import type { CircleErr } from "../../errors.js"; +import { getCircleAccount } from "./get-circle-account.js"; +import { + baseAccountCreateSchema, + baseCredentialIdSchema, +} from "../base-schemas.js"; + +const type = z.literal("circle"); + +export const circlePlatformIdentifiersSchema = z.object({ + circleWalletId: z.string().openapi({ + description: "The ID of the Circle wallet", + example: "12345678-1234-1234-1234-123456789012", + }), + walletSetId: z.string().openapi({ + description: "The ID of the wallet set", + example: "12345678-1234-1234-1234-123456789012", + }), + isTestnet: z.boolean().openapi({ + description: "Whether the Circle wallet is on testnet", + example: true, + }), + type, +}); + +export const circleAccountCreateParamsSchema = z + .object({ + type, + walletSetId: z.string().optional().openapi({ + description: "The ID of the wallet set", + example: "12345678-1234-1234-1234-123456789012", + }), + isTestnet: z.boolean().openapi({ + description: "Whether the Circle wallet is on testnet", + example: true, + }), + }) + .merge(baseCredentialIdSchema) + .merge(baseAccountCreateSchema); + +export const circleAccountCredentialSchema = z.object({ + entitySecret: z.string().openapi({ + description: + "32-byte hex string. Consult https://developers.circle.com/w3s/entity-secret-management to create and register an entity secret.", + example: "152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4", + }), + type, +}); + +export const circleAccountConfigSchema = z.object({ + apiKey: z.string().openapi({ + description: "The API key for the Circle API", + }), + type, +}); + +type AxiosApiError = { + response?: { + status?: number; + data?: { + message?: string; + }; + }; +}; + +export const isAxiosApiError = (error: unknown): error is AxiosApiError => { + return ( + typeof error === "object" && + error !== null && + "response" in error && + typeof error.response === "object" && + error.response !== null + ); +}; + +export const mapCircleError = ( + error: unknown, + code: CircleErr["code"], + defaultMessage: string, +): CircleErr => { + if (isAxiosApiError(error)) { + const statusCode = error.response?.status ?? 500; + const responseMessage = error.response?.data?.message; + + // Map HTTP status codes to appropriate error codes + const mappedCode: CircleErr["code"] = + statusCode === 429 + ? "rate_limit_exceeded" + : statusCode === 401 + ? "unauthorized" + : statusCode === 503 + ? "service_unavailable" + : code; + + return { + kind: "circle", + code: mappedCode, + status: statusCode, + message: responseMessage ?? defaultMessage, + source: error, + } as CircleErr; + } + + return { + kind: "circle", + code, + status: 500, + message: error instanceof Error ? error.message : defaultMessage, + source: error instanceof Error ? error : undefined, + }; +}; + +export function provisionCircleAccount({ + params, + config, + credentials, + client, +}: { + params: z.infer; + config: z.infer; + credentials: z.infer; + client: ThirdwebClient; +}): ResultAsync< + { + account: Account; + platformIdentifiers: z.infer; + }, + CircleErr +> { + const circleDeveloperSdk = initiateDeveloperControlledWalletsClient({ + apiKey: config.apiKey, + entitySecret: credentials.entitySecret, + }); + + return safeTry(async function* () { + // Get or create wallet set + let walletSetId = params.walletSetId; + + if (!walletSetId) { + const walletSetResponse = yield* ResultAsync.fromPromise( + circleDeveloperSdk.createWalletSet({ + name: `Engine WalletSet ${new Date().toISOString()}`, + }), + (error) => + mapCircleError( + error, + "wallet_set_creation_failed", + "Could not create wallet set", + ), + ); + + walletSetId = walletSetResponse.data?.walletSet.id; + if (!walletSetId) { + return err({ + kind: "circle", + code: "wallet_set_creation_failed", + message: "Did not receive wallet set ID from Circle API", + status: 500, + } as CircleErr); + } + } + + // Provision new wallet + const walletResponse = yield* ResultAsync.fromPromise( + circleDeveloperSdk.createWallets({ + accountType: "EOA", + blockchains: [params.isTestnet ? "EVM-TESTNET" : "EVM"], + count: 1, + walletSetId: walletSetId, + }), + (error) => + mapCircleError( + error, + "wallet_provisioning_failed", + "Could not provision wallet", + ), + ); + + const provisionedWallet = walletResponse.data?.wallets?.[0]; + if (!provisionedWallet) { + return err({ + kind: "circle", + code: "wallet_provisioning_failed", + message: "Did not receive provisioned wallet from Circle API", + status: 500, + } as CircleErr); + } + + // Get Circle account + const account = yield* getCircleAccount({ + walletId: provisionedWallet.id, + apiKey: config.apiKey, + entitySecret: credentials.entitySecret, + client, + }); + + return ok({ + account, + platformIdentifiers: { + type: "circle" as const, + circleWalletId: provisionedWallet.id, + walletSetId: walletSetId, + isTestnet: !!params.isTestnet, + }, + }); + }); +} + +export type CircleAccount = Account; diff --git a/src/lib/accounts/circle/get-circle-account.ts b/src/lib/accounts/circle/get-circle-account.ts new file mode 100644 index 000000000..66b00dae6 --- /dev/null +++ b/src/lib/accounts/circle/get-circle-account.ts @@ -0,0 +1,210 @@ +import { errAsync, okAsync, ResultAsync } from "neverthrow"; +import type { Account } from "thirdweb/wallets"; +import { initiateDeveloperControlledWalletsClient } from "@circle-fin/developer-controlled-wallets"; +import { mapCircleError } from "./circle.js"; +import { + eth_sendRawTransaction, + getRpcClient, + serializeTransaction, + type Address, + type Hex, + type ThirdwebClient, +} from "thirdweb"; + +import { parseSignature, type SignableMessage } from "viem"; +import { stringify, toHex } from "thirdweb/utils"; + +import type { CircleErr, RpcErr } from "../../errors.js"; +import type { + SendTransactionOptions, + SendTransactionResult, + SignTransactionOptions, +} from "../transaction-types.js"; +import type { TypedData } from "ox"; +import { getChain } from "../../chain.js"; + +export function getCircleAccount({ + walletId, + apiKey, + entitySecret, + client, +}: { + walletId: string; + apiKey: string; + entitySecret: string; + client: ThirdwebClient; +}): ResultAsync { + const circleDeveloperSdk = initiateDeveloperControlledWalletsClient({ + apiKey, + entitySecret, + }); + + // Initial wallet setup using ResultAsync + return ResultAsync.fromPromise( + circleDeveloperSdk.getWallet({ id: walletId }), + (error) => + mapCircleError( + error, + "wallet_retrieval_failed", + `Could not get wallet with id:${walletId}`, + ), + ).andThen((walletResponse) => { + const wallet = walletResponse.data?.wallet; + if (!wallet) { + return errAsync({ + kind: "circle", + code: "wallet_retrieval_failed", + status: 500, + message: `Unable to get circle wallet with id:${walletId}`, + } as CircleErr); + } + + const address = wallet.address as Address; + + // Account methods that throw CircleErr + async function signTransaction(tx: SignTransactionOptions): Promise { + try { + const signature = await circleDeveloperSdk.signTransaction({ + walletId, + transaction: stringify(tx), + }); + + if (!signature.data?.signature) { + throw { + kind: "circle", + code: "signature_failed", + status: 500, + message: "Unable to sign transaction", + } as CircleErr; + } + + return signature.data.signature as Hex; + } catch (error) { + throw mapCircleError( + error, + "signature_failed", + "Could not get transaction signature", + ); + } + } + + async function sendTransaction( + tx: SendTransactionOptions, + ): SendTransactionResult { + let signature: Hex; + try { + signature = await signTransaction(tx); + } catch (error) { + // signTransaction already returns CircleErr + // biome-ignore lint/complexity/noUselessCatch: better for readability + throw error; + } + + const rpcRequest = getRpcClient({ + client: client, + chain: getChain(tx.chainId), + }); + + const splittedSignature = parseSignature(signature); + const signedTransaction = serializeTransaction({ + transaction: tx, + signature: splittedSignature, + }); + + try { + const transactionHash = await eth_sendRawTransaction( + rpcRequest, + signedTransaction, + ); + return { transactionHash }; + } catch (error) { + throw { + kind: "rpc", + code: "send_transaction_failed", + status: 500, + message: + error instanceof Error + ? error.message + : `RPC request failed from Circle Account on chain ${tx}`, + source: error instanceof Error ? error : undefined, + } as RpcErr; + } + } + + async function signTypedData< + const typedData extends TypedData.TypedData | Record, + primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, + >(_typedData: TypedData.Definition): Promise { + try { + const signatureResponse = await circleDeveloperSdk.signTypedData({ + data: stringify(_typedData), + walletId, + }); + + if (!signatureResponse.data?.signature) { + throw { + kind: "circle", + code: "signature_failed", + status: 500, + message: "Could not sign typed data", + } as CircleErr; + } + + return signatureResponse.data.signature as Hex; + } catch (error) { + throw mapCircleError( + error, + "signature_failed", + "Could not get signature for typed data", + ); + } + } + + async function signMessage({ + message, + }: { + message: SignableMessage; + }): Promise { + try { + const isRawMessage = typeof message === "object" && "raw" in message; + let messageToSign = isRawMessage ? message.raw : message; + + if (typeof messageToSign !== "string") { + messageToSign = toHex(messageToSign); + } + + const signatureResponse = await circleDeveloperSdk.signMessage({ + walletId, + message: messageToSign, + encodedByHex: isRawMessage, + }); + + if (!signatureResponse.data?.signature) { + throw { + kind: "circle", + code: "signature_failed", + status: 500, + message: "Could not get signature", + } as CircleErr; + } + + return signatureResponse.data.signature as Hex; + } catch (error) { + throw mapCircleError( + error, + "signature_failed", + "Could not get message signature", + ); + } + } + + // Return the Account implementation + return okAsync({ + address, + sendTransaction, + signMessage, + signTypedData: signTypedData as Account["signTypedData"], + signTransaction, + } satisfies Account); + }); +} diff --git a/src/lib/accounts/gcp/gcp.ts b/src/lib/accounts/gcp/gcp.ts new file mode 100644 index 000000000..6837cb5b1 --- /dev/null +++ b/src/lib/accounts/gcp/gcp.ts @@ -0,0 +1,243 @@ +import * as z from "zod"; +import type { GcpKmsErr } from "../../errors.js"; +import type { ThirdwebClient } from "thirdweb"; +import { err, ok, ResultAsync, safeTry } from "neverthrow"; +import type { Account } from "thirdweb/wallets"; +import { KeyManagementServiceClient } from "@google-cloud/kms"; +import { getGcpKmsAccount } from "./get-gcp-account.js"; +import { + baseAccountCreateSchema, + baseCredentialIdSchema, +} from "../base-schemas.js"; + +const type = z.literal("gcp-kms"); + +export const gcpPlatformIdentifiersSchema = z.object({ + gcpKmsResourcePath: z.string().openapi({ + description: "The resource path of the GCP KMS key", + example: + "projects/123456789012/locations/global/keyRings/keyring-123456789012/cryptoKeys/key-123456789012", + }), + type, +}); + +export const gcpAccountCreateParamsSchema = z + .object({ type }) + .merge(baseAccountCreateSchema) + .merge(baseCredentialIdSchema); + +export const gcpAccountCredentialSchema = z.object({ + email: z.string().email().openapi({ + description: "The email address of the GCP account", + example: "user@example.com", + }), + privateKey: z.string().openapi({ + description: "The private key of the GCP account", + example: + "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/5/9+9/8/7/6/5/4/3/2/1/0\n...", + }), + type, +}); + +export const gcpAccountConfigSchema = z.object({ + projectId: z.string().openapi({ + description: "The project ID of the GCP account", + example: "123456789012", + }), + locationId: z.string().openapi({ + description: "The location ID of the GCP account", + example: "global", + }), + keyRingId: z.string().openapi({ + description: "The key ring ID of the GCP account", + example: "keyring-123456789012", + }), + type, +}); + +type GcpApiError = { + code?: number; + details?: string; + message?: string; + status?: string; +}; + +const isGcpApiError = (error: unknown): error is GcpApiError => { + return ( + typeof error === "object" && + error !== null && + ("code" in error || "status" in error) + ); +}; + +export const mapGcpError = ( + error: unknown, + code: GcpKmsErr["code"], + defaultMessage: string, +): GcpKmsErr => { + if (isGcpApiError(error)) { + const statusCode = error.code ?? 500; + + // Map GCP error codes to our error codes + const mappedCode: GcpKmsErr["code"] = + error.status === "PERMISSION_DENIED" + ? "unauthorized" + : error.status === "RESOURCE_EXHAUSTED" + ? "rate_limit_exceeded" + : error.status === "FAILED_PRECONDITION" + ? "invalid_key_state" + : code; + + return { + kind: "gcp_kms", + code: mappedCode, + status: statusCode, + message: error.message ?? defaultMessage, + source: error, + } as GcpKmsErr; + } + + return { + kind: "gcp_kms", + code, + status: 500, + message: error instanceof Error ? error.message : defaultMessage, + source: error instanceof Error ? error : undefined, + }; +}; + +export function provisionGcpKmsAccount({ + config, + credentials, + client: thirdwebClient, +}: { + params: z.infer; + config: z.infer; + credentials: z.infer; + client: ThirdwebClient; +}): ResultAsync< + { + account: Account; + platformIdentifiers: z.infer; + }, + GcpKmsErr +> { + return safeTry(async function* () { + const kmsClient = new KeyManagementServiceClient({ + credentials: { + client_email: credentials.email, + private_key: credentials.privateKey.split(String.raw`\n`).join("\n"), + }, + projectId: config.projectId, + }); + + const cryptoKeyId = `ec-web3api-${new Date().getTime()}`; + const keyResponse = yield* ResultAsync.fromPromise( + kmsClient.createCryptoKey({ + parent: kmsClient.keyRingPath( + config.projectId, + config.locationId, + config.keyRingId, + ), + cryptoKeyId, + cryptoKey: { + purpose: "ASYMMETRIC_SIGN", + versionTemplate: { + algorithm: "EC_SIGN_SECP256K1_SHA256", + protectionLevel: "HSM", + }, + }, + }), + (error) => + mapGcpError( + error, + "key_creation_failed", + "Failed to create GCP KMS key", + ), + ); + + const [key] = keyResponse; + + const resourcePath = getGcpKmsResourcePath({ + projectId: config.projectId, + locationId: config.locationId, + keyRingId: config.keyRingId, + cryptoKeyId, + versionId: "1", + }); + + if (`${key.name}/cryptoKeyVersions/1` !== resourcePath) { + return err({ + kind: "gcp_kms", + code: "key_creation_failed", + status: 500, + message: `Expected created key resource path to be ${resourcePath}, but got ${key.name}`, + } as GcpKmsErr); + } + + yield* ResultAsync.fromPromise(kmsClient.close(), (error) => + mapGcpError(error, "client_error", "Failed to close KMS client"), + ); + + const account = yield* getGcpKmsAccount({ + client: thirdwebClient, + respourcePath: resourcePath, + clientOptions: { + credentials: { + client_email: credentials.email, + private_key: credentials.privateKey, + }, + }, + }); + + return ok({ + account, + platformIdentifiers: { + type: "gcp-kms" as const, + gcpKmsResourcePath: resourcePath, + }, + }); + }); +} + +/** + * Split a GCP KMS resource path into its parts. + */ +export function splitGcpKmsResourcePath(resourcePath: string) { + const parts = resourcePath.split("/"); + + if (parts.length < 9) { + throw new Error("Invalid GCP KMS resource path"); + } + + const projectId = parts[1]; + const locationId = parts[3]; + const keyRingId = parts[5]; + const cryptoKeyId = parts[7]; + const versionId = parts[9]; + + if (!projectId || !locationId || !keyRingId || !cryptoKeyId || !versionId) { + throw new Error("Invalid GCP KMS resource path"); + } + + return { + projectId, + locationId, + keyRingId, + cryptoKeyId, + versionId, + }; +} + +/** + * Get a GCP KMS resource path from its parts. + */ +export function getGcpKmsResourcePath(options: { + locationId: string; + keyRingId: string; + cryptoKeyId: string; + versionId: string; + projectId: string; +}) { + return `projects/${options.projectId}/locations/${options.locationId}/keyRings/${options.keyRingId}/cryptoKeys/${options.cryptoKeyId}/cryptoKeyVersions/${options.versionId}`; +} diff --git a/src/lib/accounts/gcp/get-gcp-account.ts b/src/lib/accounts/gcp/get-gcp-account.ts new file mode 100644 index 000000000..aeaab09a3 --- /dev/null +++ b/src/lib/accounts/gcp/get-gcp-account.ts @@ -0,0 +1,162 @@ +import { + eth_sendRawTransaction, + getAddress, + getRpcClient, + keccak256, + serializeTransaction, + type Hex, + type ThirdwebClient, +} from "thirdweb"; +import type { Account } from "thirdweb/wallets"; +import type { GcpKmsErr, RpcErr } from "../../errors.js"; +import { ok, ResultAsync, safeTry } from "neverthrow"; +import { CloudKmsSigner } from "@cloud-cryptographic-wallet/cloud-kms-signer"; +import { mapGcpError } from "./gcp.js"; +import type { + SendTransactionOptions, + SendTransactionResult, + SignTransactionOptions, +} from "../transaction-types.js"; +import { Bytes } from "@cloud-cryptographic-wallet/signer"; +import { getChain } from "../../chain.js"; +import type { SignableMessage } from "viem"; +import { hashMessage } from "thirdweb/utils"; +import type { TypedData } from "ox"; +import { getSignPayload } from "ox/TypedData"; + +export function getGcpKmsAccount({ + respourcePath: unprocessedName, + clientOptions, + client, +}: { + respourcePath: string; + clientOptions: { + credentials: { + client_email: string; + private_key: string; + }; + }; + client: ThirdwebClient; +}): ResultAsync { + return safeTry(async function* () { + clientOptions.credentials.private_key = + clientOptions.credentials.private_key.split(String.raw`\n`).join("\n"); + + const resourcePath = unprocessedName.includes("cryptoKeyVersions") + ? unprocessedName + : unprocessedName.replace("cryptoKeysVersion", "cryptoKeyVersions"); + + const signer = new CloudKmsSigner(resourcePath, clientOptions); + + // Get address + const publicKey = yield* ResultAsync.fromPromise( + signer.getPublicKey(), + (error) => + mapGcpError( + error, + "address_retrieval_failed", + "Failed to get public key", + ), + ); + + const address = getAddress(publicKey.toAddress().toString()); + + async function signTransaction(tx: SignTransactionOptions): Promise { + try { + const serializedTx = serializeTransaction({ transaction: tx }); + const txHash = keccak256(serializedTx); + const signature = await signer.sign(Bytes.fromString(txHash.slice(2))); + + const r = signature.r.toString() as Hex; + const s = signature.s.toString() as Hex; + const v = BigInt(signature.v); + const yParity: 0 | 1 = signature.v % 2 === 0 ? 1 : 0; + + return serializeTransaction({ + transaction: tx, + signature: { r, s, v, yParity }, + }); + } catch (error) { + throw mapGcpError( + error, + "signature_failed", + "Could not sign transaction", + ); + } + } + + async function sendTransaction( + tx: SendTransactionOptions, + ): SendTransactionResult { + let signature: Hex; + try { + signature = await signTransaction(tx); + } catch (error) { + // signTransaction only throws a gcpErr, safe to throw + // biome-ignore lint/complexity/noUselessCatch: readability + throw error; + } + + const rpcRequest = getRpcClient({ + client: client, + chain: await getChain(tx.chainId), + }); + + try { + const transactionHash = await eth_sendRawTransaction( + rpcRequest, + signature, + ); + return { transactionHash }; + } catch (error) { + throw { + kind: "rpc", + code: "send_transaction_failed", + status: 500, + message: + error instanceof Error ? error.message : "RPC request failed", + source: error instanceof Error ? error : undefined, + } as RpcErr; + } + } + + async function signMessage({ + message, + }: { + message: SignableMessage; + }): Promise { + try { + const messageHash = hashMessage(message); + const signature = await signer.sign(Bytes.fromString(messageHash)); + return signature.bytes.toString() as Hex; + } catch (error) { + throw mapGcpError(error, "signature_failed", "Could not sign message"); + } + } + + async function signTypedData< + const typedData extends TypedData.TypedData | Record, + primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, + >(_typedData: TypedData.Definition): Promise { + try { + const typedDataHash = getSignPayload(_typedData); + const signature = await signer.sign(Bytes.fromString(typedDataHash)); + return signature.bytes.toString() as Hex; + } catch (error) { + throw mapGcpError( + error, + "signature_failed", + "Could not sign typed data", + ); + } + } + + return ok({ + address, + sendTransaction, + signMessage, + signTypedData: signTypedData as Account["signTypedData"], + signTransaction, + } satisfies Account); + }); +} diff --git a/src/lib/accounts/local.ts b/src/lib/accounts/local.ts new file mode 100644 index 000000000..2bbd2fa56 --- /dev/null +++ b/src/lib/accounts/local.ts @@ -0,0 +1,83 @@ +import { privateKeyToAccount, randomPrivateKey } from "thirdweb/wallets"; +import { thirdwebClient } from "../thirdweb-client.js"; +import { env } from "../env.js"; +import { decryptKeystore, generateKeystore } from "../keystore.js"; +import { Result } from "neverthrow"; +import type { LocalAccountErr } from "../errors.js"; +import * as z from "zod"; +import { baseAccountCreateSchema } from "./base-schemas.js"; + +const type = z.literal("local"); + +export const localPlatformIdentifiersSchema = z.object({ + platformIdentifiers: z.null(), + type, +}); + +export const localAccountCreateParamsSchema = z + .object({ + type, + // encryptionPassword: z.string().optional().openapi({ + // description: + // "The encryption password used to encrypt the account. This is unrecoverable, and should be kept secret. IF YOU LOSE THIS PASSWORD, YOU WILL LOSE ACCESS TO YOUR ACCOUNT. If omitted, your account will be encrypted with the default encryption password. This is only valid for local accounts.", + // }), + }) + .merge(baseAccountCreateSchema); + +/** + * Create a local wallet with a random private key + * Does not store the wallet in the database + */ +export function provisionLocalAccount( + _params: Omit, "label">, +) { + const pk = randomPrivateKey(); + + const account = privateKeyToAccount({ + client: thirdwebClient, + privateKey: pk, + }); + + return Result.fromThrowable( + () => + generateKeystore( + pk, + // params.encryptionPassword ?? + env.ENCRYPTION_PASSWORD, + ), + (error): LocalAccountErr => ({ + kind: "local_account", + code: "account_creation_failed", + message: error instanceof Error ? error.message : undefined, + status: 500, + source: error instanceof Error ? error : undefined, + }), + )().map((encryptedJsonData) => ({ + account, + encryptedJson: JSON.stringify(encryptedJsonData), + })); +} + +export function encryptedJsonToAccount({ + json, + encryptionPassword = env.ENCRYPTION_PASSWORD, +}: { + json: string; + encryptionPassword?: string; +}) { + return Result.fromThrowable( + () => decryptKeystore(JSON.parse(json), encryptionPassword), + (error): LocalAccountErr => ({ + kind: "local_account", + code: "account_decryption_failed", + message: error instanceof Error ? error.message : undefined, + status: 500, + source: error instanceof Error ? error : undefined, + }), + )().map((privateKey) => + privateKeyToAccount({ + client: thirdwebClient, + privateKey, + }), + ); +} diff --git a/src/lib/accounts/smart.ts b/src/lib/accounts/smart.ts new file mode 100644 index 000000000..54313039b --- /dev/null +++ b/src/lib/accounts/smart.ts @@ -0,0 +1,60 @@ +import { defineChain, type Address, type Chain } from "thirdweb"; +import { smartWallet, type Account } from "thirdweb/wallets"; +import { thirdwebClient } from "../thirdweb-client.js"; +import { Result, ResultAsync } from "neverthrow"; +import type { RpcErr, SmartAccountErr } from "../errors.js"; + +/** + * Get a smart account for a given admin account + * Optionally specify the account factory address, and entrypoint address + * If no network is specified, it will default to ethereum mainnet + */ +export function getSmartAccount({ + adminAccount, + accountSalt, + accountFactoryAddress, + entrypointAddress, + chain, +}: { + adminAccount: Account; + accountSalt?: string; + accountFactoryAddress?: Address; + entrypointAddress?: Address; + chain?: Chain; +}) { + return Result.fromThrowable( + () => + smartWallet({ + chain: chain ?? defineChain(1), + sponsorGas: true, + factoryAddress: accountFactoryAddress, + overrides: { + entrypointAddress, + accountSalt, + }, + }), + (error) => + ({ + code: "smart_account_validation_failed", + kind: "smart_account", + message: "Unable to sync initialise smart account", + status: 500, + source: error, + } as SmartAccountErr), + )().asyncAndThen((smartAccount) => + ResultAsync.fromPromise( + smartAccount.connect({ + client: thirdwebClient, + personalAccount: adminAccount, + }), + (error) => + ({ + code: "smart_account_determination_failed", + kind: "rpc", + message: "Unable to determine smart account address", + status: 500, + source: error, + } as RpcErr), + ), + ); +} diff --git a/src/lib/accounts/transaction-types.ts b/src/lib/accounts/transaction-types.ts new file mode 100644 index 000000000..fc6930102 --- /dev/null +++ b/src/lib/accounts/transaction-types.ts @@ -0,0 +1,11 @@ +import type { Account } from "thirdweb/wallets"; + +export type SendTransaction = Account["sendTransaction"]; +export type SendTransactionOptions = Parameters[0]; + +export type SignTransaction = Account["signTransaction"]; +export type SignTransactionOptions = Parameters< + NonNullable +>[0]; + +export type SendTransactionResult = ReturnType; diff --git a/src/lib/accounts/vault/get-vault-account.ts b/src/lib/accounts/vault/get-vault-account.ts new file mode 100644 index 000000000..929c6f0cd --- /dev/null +++ b/src/lib/accounts/vault/get-vault-account.ts @@ -0,0 +1,402 @@ +import { bytesToHex } from "@noble/hashes/utils"; +import type { + TypedData, + TypedDataDomain, + TypedDataToPrimitiveTypes, +} from "abitype"; +import { HTTPError } from "ky"; +import { Result, ResultAsync } from "neverthrow"; +import { + type Address, + eth_sendRawTransaction, + getRpcClient, + type Hex, + type ThirdwebClient, +} from "thirdweb"; +import type { Account } from "thirdweb/wallets"; +import type { SignableMessage } from "viem"; +import { getChain } from "../../chain.js"; +import type { BaseErr, RpcErr } from "../../errors.js"; +import { + type VaultClient, + signMessage as vault_signMessage, + signStructuredMessage as vault_signStructuredMessage, + signTransaction as vault_signTransaction, + signTypedData as vault_signTypedData, +} from "../../vault-sdk/sdk.js"; +import { parseTransaction as vault_parseTransaction } from "../../vault-sdk/transaction-parser.js"; +import type { + StructuredMessageInput, + UserOperationV06Input, + UserOperationV07Input, + Auth as VaultAuth, + VaultError, +} from "../../vault-sdk/types.js"; +import type { + SendTransactionOptions, + SignTransactionOptions, +} from "../transaction-types.js"; + +export type VaultAccountOptions = { + thirdwebClient: ThirdwebClient; + vaultClient: VaultClient; + address: Address; + auth: VaultAuth; +}; + +export function getVaultAccount(options: VaultAccountOptions): Account { + const { vaultClient, thirdwebClient, address, auth } = options; + async function signTransaction(tx: SignTransactionOptions) { + // Use Result.fromThrowable for synchronous operation + const parseResult = Result.fromThrowable( + () => vault_parseTransaction(tx), + (e) => + createVaultError( + e, + address, + "signTransaction", + "transaction_parse_failed", + 500, + ), + )(); + + if (parseResult.isErr()) { + throw parseResult.error; + } + + const typedTransaction = parseResult.value; + + const signResult = await ResultAsync.fromPromise( + vault_signTransaction({ + client: vaultClient, + request: { + auth, + options: { + from: address, + transaction: typedTransaction, + }, + }, + }), + (e) => createVaultError(e, address, "signTransaction"), + ); + + if (signResult.isErr()) { + throw signResult.error; + } + + const result = signResult.value; + + if (result.error) { + throw handleVaultResponseError(result.error, address, "signTransaction"); + } + + return result.data.signature as Hex; + } + + async function signTypedData< + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, + >(typedData: { + domain: TypedDataDomain; + types: Types; + primaryType: PrimaryType; + message: TypedDataToPrimitiveTypes[PrimaryType]; + }) { + const signResult = await ResultAsync.fromPromise( + vault_signTypedData({ + client: vaultClient, + request: { + auth, + options: { + from: address, + typedData: { + domain: typedData.domain, + types: typedData.types, + primaryType: typedData.primaryType, + message: typedData.message, + }, + }, + }, + }), + (e) => createVaultError(e, address, "signTypedData"), + ); + + if (signResult.isErr()) { + throw signResult.error; + } + + const result = signResult.value; + + if (result.error) { + throw handleVaultResponseError(result.error, address, "signTypedData"); + } + + return result.data.signature as Hex; + } + + async function sendTransaction(tx: SendTransactionOptions) { + const signature = await signTransaction(tx); + + const rpcRequest = getRpcClient({ + client: thirdwebClient, + chain: getChain(tx.chainId), + }); + + try { + const transactionHash = await eth_sendRawTransaction( + rpcRequest, + signature, + ); + return { transactionHash }; + } catch (error) { + throw { + kind: "rpc", + code: "send_transaction_failed", + status: 500, + message: error instanceof Error ? error.message : "RPC request failed", + source: error instanceof Error ? error : undefined, + } as RpcErr; + } + } + + async function signMessage({ + message, + chainId, + originalMessage, + }: { + message: SignableMessage; + originalMessage?: string; + chainId?: number; + }) { + let finalMessage: string; + let messageFormat: "text" | "hex" = "text"; + + if (typeof message === "string") { + finalMessage = message; + } else if (typeof message.raw === "string") { + finalMessage = message.raw; + messageFormat = "hex"; + } else { + finalMessage = bytesToHex(message.raw); + messageFormat = "hex"; + } + + // Handle structured message if originalMessage is provided + if (originalMessage) { + // Use Result.fromThrowable to safely parse JSON + const parseResult = Result.fromThrowable( + () => JSON.parse(originalMessage), + (e) => + createVaultError( + e, + address, + "signMessage", + "serialization_error", + 400, + ), + )(); + + // Only proceed with UserOp detection if parsing succeeded + if (parseResult.isOk()) { + const parsedMessage = parseResult.value; + + // Basic check that this might be a UserOp (minimal required fields) + const looksLikeUserOp = + parsedMessage?.sender && + parsedMessage?.nonce && + parsedMessage?.callData && + parsedMessage?.callGasLimit && + parsedMessage?.verificationGasLimit && + parsedMessage?.maxFeePerGas; + + if (looksLikeUserOp) { + // Check for version-specific fields + const hasV06OnlyFields = "paymasterAndData" in parsedMessage; + const hasV07OnlyFields = + "paymasterData" in parsedMessage || "paymaster" in parsedMessage; + + let structuredMessage: StructuredMessageInput; + + // Prioritize explicit v0.7 indicators, fall back to v0.6 only if clear + if (hasV07OnlyFields || !hasV06OnlyFields) { + structuredMessage = { + useropV07: parsedMessage as UserOperationV07Input, + }; + } else { + structuredMessage = { + useropV06: parsedMessage as UserOperationV06Input, + }; + } + + // Use ResultAsync for the async operation + const signResult = await ResultAsync.fromPromise( + vault_signStructuredMessage({ + client: vaultClient, + request: { + auth, + options: { + from: address, + structuredMessage, + chainId, + }, + }, + }), + (e) => + createVaultError( + e, + address, + "signMessage", + "protocol_error", + 500, + ), + ); + + if (signResult.isErr()) { + throw signResult.error; + } + + const result = signResult.value; + + if (result.error) { + throw handleVaultResponseError( + result.error, + address, + "signMessage", + ); + } + + // Check if message matches + if (result.data.message !== `0x${finalMessage}`) { + throw createVaultError( + new Error( + "[VAULT ERROR] Received message does not match original message", + ), + address, + "signMessage", + "invalid_input", + 400, + ); + } + + return result.data.signature as Hex; + } + } + // If parsing failed or it's not a UserOp, continue with normal signing + // No need to log anything here, the error is already captured in parseResult if needed + } + + // Original signMessage code for regular signing + const signResult = await ResultAsync.fromPromise( + vault_signMessage({ + client: vaultClient, + request: { + auth, + options: { + from: address, + message: finalMessage, + format: messageFormat, + chainId, + }, + }, + }), + (e) => createVaultError(e, address, "signMessage", "protocol_error", 500), + ); + + if (signResult.isErr()) { + throw signResult.error; + } + + const result = signResult.value; + + if (result.error) { + throw handleVaultResponseError(result.error, address, "signMessage"); + } + + return result.data.signature as Hex; + } + + // signAuthorization: async (authorization: AuthorizationRequest) => { + // const signature = ox__Secp256k1.sign({ + // payload: ox__Authorization.getSignPayload(authorization), + // privateKey: privateKey, + // }); + // return ox__Authorization.from(authorization, { signature }); + // }, + + return { + address, + signTypedData: signTypedData as Account["signTypedData"], + sendTransaction, + signTransaction, + signMessage, + } satisfies Account; +} + +export type VaultKmsErr = BaseErr & { + kind: "vault_kms"; + code: + | "auth_unsupported_operation" + | "auth_insufficient_scope" + | "auth_invalid_admin_key" + | "internal_server_error" + | "serialization_error" + | "invalid_input" + | "protocol_error" // we use this for all UnencryptedErrors + | "unreachable" // we use this for all thrown errors + | "transaction_parse_failed"; // new code for transaction parsing failures + message: string; + status?: number; + details?: string; + address: Address; + operation: "signMessage" | "signTransaction" | "signTypedData"; +}; + +// Helper function to create a standard VaultKmsErr from any error +function createVaultError( + e: unknown, + address: Address, + operation: VaultKmsErr["operation"], + code: VaultKmsErr["code"] = "unreachable", + status: BaseErr["status"] = 500, +): VaultKmsErr { + if (e instanceof HTTPError) { + return { + address, + code: "unreachable", + message: e.message, + source: e, + kind: "vault_kms", + operation, + status: 500, + }; + } + + return { + address, + code, + message: + e instanceof Error ? e.message : `Unexpected error during ${operation}`, + source: e instanceof Error ? e : undefined, + kind: "vault_kms", + operation, + status, + }; +} + +// Helper function to handle vault API response errors +function handleVaultResponseError( + error: VaultError, + address: Address, + operation: VaultKmsErr["operation"], +): VaultKmsErr { + return { + address, + code: + "code" in error ? (error.code as VaultKmsErr["code"]) : "protocol_error", + message: error.message, + status: "status" in error ? (error.status as VaultKmsErr["status"]) : 400, + kind: "vault_kms", + operation, + details: error.details, + }; +} diff --git a/src/lib/admin-account.ts b/src/lib/admin-account.ts new file mode 100644 index 000000000..36b996848 --- /dev/null +++ b/src/lib/admin-account.ts @@ -0,0 +1,6 @@ +import { encryptedJsonToAccount } from "./accounts/local.js"; +import { config } from "./config.js"; + +export const adminAccount = encryptedJsonToAccount({ + json: config.authEoaEncryptedJson, +})._unsafeUnwrap(); diff --git a/src/lib/cache.ts b/src/lib/cache.ts new file mode 100644 index 000000000..d5fb6821d --- /dev/null +++ b/src/lib/cache.ts @@ -0,0 +1,23 @@ +import cron from "node-cron"; +import { config, refreshConfig } from "./config.js"; + +function secondsToCron(seconds: number) { + return `*/${Math.floor(seconds / 60)} * * * *`; +} + +let task: cron.ScheduledTask | undefined = undefined; + +export async function initiateCacheClearTask() { + const cacheClearRegistry = [refreshConfig]; + + if (task) { + task.stop(); + } + + task = cron.schedule( + secondsToCron(config.cacheClearIntervalSeconds), + async () => { + await Promise.all(cacheClearRegistry.map((fn) => fn())); + }, + ); +} diff --git a/src/lib/chain.ts b/src/lib/chain.ts new file mode 100644 index 000000000..d4cc7f1bb --- /dev/null +++ b/src/lib/chain.ts @@ -0,0 +1,35 @@ +import { defineChain, type Chain } from "thirdweb"; +import { config } from "./config.js"; +import { Result } from "neverthrow"; +import type { ValidationErr } from "./errors.js"; + +/** + * Get the chain for thirdweb v5 SDK. Supports chain overrides. + * @param chainId + * @returns Chain + */ +export const getChain = (chainId: number): Chain => { + for (const override of config.chainOverrides) { + if (chainId === override.id) { + // we need to call defineChain to ensure that the chain is registered in CUSTOM_CHAIN_MAP + // even if we have a Chain type, we need to call defineChain to ensure that the chain is registered + return defineChain(override); + } + } + + return defineChain(chainId); +}; + +export const getChainResult = Result.fromThrowable( + (chainId: string) => { + const chainIdNumber = Number.parseInt(chainId); + return getChain(chainIdNumber); + }, + () => + ({ + code: "parse_error", + kind: "validation", + status: 400, + message: `Invalid chain ID: could not parse to number`, + }) satisfies ValidationErr as ValidationErr, +); diff --git a/src/lib/config.ts b/src/lib/config.ts new file mode 100644 index 000000000..5154490ee --- /dev/null +++ b/src/lib/config.ts @@ -0,0 +1,141 @@ +import { eq } from "drizzle-orm"; +import { ResultAsync, err, ok, safeTry } from "neverthrow"; +import * as z from "zod"; +import { db } from "../db/connection.js"; +import { configuration } from "../db/schema.js"; +import type { ConfigInDb } from "../db/types.js"; +import { provisionLocalAccount } from "./accounts/local.js"; +import { decrypt } from "./crypto.js"; +import { + type ConfigErr, + type CryptoErr, + type DbErr, + type LocalAccountErr, + type ValidationErr, + mapDbError, + mapZodError, +} from "./errors.js"; +import { initializeLogger } from "./logger.js"; +import { redis } from "./redis.js"; + +const configLogger = initializeLogger("config"); + +export const configInRedisSchema = z.object({ + cacheClearIntervalSeconds: z.coerce.number().default(60 * 5), +}); + +type ConfigInRedis = z.infer; +type DecryptedConfig = { + mtlsCertificate: string | undefined; + mtlsPrivateKey: string | undefined; +}; +export type EngineConfig = ConfigInDb & + ConfigInRedis & { + decrypted: DecryptedConfig; + }; + +export let config = (await fetchConfig())._unsafeUnwrap(); + +export function getConfigInRedis(): ResultAsync< + ConfigInRedis, + ConfigErr | ValidationErr +> { + return ResultAsync.fromPromise( + redis.get("config"), + (): ConfigErr => + ({ + kind: "config", + code: "redis_error", + status: 500, + }) as const, + ).andThen((configStr) => { + const configParsed = + typeof configStr === "string" ? JSON.parse(configStr) : {}; + + return ResultAsync.fromPromise( + Promise.resolve(configInRedisSchema.parse(configParsed)), + mapZodError, + ); + }); +} + +export function getConfigInDb(): ResultAsync< + ConfigInDb, + DbErr | ConfigErr | LocalAccountErr +> { + return ResultAsync.fromPromise( + db.query.configuration.findFirst({ + where: eq(configuration.id, "default"), + }), + mapDbError, + ).andThen((config) => { + if (config) return ok(config); + + configLogger.info("No existing default config, writing new config"); + return provisionLocalAccount({ type: "local" }) + .asyncAndThen(({ account: _authAccount, encryptedJson }) => + ResultAsync.fromPromise( + db + .insert(configuration) + .values({ + authEoaEncryptedJson: encryptedJson, + }) + .onConflictDoNothing() + .returning(), + mapDbError, + ), + ) + .andThen(([result]) => + result + ? ok(result) + : err({ + kind: "config", + code: "config_creation_failed", + status: 500, + message: "Failed to insert configuration", + } as const), + ) + .andTee(() => { + configLogger.info("Successfully wrote new config"); + }); + }); +} + +export function fetchConfig(): ResultAsync< + EngineConfig, + DbErr | ConfigErr | ValidationErr | CryptoErr | LocalAccountErr +> { + return ResultAsync.combine([getConfigInRedis(), getConfigInDb()]) + .map(([redisConfig, dbConfig]) => ({ + ...dbConfig, + ...redisConfig, + })) + .andThen((config) => + safeTry(async function* () { + const mtlsCertificate = config.mtlsCertificateEncrypted + ? yield* decrypt(config.mtlsCertificateEncrypted) + : undefined; + + const mtlsPrivateKey = config.mtlsPrivateKeyEncrypted + ? yield* decrypt(config.mtlsPrivateKeyEncrypted) + : undefined; + + return ok({ + ...config, + decrypted: { + mtlsCertificate, + mtlsPrivateKey, + }, + }); + }), + ); +} + +export function refreshConfig(): ResultAsync< + EngineConfig, + DbErr | ConfigErr | ValidationErr | CryptoErr | LocalAccountErr +> { + return fetchConfig().andTee((newConfig) => { + config = newConfig; + }); +} diff --git a/src/lib/crypto.ts b/src/lib/crypto.ts new file mode 100644 index 000000000..ae74d6f95 --- /dev/null +++ b/src/lib/crypto.ts @@ -0,0 +1,102 @@ +import { createPublicKey, pbkdf2Sync, randomBytes } from "node:crypto"; +import { CompactEncrypt, compactDecrypt } from "jose"; +import { type Result, ResultAsync, err, errAsync, ok } from "neverthrow"; +import { env } from "./env.js"; +import type { CryptoErr } from "./errors.js"; + +const ITERATIONS = 100000; +const KEY_LENGTH = 32; +const SALT_LENGTH = 16; + +interface EncryptedData { + salt: string; + data: string; +} + +function deriveKey(password: string, salt: Buffer): Result { + try { + return ok(pbkdf2Sync(password, salt, ITERATIONS, KEY_LENGTH, "sha256")); + } catch (error) { + return err({ + kind: "crypto", + code: "key_derivation_failed", + status: 500, + source: error instanceof Error ? error : undefined, + }); + } +} + +export function encrypt(data: string): ResultAsync { + const salt = randomBytes(SALT_LENGTH); + + return deriveKey(env.ENCRYPTION_PASSWORD, salt) + .asyncAndThen((key) => + ResultAsync.fromPromise( + new CompactEncrypt(new TextEncoder().encode(data)) + .setProtectedHeader({ alg: "dir", enc: "A256GCM" }) + .encrypt(key), + (error): CryptoErr => ({ + kind: "crypto", + code: "encryption_failed", + status: 500, + message: "JWE encryption failed", + source: error instanceof Error ? error : undefined, + }), + ), + ) + .map((jwe) => { + const result: EncryptedData = { + salt: salt.toString("base64"), + data: jwe, + }; + return JSON.stringify(result); + }); +} + +export function decrypt(encrypted: string): ResultAsync { + let parsed: EncryptedData; + try { + parsed = JSON.parse(encrypted) as EncryptedData; + } catch (error) { + return errAsync({ + kind: "crypto", + code: "invalid_format_not_json", + status: 500, + message: "Invalid encrypted data format, could not parse JSON", + source: error instanceof Error ? error : undefined, + }); + } + + const saltBuffer = Buffer.from(parsed.salt, "base64"); + + return deriveKey(env.ENCRYPTION_PASSWORD, saltBuffer) + .asyncAndThen((key) => + ResultAsync.fromPromise( + compactDecrypt(parsed.data, key), + (error): CryptoErr => ({ + kind: "crypto", + code: "decryption_failed", + status: 500, + message: "JWE decryption failed", + source: error instanceof Error ? error : undefined, + }), + ), + ) + .map(({ plaintext }) => new TextDecoder().decode(plaintext)); +} +export function legacyEncrypt(data: string): string { + return CryptoJS.AES.encrypt(data, env.ENCRYPTION_PASSWORD).toString(); +} + +export function legacyDecryptWith(data: string, password: string) { + return CryptoJS.AES.decrypt(data, password).toString(CryptoJS.enc.Utf8); +} + +export function isWellFormedPublicKey(key: string) { + try { + createPublicKey(key); + return true; + } catch (_e) { + return false; + } +} diff --git a/src/tracer.ts b/src/lib/datadog.ts similarity index 79% rename from src/tracer.ts rename to src/lib/datadog.ts index 4aae137e3..8d1eff372 100644 --- a/src/tracer.ts +++ b/src/lib/datadog.ts @@ -1,5 +1,5 @@ import tracer from "dd-trace"; -import { env } from "./shared/utils/env"; +import { env } from "./env.js"; if (env.DD_TRACER_ACTIVATED) { tracer.init(); // initialized in a different file to avoid hoisting. diff --git a/src/lib/env.ts b/src/lib/env.ts new file mode 100644 index 000000000..b97aae477 --- /dev/null +++ b/src/lib/env.ts @@ -0,0 +1,92 @@ +import * as z from "zod"; + +const boolEnvSchema = (defaultBool: boolean) => + z + .string() + .default(defaultBool ? "true" : "false") + .refine((s) => s === "true" || s === "false", "must be 'true' or 'false'") + .transform((s) => s === "true"); + +export const UrlSchema = z + .string() + .refine( + (value) => value.startsWith("http://") || value.startsWith("https://"), + { message: "Invalid URL" }, + ); + +const envSchema = z.object({ + NODE_ENV: z + .enum(["production", "development", "test", "local"]) + .default("development"), + LOG_LEVEL: z + .enum(["error", "warn", "info", "http", "debug", "silly"]) + .default("http"), + ENGINE_VERSION: z.string().optional(), + ENGINE_TIER: z.string().optional(), + THIRDWEB_API_SECRET_KEY: z.string().min(1), + ENCRYPTION_PASSWORD: z.string().min(1), + VAULT_URL: z.string().url(), + POSTGRES_CONNECTION_URL: z + .string() + .default( + "postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable", + ), + PORT: z.coerce.number().default(3005), + HOST: z.string().default("0.0.0.0"), + ENABLE_HTTPS: boolEnvSchema(false), + HTTPS_PASSPHRASE: z.string().default("thirdweb-engine"), + TRUST_PROXY: boolEnvSchema(false), + CLIENT_ANALYTICS_URL: z + .union([UrlSchema, z.literal("")]) + .default("https://c.thirdweb.com/event"), + SDK_BATCH_TIME_LIMIT: z.coerce.number().default(0), + SDK_BATCH_SIZE_LIMIT: z.coerce.number().default(100), + REDIS_URL: z.string(), + SEND_TRANSACTION_QUEUE_CONCURRENCY: z.coerce.number().default(1000), + CONFIRM_TRANSACTION_QUEUE_CONCURRENCY: z.coerce.number().default(1000), + SEND_TRANSACTION_WORKER_CONCURRENCY: z.coerce.number().default(200), + CONFIRM_TRANSACTION_WORKER_CONCURRENCY: z.coerce.number().default(200), + ENGINE_MODE: z + .enum(["default", "sandbox", "server_only", "worker_only"]) + .default("default"), + GLOBAL_RATE_LIMIT_PER_MIN: z.coerce.number().default(400 * 60), + DD_TRACER_ACTIVATED: boolEnvSchema(false), + FORCE_DB_MIGRATION: boolEnvSchema(false), + // Prometheus + METRICS_PORT: z.coerce.number().default(4001), + METRICS_ENABLED: boolEnvSchema(true), + + /** + * Limits + */ + // Sets the max amount of memory Redis can use. + // "0" means use all available memory. + REDIS_MAXMEMORY: z.string().default("0"), + // Sets the number of recent transactions to store. Older transactions are pruned periodically. + // In testing, 100k transactions consumes ~300mb memory. + TRANSACTION_HISTORY_COUNT: z.coerce.number().default(100_000), + // Sets the number of recent completed jobs in each queue. + QUEUE_COMPLETE_HISTORY_COUNT: z.coerce.number().default(2_000), + // Sets the number of recent failed jobs in each queue. + // These limits are higher to debug failed jobs. + QUEUE_FAIL_HISTORY_COUNT: z.coerce.number().default(10_000), + // Sets the number of recent nonces to map to queue IDs. + NONCE_MAP_COUNT: z.coerce.number().default(10_000), + + ENABLE_KEYPAIR_AUTH: boolEnvSchema(false), + ENABLE_CUSTOM_HMAC_AUTH: boolEnvSchema(false), + CUSTOM_HMAC_AUTH_CLIENT_ID: z.string().optional(), + CUSTOM_HMAC_AUTH_CLIENT_SECRET: z.string().optional(), +}); + +const { data: parsedEnv, error } = envSchema.safeParse(process.env); + +if (error) { + console.error( + "❌ Invalid environment variables:", + error.flatten().fieldErrors, + ); + throw new Error("Invalid environment variables"); +} + +export const env = parsedEnv; diff --git a/src/lib/errors.ts b/src/lib/errors.ts new file mode 100644 index 000000000..a557db30f --- /dev/null +++ b/src/lib/errors.ts @@ -0,0 +1,716 @@ +import type { Hook } from "@hono/zod-validator"; +import type { Env } from "hono"; +import { HTTPException } from "hono/http-exception"; +import type { Address, Hex } from "thirdweb"; +import { ZodError } from "zod"; +import type { + ExecutionParamsSerialized, + ExecutionResultSerialized, +} from "../db/types.js"; +import type { QueueingErr as BundlerExecutorAsyncQueueingErr } from "../executors/external-bundler-async/index.js"; +import type { VaultKmsErr } from "./accounts/vault/get-vault-account.js"; + +export type HttpErrStatusCode = 400 | 401 | 403 | 404 | 500 | 501; + +export type BaseErr = { + message?: string; + status: HttpErrStatusCode; + source?: Error; +}; + +export type AuthErr = BaseErr & { + kind: "auth"; + code: + | "missing_auth_header" + | "malformed_auth_header" + | "invalid_jwt" + | "expired_jwt" + | "invalid_signature" + | "insufficient_permissions" + | "invalid_keypair" + | "invalid_body_hash" + | "webhook_auth_failed"; +}; + +export type AccessTokenErr = BaseErr & { + kind: "access_token"; + code: "token_not_found" | "token_revoked" | "insufficient_permissions"; +}; + +export type KeypairErr = BaseErr & { + kind: "keypair"; + code: "missing_identifier" | "keypair_not_found"; +}; + +export type PermissionsErr = BaseErr & { + kind: "permissions"; + code: "insufficient_permissions" | "no_permissions"; +}; + +export type DbErr = BaseErr & + ( + | { + kind: "database"; + code: "query_failed" | "invalid_id_format"; + } + | { + kind: "database"; + code: "transaction_db_entry_failed"; + status: 500; + executionParams: ExecutionParamsSerialized; + executionResult: ExecutionResultSerialized; + } + ); + +export function buildTransactionDbEntryErr({ + error, + executionParams, + executionResult, +}: { + error: DbErr; + executionParams: ExecutionParamsSerialized; + executionResult: ExecutionResultSerialized; +}) { + return { + kind: "database", + code: "transaction_db_entry_failed", + message: + "Your transaction was sent sucessfully but engine was unable to store transaction details. Please do not resend this transaction to prevent double spending.", + status: 500, + source: error.source, + executionParams, + executionResult, + } as DbErr; +} + +export type ValidationErr = BaseErr & { + kind: "validation"; + code: + | "invalid_address" + | "parse_error" + | "filter_error" + | "invalid_contract_details" + | "invalid_chain" + | "transaction_simulation_failed"; + chainId?: string; + contractAddress?: Address; +}; + +export type WebhookErr = BaseErr & { + kind: "webhook"; + code: "request_failed"; + status: number; +}; + +export type ConfigErr = BaseErr & { + kind: "config"; + code: "redis_error" | "account_generation_failed" | "config_creation_failed"; +}; + +export type LocalAccountErr = BaseErr & { + kind: "local_account"; + code: "account_creation_failed" | "account_decryption_failed"; +}; + +export type CryptoErr = { + kind: "crypto"; + code: + | "encryption_failed" + | "decryption_failed" + | "invalid_format_not_json" + | "key_derivation_failed"; +} & BaseErr; + +export type RpcErr = { + kind: "rpc"; + chainId?: string; + address?: Address; + transactionHash?: Hex; + code: + | "smart_account_determination_failed" + | "send_transaction_failed" + | "sign_transaction_failed" + | "sign_message_failed" + | "sign_typed_data_failed" + | "sign_userop_failed" + | "bundle_userop_failed" + | "get_transaction_count_failed" + | "get_userop_receipt_failed" + | "serialize_transaction_failed" + | "get_transaction_receipt_failed" + | "get_balance_failed" + | "resolve_method_failed" + | "encode_transaction_failed" + | "read_contract_failed" + | "chain_determination_failed"; +} & BaseErr; + +export type SmartAccountErr = { + kind: "smart_account"; + code: "smart_account_validation_failed"; +} & BaseErr; + +export type AccountErr = { + kind: "account"; + address?: Address; + code: + | "account_not_found" + | "account_deletion_failed" + | "could_not_disambiguate" + | "invalid_platform_identifiers"; +} & BaseErr; + +export type CircleErr = BaseErr & { + kind: "circle"; + code: + | "wallet_set_creation_failed" + | "wallet_provisioning_failed" + | "wallet_retrieval_failed" + | "invalid_wallet_set" + | "rate_limit_exceeded" + | "unauthorized" + | "service_unavailable" + | "signature_failed"; +}; + +export type AwsKmsErr = BaseErr & { + kind: "aws_kms"; + code: + | "unauthorized" + | "rate_limit_exceeded" + | "invalid_key_state" + | "key_creation_failed" + | "address_retrieval_failed" + | "signature_failed"; + message: string; + cause?: unknown; +}; + +export type GcpKmsErr = BaseErr & { + kind: "gcp_kms"; + code: + | "unauthorized" + | "rate_limit_exceeded" + | "invalid_key_state" + | "key_creation_failed" + | "client_error" + | "address_retrieval_failed" + | "signature_failed"; +}; + +export type WalletProviderConfigErr = BaseErr & { + kind: "wallet_provider_config"; + code: + | "missing_aws_kms_config" + | "missing_gcp_kms_config" + | "missing_circle_config"; +}; + +export type EoaCredentialErr = BaseErr & { + kind: "eoa_credential"; + code: "credential_not_found"; +}; + +export type EngineErr = + | AuthErr + | DbErr + | ValidationErr + | AccessTokenErr + | PermissionsErr + | KeypairErr + | WebhookErr + | CryptoErr + | LocalAccountErr + | RpcErr + | SmartAccountErr + | CircleErr + | AwsKmsErr + | GcpKmsErr + | VaultKmsErr + | WalletProviderConfigErr + | EoaCredentialErr + | AccountErr + | BundlerExecutorAsyncQueueingErr; + +export function isEngineErr(err: unknown): err is EngineErr { + return ( + typeof err === "object" && + "kind" in (err as EngineErr) && + "code" in (err as EngineErr) + ); +} + +export class EngineHttpException extends HTTPException { + engineErr: EngineErr; + + constructor(error: EngineErr) { + super(error.status, { + message: error.message ?? getDefaultErrorMessage(error), + cause: error.source, + }); + this.engineErr = error; + } +} + +export function engineErrToHttpException(error: EngineErr): HTTPException { + return new EngineHttpException(error); +} + +export function getDefaultErrorMessage(error: EngineErr): string { + switch (error.kind) { + case "auth": { + const messages: Record = { + missing_auth_header: "Missing or invalid authorization header", + invalid_jwt: "Invalid JWT token", + invalid_signature: "Invalid signature", + insufficient_permissions: "Insufficient permissions", + malformed_auth_header: "Malformed authorization header", + expired_jwt: "Token has expired", + invalid_keypair: "Invalid keypair", + invalid_body_hash: "Invalid body hash", + webhook_auth_failed: "Webhook authentication failed", + }; + return messages[error.code]; + } + case "database": { + const messages: Record = { + query_failed: "Database operation failed", + invalid_id_format: "Invalid ID format", + transaction_db_entry_failed: + "Your transaction was sent sucessfully but engine was unable to store transaction details. Please do not resend this transaction to prevent double spending.", + }; + return messages[error.code]; + } + case "access_token": { + const messages: Record = { + token_not_found: "Token not found", + token_revoked: "Token revoked", + insufficient_permissions: "Insufficient permissions", + }; + return messages[error.code]; + } + case "validation": { + const messages: Record = { + invalid_address: "Invalid address", + parse_error: "Invalid input", + filter_error: "Invalid filters specified", + invalid_contract_details: "Invalid contract details", + invalid_chain: + "Invalid chain. This could mean parsing the chain ID failed, or the requested action is not supported on this chain.", + transaction_simulation_failed: + "Transaction simulation failed. This usually means the contract reverted.", + }; + return messages[error.code]; + } + case "permissions": { + const messages: Record = { + insufficient_permissions: "Insufficient permissions for operation", + no_permissions: "No permissions defined for this address", + }; + return messages[error.code]; + } + case "keypair": { + const messages: Record = { + missing_identifier: "Missing identifier", + keypair_not_found: "Keypair not found", + }; + return messages[error.code]; + } + case "webhook": { + const messages: Record = { + request_failed: "Webhook request failed", + }; + return messages[error.code]; + } + case "crypto": { + const messages: Record = { + encryption_failed: "Encryption failed", + decryption_failed: "Decryption failed", + invalid_format_not_json: + "Invalid encrypted data format, could not parse JSON", + key_derivation_failed: "Key derivation failed", + }; + return messages[error.code]; + } + case "local_account": { + const messages: Record = { + account_creation_failed: "Account creation failed", + account_decryption_failed: "Account decryption failed", + }; + return messages[error.code]; + } + case "rpc": { + const messages: Record = { + smart_account_determination_failed: + "Unable to auto create smart account for newly created account", + send_transaction_failed: "Failed to send transaction to RPC", + sign_transaction_failed: "Failed to sign transaction", + sign_message_failed: "Failed to sign message", + sign_typed_data_failed: "Failed to sign typed data", + sign_userop_failed: "Failed to sign user operation", + bundle_userop_failed: "Failed to bundle user operation", + get_userop_receipt_failed: "Failed to get user operation receipt", + get_transaction_count_failed: "Failed to get transaction count", + serialize_transaction_failed: + "Failed to serialize transaction. This usually means we were unable to simulate the transaction, because simulation failed.", + get_transaction_receipt_failed: "Failed to get transaction receipt", + get_balance_failed: "Failed to get balance", + resolve_method_failed: + "Failed to resolve method, this usually means we were unable to get your contract ABI", + encode_transaction_failed: + "Failed to encode transaction, this usually happens when the transaction is malformed", + read_contract_failed: "Failed to read contract", + chain_determination_failed: + "Failed to determine chain (eg: checking if chain is zkSync)", + }; + return messages[error.code]; + } + case "smart_account": { + const messages: Record = { + smart_account_validation_failed: "Unable to validate smart account", + }; + return messages[error.code]; + } + case "circle": { + const messages: Record = { + wallet_set_creation_failed: "Unable to create wallet set", + wallet_provisioning_failed: "Unable to provision wallet", + wallet_retrieval_failed: "Unable to retrieve wallet", + invalid_wallet_set: "Invalid wallet set", + rate_limit_exceeded: "Rate limit exceeded", + unauthorized: "Unauthorized", + service_unavailable: "Service unavailable", + signature_failed: "Signature failed", + }; + return messages[error.code]; + } + case "aws_kms": { + const messages = { + unauthorized: "Unauthorized", + rate_limit_exceeded: "Rate limit exceeded", + invalid_key_state: "Invalid key state", + key_creation_failed: "Key creation failed", + address_retrieval_failed: "Address retrieval failed", + signature_failed: "Signature failed", + }; + return messages[error.code]; + } + case "gcp_kms": { + const messages: Record = { + address_retrieval_failed: "Address retrieval failed", + signature_failed: "Signature failed", + key_creation_failed: "Key creation failed", + client_error: "Client error", + invalid_key_state: "Invalid key state", + unauthorized: "Unauthorized", + rate_limit_exceeded: "Rate limit exceeded", + }; + return messages[error.code]; + } + case "vault_kms": { + const messages: Record = { + auth_unsupported_operation: "Auth unsupported operation", + auth_insufficient_scope: "Auth insufficient scope", + auth_invalid_admin_key: "Auth invalid admin key", + internal_server_error: "Internal server error", + serialization_error: "Serialization error", + invalid_input: "Invalid input", + protocol_error: "Protocol error", + unreachable: "Unreachable", + transaction_parse_failed: "Transaction parse failed", + }; + return messages[error.code]; + } + case "wallet_provider_config": { + const messages: Record = { + missing_aws_kms_config: "Missing AWS KMS config", + missing_gcp_kms_config: "Missing GCP KMS config", + missing_circle_config: "Missing Circle config", + }; + return messages[error.code]; + } + case "eoa_credential": { + const messages: Record = { + credential_not_found: "Credential not found", + }; + return messages[error.code]; + } + case "account": { + const messages: Record = { + account_not_found: "Account not found", + account_deletion_failed: "Account deletion failed", + could_not_disambiguate: + "Multiple signers have been found for this smart account. Please specify signer address to use this smart account", + invalid_platform_identifiers: + "Invalid platform identifiers. Platform identifiers for this EOA do not match the type of the account", + }; + return messages[error.code]; + } + case "queue": { + const messages: Record = + { + "external_bundler:queuing_confirm_job_failed": + "Failed to queue confirm job", + "external_bundler:queuing_send_job_failed": + "Failed to queue send job", + }; + return messages[error.code]; + } + } +} + +export function unwrapError(originalError: unknown) { + return { + ...(originalError + ? { + name: originalError?.constructor?.name ?? "Unknown", + message: (originalError as Error)?.message ?? String(originalError), + stack: (originalError as Error)?.stack, + ...(originalError as object), + } + : {}), + }; +} + +export function mapDbError(error: unknown): DbErr { + if (error instanceof Error) { + if (error.message.includes("invalid input syntax for type uuid")) { + return { + kind: "database", + code: "invalid_id_format", + status: 400, + source: error, + }; + } + } + + return { + kind: "database", + code: "query_failed", + status: 500, + source: error instanceof Error ? error : undefined, + }; +} + +export function getZodErrorMessage(error: ZodError): string { + return error.errors + .map((err) => { + const path = err.path.join("."); + return path ? `${path}: ${err.message}` : err.message; + }) + .join(", "); +} + +export function mapZodError(error: unknown): ValidationErr { + if (error instanceof ZodError) { + return { + kind: "validation", + code: "parse_error", + status: 400, + message: getZodErrorMessage(error), + } as const; + } + + // Handle non-Zod errors by returning a generic validation error + return { + kind: "validation", + code: "parse_error", + status: 400, + message: "Invalid input", + source: error instanceof Error ? error : undefined, + } as const; +} + +export const zErrorMapper: Hook = (result) => { + if (!result.success) { + throw engineErrToHttpException(mapZodError(result.error)); + } +}; + +type RpcErrorOptions = { + code?: RpcErr["code"]; + status?: number; + defaultMessage?: string; + chainId?: string; + address?: Address; +}; + +const DEFAULT_RPC_OPTIONS: RpcErrorOptions = { + code: "send_transaction_failed", + status: 500, + defaultMessage: "RPC request failed", +}; + +export type AccountActionErr = GcpKmsErr | AwsKmsErr | CircleErr; + +/** + * Checks if the error is an account action error. + * An account action error happens at the "account" level. + * If you were to send a transaction with a gcp kms account, it can fail at 2 levels. + * + * `account.sendTransaction` internally calls `signTransaction`. + * If signing a transacation failed because we couldn't access the KMS account itself, + * this error would be an `AccountActionErr`. + * + * If instead, the send call to RPC errored, then you will receive an RpcErr + * You can use the `accountActionErrorMapper` along with any method to an Account type. + * This will accurately map to an AccountErr or an RpcErr based on what went wrong. + * + * @param error - The error to check. + * @returns True if the error is an account action error, false otherwise. + */ +export function isAccountActionErr(error: unknown): error is AccountActionErr { + return ( + isEngineErr(error) && + (error.kind === "gcp_kms" || + error.kind === "aws_kms" || + error.kind === "circle") + ); +} + +/** + * Maps an account action error to an EngineErr. + * This will accurately map to an AccountErr or an RpcErr based on what went wrong. + * + * @param options - The options to pass to the mapper. + * @returns The mapped error. + */ +export const accountActionErrorMapper = (options: RpcErrorOptions = {}) => { + const { code, status, defaultMessage, address, chainId } = { + ...DEFAULT_RPC_OPTIONS, + ...options, + }; + + return (error: unknown): EngineErr => { + if (isEngineErr(error)) { + return error; + } + + if (error instanceof Error && error.name === "TransactionError") { + const chainId = "chainId" in error ? error.chainId : undefined; + const contractAddress = + "contractAddress" in error ? error.contractAddress : undefined; + return { + kind: "validation", + code: "transaction_simulation_failed", + status: 400, + message: `Transaction simulation failed: ${error.message}`, + source: error, + chainId, + contractAddress, + } as ValidationErr; + } + + return { + kind: "rpc", + code, + status, + chainId, + address, + message: defaultMessage + ? defaultMessage + : error instanceof Error + ? error.message + : defaultMessage, + source: error instanceof Error ? error : undefined, + } as RpcErr; + }; +}; + +/** + * Enhanced pretty printer for error objects + * Handles custom error objects that may contain nested Error instances + * Formats all fields as key-value pairs with special handling for Error objects + */ +export function prettyPrintError(error: unknown, indent: string = ""): string { + // Base case: null or undefined + if (error === null) { + return `${indent}null`; + } else if (error === undefined) { + return `${indent}undefined`; + } + + // Handle standard Error objects + if (error instanceof Error) { + let result = `${indent}${error.name}: ${error.message}\n`; + if (error.stack) { + result += `${indent}${error.stack.split("\n").join(`\n${indent}`)}\n`; + } + + // Print any additional properties on the Error object + const errorObj = error as any; + const knownProps = ["name", "message", "stack"]; + const additionalProps = Object.keys(errorObj).filter( + (key) => !knownProps.includes(key), + ); + + if (additionalProps.length > 0) { + result += `${indent}Additional properties:\n`; + for (const prop of additionalProps) { + result += `${indent} ${prop}: ${formatValue(errorObj[prop], `${indent} `)}\n`; + } + } + + return result; + } + + // Handle string errors + if (typeof error === "string") { + return `${indent}${error}`; + } + + // Handle custom error objects + if (typeof error === "object") { + let result = ""; + + // Handle arrays + if (Array.isArray(error)) { + result = `${indent}[\n`; + for (let i = 0; i < error.length; i++) { + result += `${indent} [${i}]: ${formatValue(error[i], `${indent} `)}\n`; + } + result += `${indent}]`; + return result; + } + + // Handle plain objects + result = `${indent}{\n`; + for (const [key, value] of Object.entries(error)) { + result += `${indent} ${key}: ${formatValue(value, `${indent} `)}\n`; + } + result += `${indent}}`; + return result; + } + + // Handle primitive values + return `${indent}${String(error)}`; +} + +/** + * Helper function to format different types of values, with special handling for Error objects + */ +function formatValue(value: unknown, indent: string): string { + // Handle null and undefined + if (value === null) { + return "null"; + } else if (value === undefined) { + return "undefined"; + } + + // Handle Error objects + if (value instanceof Error) { + return `\n${prettyPrintError(value, `${indent} `)}`; + } + + // Handle nested objects recursively + if (typeof value === "object" && value !== null) { + return `\n${prettyPrintError(value, `${indent} `)}`; + } + + // Handle primitive values + if (typeof value === "string") { + return `"${value}"`; + } + + return String(value); +} diff --git a/src/lib/evm.ts b/src/lib/evm.ts new file mode 100644 index 000000000..103edee46 --- /dev/null +++ b/src/lib/evm.ts @@ -0,0 +1,3 @@ +export function getDisplayAddress(address: string) { + return `${address.slice(0, 6)}...${address.slice(-4)}`; +} diff --git a/src/lib/keypairs.ts b/src/lib/keypairs.ts new file mode 100644 index 000000000..17023b6c7 --- /dev/null +++ b/src/lib/keypairs.ts @@ -0,0 +1,59 @@ +import { LRUCache } from "lru-cache"; +import { ResultAsync, err, errAsync, ok, okAsync } from "neverthrow"; +import { db } from "../db/connection.js"; +import type { KeypairDbEntry } from "../db/types.js"; +import { type KeypairErr, type DbErr, mapDbError } from "./errors.js"; + +const keypairCache = new LRUCache({ + max: 1024, +}); + +type GetKeypairParams = { + publicKey?: string; + publicKeyHash?: string; +}; + +export function getKeypair({ + publicKey, + publicKeyHash, +}: GetKeypairParams): ResultAsync { + const id = publicKeyHash ?? publicKey; + if (!id) { + return errAsync({ + kind: "keypair", + code: "missing_identifier", + status: 400, + } as const); + } + + const cached = keypairCache.get(id); + if (cached) { + return okAsync(cached); + } + + return ResultAsync.fromPromise( + db.query.keypairs.findFirst({ + where: (keypairs, { or, eq, and, isNull }) => + and( + or( + publicKey ? eq(keypairs.publicKey, publicKey) : undefined, + publicKeyHash ? eq(keypairs.hash, publicKeyHash) : undefined, + ), + isNull(keypairs.deletedAt), + ), + }), + mapDbError, + ) + .andTee((keypair) => { + keypair && keypairCache.set(id, keypair); + }) + .andThen((keypair) => + keypair + ? ok(keypair) + : err({ + kind: "keypair", + code: "keypair_not_found", + status: 400, + } as const), + ); +} diff --git a/src/lib/keystore.test.ts b/src/lib/keystore.test.ts new file mode 100644 index 000000000..e0c18fc0e --- /dev/null +++ b/src/lib/keystore.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, test } from "bun:test"; +import { generateKeystore, decryptKeystore } from "./keystore.js"; +import { privateKeyToAccount } from "thirdweb/wallets"; + +describe("keystore", () => { + const testKeystore = { + data: '{"address":"7d67388109f26f768b6ec84cf1bae78ffd2740c9","id":"197973e0-d42e-4316-a3e7-a71b03471caa","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"392e0a4f1ef5d3a4df3417bc4d1187b1"},"ciphertext":"b189e4c3d4fdcac11e56c68b5e1fb6abfca34aa01063cf2209d2879abc96c7e5","kdf":"scrypt","kdfparams":{"salt":"182b95da1188ea6d1f32f44e808a35a3ed8599c2fee755fda0195aeeeb2ef1f3","n":131072,"dklen":32,"p":1,"r":8},"mac":"78624250436e61013d98ebdcdb61e5e97bf020151b96cd526f92068ab5886791"}}', + address: "0x7d67388109F26f768B6EC84Cf1bae78ffd2740C9", + }; + + const password = "hellohello"; + + test("should decrypt existing keystore correctly", () => { + const decrypted = decryptKeystore(testKeystore.data, password); + // @ts-expect-error we don't need a client + const account = privateKeyToAccount({ privateKey: decrypted, client: {} }); + expect(account.address.toLowerCase()).toBe( + testKeystore.address.toLowerCase(), + ); + }); + + test("should encrypt and decrypt correctly", () => { + const testPk = + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; + const encrypted = generateKeystore(testPk, password); + const decrypted = decryptKeystore(encrypted, password); + expect(decrypted).toBe(testPk); + }); + + test("should fail with wrong password", () => { + expect(() => { + decryptKeystore(testKeystore.data, "wrongpassword"); + }).toThrow("Invalid password"); + }); +}); diff --git a/src/lib/keystore.ts b/src/lib/keystore.ts new file mode 100644 index 000000000..5fc09af9e --- /dev/null +++ b/src/lib/keystore.ts @@ -0,0 +1,174 @@ +import { + randomBytes, + createCipheriv, + createDecipheriv, + scryptSync, + timingSafeEqual, + randomUUID, +} from "node:crypto"; +import { keccak256 } from "ox/Hash"; +import { Hex } from "ox"; + +interface Keystore { + version: 3; + id: string; + crypto: { + cipher: string; + ciphertext: string; + cipherparams: { + iv: string; + }; + kdf: string; + kdfparams: { + dklen: number; + n: number; + r: number; + p: number; + salt: string; + }; + mac: string; + }; +} + +function normalizeHexString(hex: string): Buffer { + // Remove 0x prefix if present + const normalized = hex.startsWith("0x") ? hex.slice(2) : hex; + // Validate hex string + if (!/^[0-9a-fA-F]{64}$/.test(normalized)) { + throw new Error("Invalid private key format: must be 32 bytes hex string"); + } + return Buffer.from(normalized, "hex"); +} + +function ensureBuffer( + value: Buffer | string, + encoding: BufferEncoding = "hex" +): Buffer { + if (Buffer.isBuffer(value)) return value; + return Buffer.from(value, encoding); +} + +function generateKeystore(privateKey: string, password: string): Keystore { + if (!password || typeof password !== "string") { + throw new Error("Password must be a non-empty string"); + } + + const pkBuffer = normalizeHexString(privateKey); + const passwordBytes = Buffer.from(password, "utf8"); + + // Generate random values + const salt = randomBytes(32); + const iv = randomBytes(16); + + // KDF params + const n = 8192; + const r = 8; + const p = 1; + const dklen = 32; + + try { + // Derive key using scrypt + const derivedKey = scryptSync(passwordBytes, salt, dklen, { N: n, r, p }); + + // Encrypt private key + const cipher = createCipheriv("aes-128-ctr", derivedKey.slice(0, 16), iv); + const ciphertext = Buffer.concat([cipher.update(pkBuffer), cipher.final()]); + + // Generate MAC + const mac = Buffer.concat([derivedKey.slice(16, 32), ciphertext]); + const macHash = keccak256(mac); + const macHashInHexWithoutPrefix = Hex.from(macHash).toString().slice(2); + // Create keystore object with proper hex encoding + const keystore: Keystore = { + version: 3, + id: randomUUID().toString(), + crypto: { + cipher: "aes-128-ctr", + ciphertext: ciphertext.toString("hex"), + cipherparams: { + iv: iv.toString("hex"), + }, + kdf: "scrypt", + kdfparams: { + dklen, + n, + r, + p, + salt: salt.toString("hex"), + }, + mac: macHashInHexWithoutPrefix, + }, + }; + + return keystore; + } finally { + // Zero out sensitive data + pkBuffer.fill(0); + passwordBytes.fill(0); + } +} + +function decryptKeystore( + keystoreData: string | Keystore, + password: string +): string { + if (!password || typeof password !== "string") { + throw new Error("Password must be a non-empty string"); + } + + const keystore: Keystore = + typeof keystoreData === "string" ? JSON.parse(keystoreData) : keystoreData; + + const passwordBytes = Buffer.from(password, "utf8"); + + try { + const { crypto } = keystore; + const { ciphertext, cipherparams, kdfparams, mac } = crypto; + + // Convert hex strings to buffers + const saltBuffer = ensureBuffer(kdfparams.salt); + const ivBuffer = ensureBuffer(cipherparams.iv); + const ciphertextBuffer = ensureBuffer(ciphertext); + const macBuffer = ensureBuffer(mac); + + // Derive key + const derivedKey = scryptSync(passwordBytes, saltBuffer, kdfparams.dklen, { + N: kdfparams.n, + r: kdfparams.r, + p: kdfparams.p, + maxmem: 256 * 1024 * 1024, + }); + + // Verify MAC (constant-time comparison) + const computedMac = Buffer.concat([ + derivedKey.slice(16, 32), + ciphertextBuffer, + ]); + + const computedMacHash = keccak256(computedMac); + + if (!timingSafeEqual(computedMacHash, macBuffer)) { + throw new Error("Invalid password"); + } + + // Decrypt + const decipher = createDecipheriv( + "aes-128-ctr", + derivedKey.slice(0, 16), + ivBuffer + ); + + const privateKey = Buffer.concat([ + decipher.update(ciphertextBuffer), + decipher.final(), + ]); + + // Return with 0x prefix + return `0x${privateKey.toString("hex")}`; + } finally { + // Zero out sensitive data + passwordBytes.fill(0); + } +} + +export { generateKeystore, decryptKeystore, type Keystore }; diff --git a/src/lib/logger.ts b/src/lib/logger.ts new file mode 100644 index 000000000..1cc852624 --- /dev/null +++ b/src/lib/logger.ts @@ -0,0 +1,148 @@ +import { + type Logger, + type LoggerOptions, + createLogger, + format, + transports, +} from "winston"; +import { env } from "./env.js"; + +const metadataFormatter = format((meta) => { + if (!meta[Symbol.for("splat")]) { + meta[Symbol.for("splat")] = []; + } + const customMetadata: { [key: string]: unknown } = {}; + let error: Error | undefined; + for (const el of meta[Symbol.for("splat")] as unknown[]) { + if (!el) { + continue; + } + if (el instanceof Error && !error) { + error = el; + } else { + for (const [key, val] of Object.entries(el)) { + customMetadata[key] = val; + } + } + } + const errorMetadata: Record = {}; + if (error?.stack) { + errorMetadata.stack = error.stack; + } + + return { ...meta, ...customMetadata, ...errorMetadata }; +}); + +const getLocalhostOptions = (loggerName: string): LoggerOptions => { + const prettyfiedLog = format.printf((info) => { + // Extract correlation ID if present + const correlationId = info?.correlationId + ? `{correlation-id: ${info.correlationId}}` + : ""; + + // Standard fields that we'll exclude from metadata display + const standardFields = [ + "message", + "level", + "context", + "correlationId", + "stack", + "level", + "ms", + "service", + "timestamp", + "component", + ]; + + // Build metadata object with non-standard fields only + const metadata: Record = {}; + Object.keys(info).forEach((key) => { + if (!standardFields.includes(key)) { + metadata[key] = info[key]; + } + }); + + // Convert remaining metadata to JSON string if there's anything left + const metadataStr = + Object.keys(metadata).length > 0 + ? `\n${JSON.stringify( + metadata, + (_, value) => { + // Handle circular references or complex objects + if (value instanceof Error) { + return { + message: value.message, + name: value.name, + stack: value.stack, + }; + } + return value; + }, + 2, + )}` + : ""; + + // Return formatted log with metadata appended + return `[${info.context ?? loggerName}] ${correlationId} ${info.level}: ${ + info.message || "" + } ${info.stack || ""}${metadataStr}`; + }); + + return { + level: "http", + format: format.combine( + metadataFormatter(), + format.errors({ stack: true }), + format.colorize(), + prettyfiedLog, + ), + transports: [new transports.Console()], + exceptionHandlers: [new transports.Console()], + rejectionHandlers: [new transports.Console()], + }; +}; + +const getProductionOptions = (loggerName: string): LoggerOptions => { + return { + level: env.LOG_LEVEL, + exitOnError: false, + handleExceptions: true, + handleRejections: true, + + defaultMeta: { + component: loggerName, + service: process.env.DD_SERVICE, + ...metadataFormatter(), + }, + format: format.combine( + format.errors({ stack: true }), + format((info) => { + const { correlationId, ...rest } = info; + return { + ...rest, + ...(correlationId ? { correlationId } : {}), + }; + })(), + format.json(), + ), + transports: [new transports.Console()], + exceptionHandlers: [new transports.Console()], + rejectionHandlers: [new transports.Console()], + }; +}; + +const initializeBaseLogger = (name: string): Logger => { + const isLocalhost = + (!process.env.DD_TRACER_ACTIVATED || !process.env.ZEET_PROJECT_NAME) && + (env.NODE_ENV === "local" || env.NODE_ENV === "development"); + const options = isLocalhost + ? getLocalhostOptions(name) + : getProductionOptions(name); + return createLogger(options); +}; + +export const defaultLogger = initializeBaseLogger("default"); + +export const initializeLogger = (name: string): Logger => { + return defaultLogger.child({ context: name }); +}; diff --git a/src/lib/permissions.ts b/src/lib/permissions.ts new file mode 100644 index 000000000..5a63dd712 --- /dev/null +++ b/src/lib/permissions.ts @@ -0,0 +1,88 @@ +import { err, ok, okAsync, ResultAsync } from "neverthrow"; +import type { Permission, PermissionDbEntry } from "../db/types.js"; +import type { Address } from "thirdweb"; +import { + mapDbError, + type AuthErr, + type DbErr, + type PermissionsErr, + type ValidationErr, +} from "./errors.js"; +import { getAddressResult } from "./validation/address.js"; +import { db } from "../db/connection.js"; +import { LRUCache } from "lru-cache"; +import { adminAccount } from "./admin-account.js"; + +const permissionCache = new LRUCache({ + max: 1024, +}); + +export function getPermissions( + address: Address +): ResultAsync { + const cached = permissionCache.get(address); + if (cached) { + return okAsync(cached); + } + + return ResultAsync.fromPromise( + db.query.permissions.findFirst({ + where: (permissions, { eq }) => eq(permissions.accountAddress, address), + }), + mapDbError + ) + .andTee((permission) => { + permission && permissionCache.set(address, permission); + }) + .andThen((permission) => + permission + ? ok(permission) + : err({ + kind: "permissions", + code: "no_permissions", + status: 400, + } as PermissionsErr) + ); +} + +export function checkPermissions({ + address: rawAddress, + allowedPermissions, +}: { + address: string; + allowedPermissions: Permission[]; +}): ResultAsync< + { address: Address; permissions: Permission }, + AuthErr | ValidationErr | DbErr +> { + return getAddressResult("Invalid User Address")(rawAddress) + .asyncAndThen((address) => { + if (address === adminAccount.address) { + return okAsync({ + accountAddress: address, + permissions: "ADMIN" as const, + label: "Admin", + }); + } + return getPermissions(address); + }) + .mapErr((error) => { + if (error.kind === "permissions") { + return { + kind: "auth", + code: "insufficient_permissions", + status: 401, + } as AuthErr; + } + return error; + }) + .andThen(({ accountAddress, permissions }) => { + return allowedPermissions.includes(permissions) + ? ok({ address: accountAddress, permissions }) + : err({ + kind: "auth", + code: "insufficient_permissions", + status: 401, + } as const); + }); +} diff --git a/src/shared/utils/prometheus.ts b/src/lib/prometheus.ts similarity index 79% rename from src/shared/utils/prometheus.ts rename to src/lib/prometheus.ts index 21b99132f..3adf7509b 100644 --- a/src/shared/utils/prometheus.ts +++ b/src/lib/prometheus.ts @@ -1,44 +1,46 @@ -import fastify from "fastify"; import { Counter, Gauge, Histogram, Registry } from "prom-client"; -import { getUsedBackendWallets, inspectNonce } from "../db/wallets/wallet-nonce"; -import { getLastUsedOnchainNonce } from "../../server/routes/admin/nonces"; - -const nonceMetrics = new Gauge({ - name: "engine_nonces", - help: "Current nonce values and health for backend wallets", - labelNames: ["wallet_address", "chain_id", "nonce_type"] as const, - async collect() { - const allWallets = await getUsedBackendWallets(); - - for (const { chainId, walletAddress } of allWallets) { - const [onchainNonce, engineNonce] = await Promise.all([ - getLastUsedOnchainNonce(chainId, walletAddress), - inspectNonce(chainId, walletAddress), - ]); - - this.set( - { - wallet_address: walletAddress, - chain_id: chainId.toString(), - nonce_type: "onchain", - }, - onchainNonce, - ); - this.set( - { - wallet_address: walletAddress, - chain_id: chainId.toString(), - nonce_type: "engine", - }, - engineNonce, - ); - } - }, -}); +// import { +// getUsedBackendWallets, +// inspectNonce, +// } from "./db/wallets/wallet-nonce.js"; +// import { getLastUsedOnchainNonce } from "../../server/routes/admin/nonces.js"; + +// const nonceMetrics = new Gauge({ +// name: "engine_nonces", +// help: "Current nonce values and health for backend wallets", +// labelNames: ["wallet_address", "chain_id", "nonce_type"] as const, +// async collect() { +// const allWallets = await getUsedBackendWallets(); + +// for (const { chainId, walletAddress } of allWallets) { +// const [onchainNonce, engineNonce] = await Promise.all([ +// getLastUsedOnchainNonce(chainId, walletAddress), +// inspectNonce(chainId, walletAddress), +// ]); + +// this.set( +// { +// wallet_address: walletAddress, +// chain_id: chainId.toString(), +// nonce_type: "onchain", +// }, +// onchainNonce, +// ); +// this.set( +// { +// wallet_address: walletAddress, +// chain_id: chainId.toString(), +// nonce_type: "engine", +// }, +// engineNonce, +// ); +// } +// }, +// }); export const enginePromRegister = new Registry(); -enginePromRegister.registerMetric(nonceMetrics); +// enginePromRegister.registerMetric(nonceMetrics); // Define strict types for each event type ResponseSentParams = { @@ -235,13 +237,3 @@ export function recordMetrics(eventData: MetricParams): void { } } } -// Expose metrics endpoint - -export const metricsServer = fastify({ - disableRequestLogging: true, -}); - -metricsServer.get("/metrics", async (_request, reply) => { - reply.header("Content-Type", enginePromRegister.contentType); - return enginePromRegister.metrics(); -}); diff --git a/src/lib/redis.ts b/src/lib/redis.ts new file mode 100644 index 000000000..469fd79c0 --- /dev/null +++ b/src/lib/redis.ts @@ -0,0 +1,149 @@ +import { Redis } from "ioredis"; +import { env } from "./env.js"; +import { initializeLogger } from "./logger.js"; + +const redisLogger = initializeLogger("redis"); + +// ioredis has issues with batches over 100k+ (source: https://github.com/redis/ioredis/issues/801). +export const MAX_REDIS_BATCH_SIZE = 50_000; + +export const redis = new Redis(env.REDIS_URL, { + enableAutoPipelining: true, + maxRetriesPerRequest: null, +}); + +try { + await redis.config("SET", "maxmemory", env.REDIS_MAXMEMORY); +} catch (error) { + redisLogger.error("Initializing Redis", error); +} + +redis.on("error", (error) => () => { + redisLogger.error("Redis error", error); +}); +redis.on("ready", () => { + redisLogger.info("Redis ready"); +}); + +// Assuming logger setup is similar +const lockLogger = initializeLogger("redis-lock-utils"); + +// --- Type-Safe Lock Utilities --- + +/** + * Attempts to acquire a distributed lock using Redis. + * + * @param client - The ioredis client instance. + * @param key - The unique key for the lock. + * @param ttlSeconds - The time-to-live for the lock in seconds. + * The lock will automatically expire after this duration + * if not released explicitly. + * @returns A promise that resolves to `true` if the lock was acquired + * successfully, and `false` otherwise (e.g., lock already held). + */ +export async function acquireLock( + key: string, + ttlSeconds: number, +): Promise { + try { + // SET key value EX ttlSeconds NX + // EX: Set the specified expire time, in seconds. + // NX: Only set the key if it does not already exist. + // 'OK' is returned if the operation is successful (lock acquired). + // null is returned if the key already exists (lock not acquired). + const result = await redis.set(key, "locked", "EX", ttlSeconds, "NX"); + const acquired = result === "OK"; + if (acquired) { + lockLogger.debug(`Lock acquired successfully for key: ${key}`); + } else { + lockLogger.debug(`Failed to acquire lock (already held): ${key}`); + } + return acquired; + } catch (error) { + lockLogger.error(`Error acquiring lock for key ${key}: ${error}`); + return false; // Assume lock not acquired on error + } +} + +/** + * Releases a distributed lock by deleting the key from Redis. + * + * @param client - The ioredis client instance. + * @param key - The unique key for the lock to release. + * @returns A promise that resolves when the delete command is sent. + * It doesn't guarantee the lock was actually held by the caller. + */ +export async function releaseLock(key: string): Promise { + try { + // DEL key + // Returns the number of keys that were removed (0 or 1 in this case). + const deletedCount = await redis.del(key); + if (deletedCount > 0) { + lockLogger.debug(`Lock released successfully for key: ${key}`); + } else { + // This might happen if the lock expired before release, which is fine. + lockLogger.debug( + `Lock key not found during release (already expired?): ${key}`, + ); + } + } catch (error) { + lockLogger.error(`Error releasing lock for key ${key}: ${error}`); + // Decide if you want to re-throw or just log based on your error strategy + } +} + +/** + * Waits until a specific lock key no longer exists in Redis. + * Polls Redis periodically. Includes a timeout to prevent indefinite waiting. + * + * @param client - The ioredis client instance. + * @param key - The lock key to wait for. + * @param pollIntervalMs - How often to check for the lock (in milliseconds). + * @param timeoutMs - Maximum time to wait (in milliseconds). + * @returns A promise that resolves when the lock key is gone, or rejects on timeout or error. + */ +export function waitForLock( + key: string, + pollIntervalMs = 100, // Check every 100ms by default + timeoutMs = 60000, // Default timeout 60 seconds +): Promise { + return new Promise((resolve, reject) => { + const startTime = Date.now(); + + const checkLock = async () => { + try { + // Check elapsed time + if (Date.now() - startTime > timeoutMs) { + return reject(new Error(`Timeout waiting for lock release: ${key}`)); + } + + // EXISTS key + // Returns 1 if the key exists, 0 otherwise. + const exists = await redis.exists(key); + + if (exists === 0) { + lockLogger.debug(`Lock key ${key} released. Proceeding.`); + resolve(); // Lock is gone + } else { + // Lock still exists, wait and check again + setTimeout(checkLock, pollIntervalMs); + } + } catch (error) { + lockLogger.error(`Error checking lock status for key ${key}: ${error}`); + reject(error); // Propagate Redis errors + } + }; + + // Start the first check + checkLock(); + }); +} + +export async function isRedisReachable() { + try { + await redis.ping(); + return true; + } catch { + return false; + } +} diff --git a/src/lib/result-wrapped/thirdweb-sdk.ts b/src/lib/result-wrapped/thirdweb-sdk.ts new file mode 100644 index 000000000..67064211d --- /dev/null +++ b/src/lib/result-wrapped/thirdweb-sdk.ts @@ -0,0 +1,72 @@ +import { err, ok, ResultAsync } from "neverthrow"; +import { + getContract, + type Address, + type Chain, + type Hex, + type ThirdwebClient, + type ThirdwebContract, +} from "thirdweb"; +import { isZkSyncChain } from "thirdweb/utils"; +import { accountActionErrorMapper, type ValidationErr } from "../errors"; +import { predictAccountAddress } from "thirdweb/extensions/erc4337"; + +export function isZkSyncChainResult(chain: Chain) { + return ResultAsync.fromPromise( + isZkSyncChain(chain), + accountActionErrorMapper({ + code: "chain_determination_failed", + }), + ); +} + +export function getContractResult({ + address, + chain, + client, +}: { + address: Address; + chain: Chain; + client: ThirdwebClient; +}) { + try { + const contract = getContract({ + address, + chain, + client, + }); + + return ok(contract); + } catch (e) { + return err({ + kind: "validation", + code: "invalid_contract_details", + status: 400, + source: e instanceof Error ? e : undefined, + } satisfies ValidationErr as ValidationErr); + } +} + +export function predictAccountAddressResult({ + adminSigner, + contract, + data, +}: { + adminSigner: Address; + contract: ThirdwebContract; + data: Hex; +}) { + return ResultAsync.fromPromise( + predictAccountAddress({ + adminSigner, + contract, + data, + }), + accountActionErrorMapper({ + code: "smart_account_determination_failed", + status: 500, + address: adminSigner, + chainId: contract.chain.id.toString(), + }), + ); +} diff --git a/src/lib/runtime-migrations/apply-runtime-migrations.ts b/src/lib/runtime-migrations/apply-runtime-migrations.ts new file mode 100644 index 000000000..ab503a9ca --- /dev/null +++ b/src/lib/runtime-migrations/apply-runtime-migrations.ts @@ -0,0 +1,30 @@ +import { initializeLogger } from "../logger.js"; +import { acquireLock, releaseLock, waitForLock } from "../redis.js"; + +const logger = initializeLogger("runtime-migrations"); + +const MIGRATION_LOCK_TTL_SECONDS = 60; +const LOCK_KEY = "lock:apply-migrations"; + +export async function applyRuntimeMigrations() { + // Acquire a lock to allow only one host to run migrations. + // Other hosts block until the migration is completed or lock times out. + const acquiredLock = await acquireLock(LOCK_KEY, MIGRATION_LOCK_TTL_SECONDS); + if (!acquiredLock) { + logger.info("Migration in progress. Waiting for the lock to release..."); + await waitForLock(LOCK_KEY); + process.exit(0); + } + + try { + // run all migrations here + logger.info("Completed migrations successfully."); + } catch (e) { + logger.error(`Failed to complete migrations: ${e}`); + process.exit(1); + } finally { + await releaseLock(LOCK_KEY); + } + + process.exit(0); +} diff --git a/src/lib/thirdweb-client.ts b/src/lib/thirdweb-client.ts new file mode 100644 index 000000000..6a17544e0 --- /dev/null +++ b/src/lib/thirdweb-client.ts @@ -0,0 +1,46 @@ +import { createThirdwebClient } from "thirdweb"; +import { env } from "./env.js"; +import { setServiceKey, setThirdwebDomains } from "thirdweb/utils"; +import { + THIRDWEB_BUNDLER_DOMAIN, + THIRDWEB_INAPP_WALLET_DOMAIN, + THIRDWEB_PAY_DOMAIN, + THIRDWEB_RPC_DOMAIN, + THIRDWEB_SOCIAL_API_DOMAIN, + THIRDWEB_STORAGE_DOMAIN, +} from "../constants/urls.js"; + +if (env.NODE_ENV !== "production") { + setThirdwebDomains({ + rpc: THIRDWEB_RPC_DOMAIN, + inAppWallet: THIRDWEB_INAPP_WALLET_DOMAIN, + pay: THIRDWEB_PAY_DOMAIN, + storage: THIRDWEB_STORAGE_DOMAIN, + social: THIRDWEB_SOCIAL_API_DOMAIN, + bundler: THIRDWEB_BUNDLER_DOMAIN, + }); +} + +export function getThirdwebClient( + params: + | { secretKey: string; clientId?: string } + | { clientId: string; serviceKey: string }, +) { + if ("serviceKey" in params) { + setServiceKey(params.serviceKey); + } + + const client = createThirdwebClient({ + ...params, + config: { + rpc: { maxBatchSize: 50 }, + }, + }); + + return client; +} + +export const thirdwebClient = getThirdwebClient({ + secretKey: env.THIRDWEB_API_SECRET_KEY, +}); +export const thirdwebClientId = thirdwebClient.clientId; diff --git a/src/lib/validation/address.ts b/src/lib/validation/address.ts new file mode 100644 index 000000000..9fed39909 --- /dev/null +++ b/src/lib/validation/address.ts @@ -0,0 +1,13 @@ +import { Result } from "neverthrow"; +import { getAddress } from "thirdweb"; +import type { ValidationErr } from "../errors.js"; + +export const getAddressResult = (message?: string) => + Result.fromThrowable(getAddress, () => { + return { + kind: "validation", + code: "invalid_address", + status: 400, + message, + } as ValidationErr; + }); diff --git a/src/lib/vault-client.ts b/src/lib/vault-client.ts new file mode 100644 index 000000000..cb9bae7e4 --- /dev/null +++ b/src/lib/vault-client.ts @@ -0,0 +1,6 @@ +import { env } from "./env"; +import { createVaultClient } from "./vault-sdk/sdk"; + +export const vaultClient = await createVaultClient({ + baseUrl: env.VAULT_URL, +}); diff --git a/src/lib/vault-sdk/sdk.ts b/src/lib/vault-sdk/sdk.ts new file mode 100644 index 000000000..b84bec3aa --- /dev/null +++ b/src/lib/vault-sdk/sdk.ts @@ -0,0 +1,560 @@ +import type { TypedData } from "abitype"; +import * as jose from "jose"; +import { x25519 } from "@noble/curves/ed25519"; +import { randomBytes } from "@noble/hashes/utils"; +import { sha256 } from "@noble/hashes/sha256"; +import { hkdf } from "@noble/hashes/hkdf"; +import { xchacha20poly1305 } from "@noble/ciphers/chacha"; +import { hexToBytes, bytesToHex } from "@noble/hashes/utils"; + +import type { + CreateAccessTokenPayload, + CreateEoaPayload, + CreateServiceAccountPayload, + EncryptedPayload, + GetServiceAccountPayload, + ListEoaPayload, + Payload, + PingPayload, + RevokeAccessTokenPayload, + RotateServiceAccountPayload, + SignMessagePayload, + SignTransactionPayload, + Prettify, + UnencryptedErrorResponse, + CheckedSignTypedDataPayload, + ListAccessTokensPayload, + SignStructuredMessagePayload, + SignAuthorizationPayload, + PolicyComponent, +} from "./types.js"; + +function encryptForEnclave( + payload: Payload["input"], + enclavePublicKey: Uint8Array, +): { encryptedPayload: EncryptedPayload; ephemeralPrivateKey: Uint8Array } { + const ephemeralPrivateKey = randomBytes(32); + // Generate ephemeral keypair + const ephemeralPublicKey = x25519.getPublicKey(ephemeralPrivateKey); + + // Derive shared secret using X25519 + const sharedSecret = x25519.getSharedSecret( + ephemeralPrivateKey, + enclavePublicKey, + ); + + // Key derivation + const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); + + // Convert message to bytes if it's not already + const messageBytes = + typeof payload === "string" + ? new TextEncoder().encode(payload) + : new TextEncoder().encode(JSON.stringify(payload)); + + // XChaCha20-Poly1305 encryption + const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 + const cipher = xchacha20poly1305(encryptionKey, nonce); + const ciphertext = cipher.encrypt(messageBytes); + + // Format the encrypted package + return { + encryptedPayload: { + ephemeralPublicKey: bytesToHex(ephemeralPublicKey), + nonce: bytesToHex(nonce), + ciphertext: bytesToHex(ciphertext), + }, + ephemeralPrivateKey: ephemeralPrivateKey, + }; +} + +function isErrorResponse( + response: UnencryptedErrorResponse | EncryptedPayload, +): response is UnencryptedErrorResponse { + return (response as UnencryptedErrorResponse).error !== undefined; +} + +function decryptFromEnclave( + encryptedPackage: EncryptedPayload, + ephemeralPrivateKey: Uint8Array, +) { + const { ephemeralPublicKey, nonce, ciphertext } = encryptedPackage; + + // Convert hex strings back to bytes + const pubKey = hexToBytes(ephemeralPublicKey); + const nonceBytes = hexToBytes(nonce); + const ciphertextBytes = hexToBytes(ciphertext); + + // Derive the same shared secret (from the enclave's ephemeral public key) + const sharedSecret = x25519.getSharedSecret(ephemeralPrivateKey, pubKey); + // Derive the same encryption key + const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); + + // Decrypt the ciphertext + const cipher = xchacha20poly1305(encryptionKey, nonceBytes); + const decrypted = cipher.decrypt(ciphertextBytes); + + // Convert bytes back to string and parse JSON if needed + const decryptedText = new TextDecoder().decode(decrypted); + try { + return JSON.parse(decryptedText); + } catch { + return decryptedText; + } +} + +export type VaultClient = { + baseUrl: string; + publicKey: Uint8Array; +}; + +export async function createVaultClient({ + baseUrl, +}: { + baseUrl: string; +}): Promise { + // Construct the full URL for the fetch call + const url = new URL("api/v1/enclave", baseUrl).toString(); + + type IntrospectionResponse = { + publicKey: string; + }; + + try { + const response = await fetch(url, { + method: "GET", + headers: { + // Indicate we accept JSON responses + Accept: "application/json", + }, + }); + + // fetch doesn't throw on HTTP errors (like 4xx, 5xx) by default. + // Check if the request was successful (status in the range 200-299). + if (!response.ok) { + // You might want more sophisticated error handling here, + // potentially trying to parse an error message from the response body. + throw new Error( + `Failed to fetch enclave public key: ${response.status} ${response.statusText}`, + ); + } + + // Parse the JSON response body + const data = (await response.json()) as IntrospectionResponse; + + if (!data.publicKey) { + throw new Error("Invalid response format: publicKey missing"); + } + + const publicKeyBytes = hexToBytes(data.publicKey); + + return { + baseUrl: baseUrl, // Store baseUrl + publicKey: publicKeyBytes, + }; + } catch (error) { + // Handle network errors or JSON parsing errors + throw new Error(`Failed to fetch enclave public key: ${error}`); // Re-throw or handle as appropriate for your application + } +} + +// ========== Main API function ========== +type SendRequestParams

= { + request: P["input"]; + client: VaultClient; +}; + +async function sendRequest

({ + request, + client, +}: SendRequestParams

): Promise> { + const { encryptedPayload, ephemeralPrivateKey } = encryptForEnclave( + request, + client.publicKey, + ); + + // Construct the full URL using the client's baseUrl + const url = new URL("api/v1/enclave", client.baseUrl).toString(); + + try { + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", // Good practice to specify accept header + }, + // Stringify the JSON payload for the request body + body: JSON.stringify(encryptedPayload), + }); + + // IMPORTANT: Replicate ky's throwHttpErrors: false behavior. + // We proceed to parse the body regardless of response.ok status, + // as the body itself might contain the structured error (UnencryptedErrorResponse) + // or the encrypted success payload. + + let responseData: EncryptedPayload | UnencryptedErrorResponse; + try { + responseData = (await response.json()) as + | EncryptedPayload + | UnencryptedErrorResponse; + } catch (parseError) { + // If JSON parsing fails (e.g., 500 error with HTML body), + // construct a generic error response. + return { + success: false, + data: null, + error: { + code: "FETCH_PARSE_ERROR", + message: `Failed to parse response: ${ + response.status + } ${response.statusText}. ${ + parseError instanceof Error + ? parseError.message + : String(parseError) + }`, + }, + } as Prettify; // Cast needed because error isn't strictly EncryptedError | UnencryptedError + } + + // Now check if the *parsed* response indicates an error + if (isErrorResponse(responseData)) { + console.error("🚨 Error response from enclave:", responseData); + return { + success: false, + data: null, + error: responseData.error, // Use the error from the response body + } as Prettify; + } + + // If it's not an error response, it must be the EncryptedPayload + const decryptedResponse = decryptFromEnclave( + responseData, // No need for 'as EncryptedPayload' if isErrorResponse is accurate + ephemeralPrivateKey, + ); + + // The decrypted response should match the expected success structure P["output"] + // which includes { success: true, data: ..., error: null } + return decryptedResponse as Prettify; + } catch (error) { + // Catch network errors during the fetch itself + return { + success: false, + data: null, + error: { + code: "FETCH_NETWORK_ERROR", + message: + error instanceof Error ? error.message : "Unknown network error", + }, + } as Prettify; // Cast needed + } +} + +// ========== Generic Helper Params ========== +type PayloadParams

= { + request: Prettify>; + client: VaultClient; +}; + +// ========== Helper functions ========== +export function ping({ client, request: options }: PayloadParams) { + return sendRequest({ + request: { + operation: "ping", + ...options, + }, + client, + }); +} + +export function createServiceAccount({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "serviceAccount:create", + ...options, + }, + client, + }); +} + +export function getServiceAccount({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "serviceAccount:get", + ...options, + }, + client, + }); +} + +export function rotateServiceAccount({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "serviceAccount:rotate", + ...options, + }, + client, + }); +} + +export function createEoa({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "eoa:create", + ...options, + }, + client, + }); +} + +export function listEoas({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "eoa:list", + ...options, + }, + client, + }); +} + +export function signTransaction({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "eoa:signTransaction", + ...options, + }, + client, + }); +} + +export function signMessage({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "eoa:signMessage", + ...options, + }, + client, + }); +} + +export function createAccessToken({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "accessToken:create", + ...options, + }, + client, + }); +} + +export function signTypedData< + Types extends TypedData, + PrimaryType extends keyof Types, +>({ + client, + request: options, +}: PayloadParams>) { + return sendRequest>({ + request: { + operation: "eoa:signTypedData", + auth: options.auth, + options: { + from: options.options.from, + typedData: options.options.typedData, + }, + }, + client, + }); +} + +export function revokeAccessToken({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "accessToken:revoke", + ...options, + }, + client, + }); +} + +export function signAuthorization({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "eoa:signAuthorization", + ...options, + }, + client, + }); +} + +export function signStructuredMessage({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "eoa:signStructuredMessage", + ...options, + }, + client, + }); +} + +export function listAccessTokens({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + request: { + operation: "accessToken:list", + ...options, + }, + client, + }); +} + +// --- Constants --- +export const SIGNED_TOKEN_PREFIX = "vt_sat_"; +export const STORED_TOKEN_PREFIX = "vt_act_"; +const DEFAULT_SIGNING_CONTEXT = "encryption"; // Default context for HKDF + +export interface CreateSignedAccessTokenParams { + /** The VaultClient instance (used to get the enclave public key). */ + vaultClient: VaultClient; + /** The base access token string obtained from the createAccessToken API call. */ + baseAccessToken: string; + /** The specific policies to embed in the signed token's claims. */ + additionalPolicies: PolicyComponent[]; + /** The desired expiration time for the signed token (Unix timestamp in seconds). */ + expiryTimestamp: number; + /** Optional: The context string for HKDF key derivation. Defaults to "encryption". MUST match server expectation. */ + signingContext?: string; +} + +/** + * Creates a client-side "signed access token". + * This involves encrypting the baseAccessToken and embedding it, along with + * additional policies and expiry, into a JWT signed using a key derived + * from the baseAccessToken itself. + * + * NOTE: This function is ASYNCHRONOUS because JWT signing using Web Crypto is async. It does not make any network calls to the Vault service. + * + * @param params - The parameters for creating the signed token. + * @returns A Promise resolving to the signed access token string (prefixed). + * @throws If any cryptographic operation or JWT signing fails. + */ +export async function createSignedAccessToken({ + vaultClient, + baseAccessToken, + additionalPolicies, + expiryTimestamp, + signingContext = DEFAULT_SIGNING_CONTEXT, +}: CreateSignedAccessTokenParams): Promise { + if (!vaultClient || !vaultClient.publicKey) { + throw new Error("Vault client or enclave public key is missing."); + } + if (!baseAccessToken) { + throw new Error("Base access token is required."); + } + if (!additionalPolicies) { + throw new Error("Additional policies are required."); + } + if (typeof expiryTimestamp !== "number" || expiryTimestamp <= 0) { + throw new Error("Valid expiry timestamp is required."); + } + + try { + const enclavePublicKey = vaultClient.publicKey; + const contextBytes = new TextEncoder().encode(signingContext); + + // 1. Generate client ephemeral keys for this operation + const clientEphemeralPrivateKey = randomBytes(32); + const clientEphemeralPublicKey = x25519.getPublicKey( + clientEphemeralPrivateKey, + ); + + // 2. Derive shared secret (Client Ephemeral Private Key + Enclave Public Key) + const sharedSecret = x25519.getSharedSecret( + clientEphemeralPrivateKey, + enclavePublicKey, + ); + + // 3. Derive encryption key using HKDF + const encryptionKey = hkdf( + sha256, + sharedSecret, + undefined, // No salt + contextBytes, // Use the provided or default context + 32, // 32 bytes key length + ); + + // 4. Encrypt the base access token string + const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 + const cipher = xchacha20poly1305(encryptionKey, nonce); + const baseTokenBytes = new TextEncoder().encode(baseAccessToken); + const ciphertext = cipher.encrypt(baseTokenBytes); + + // 5. Prepare JWT Signing Key (SHA-256 hash of the base token) + const secretBytes = new TextEncoder().encode(baseAccessToken); + const hashBuffer = await crypto.subtle.digest("SHA-256", secretBytes); + const jwtSigningKey = new Uint8Array(hashBuffer); + + // 6. Prepare JWT Claims + const claims = { + // Match Rust SignedTokenClaims struct (ensure names match server expectation) + exp: expiryTimestamp, + iat: Math.floor(Date.now() / 1000), + encrypted_token: bytesToHex(ciphertext), + nonce: bytesToHex(nonce), + ephemeral_public_key: bytesToHex(clientEphemeralPublicKey), + policies: additionalPolicies, + }; + + // 7. Sign the JWT using HS256 + const jwt = await new jose.SignJWT(claims) + .setProtectedHeader({ alg: "HS256" }) + // .setIssuedAt(claims.iat) // Included in claims + // .setExpirationTime(claims.exp) // Included in claims + .sign(jwtSigningKey); + + // 8. Prepend the prefix + const signedAccessToken = `${SIGNED_TOKEN_PREFIX}${jwt}`; + return signedAccessToken; + } catch (error) { + console.error("Error during signed access token creation:", error); + throw new Error( + `Failed to create signed access token: ${ + error instanceof Error ? error.message : String(error) + }`, + ); + } +} diff --git a/src/lib/vault-sdk/transaction-parser.ts b/src/lib/vault-sdk/transaction-parser.ts new file mode 100644 index 000000000..b1e9ecdbc --- /dev/null +++ b/src/lib/vault-sdk/transaction-parser.ts @@ -0,0 +1,923 @@ +// Update type definitions for our standardized types +import type { + Address, + AccessList, + TxLegacy, + TxEip2930, + TxEip1559, + TxEip4844, + TxEip4844WithSidecar, + TxEip7702, + EthereumTypedTransaction, + SignedAuthorization, +} from "./transaction-types.js"; + +// Custom error class for transaction parsing errors +class ParseTransactionError extends Error { + constructor(message: string) { + super(message); + this.name = "ParseTransactionError"; + } +} + +/** + * Type predicate assert function that helps TypeScript understand + * that the condition guarantees a value is not null or undefined + */ +function assert( + condition: T | null | undefined, + message: string, + // The double negative here (!!) converts the value to a boolean + // while preserving the type information + predicate: (value: T) => boolean = (value) => !!value, +): asserts condition is T { + if (!condition || !predicate(condition)) { + throw new ParseTransactionError(message); + } +} +// Type definitions for client-side data +type Hex = string; + +// Define possible sidecar formats we might receive +type SingleSidecar = { + blobs?: string[]; + commitments?: string[]; + proofs?: string[]; +}; + +type MultipleSidecar = { + blob: string; + commitment: string; + proof: string; +}[]; + +// Client-side transaction input format +type ClientSideSignTransactionOptions = { + type?: string | undefined; + accessList?: + | Array<{ + address: string; + storageKeys: string[]; + }> + | readonly { + address: string; + storageKeys: readonly string[]; + }[] + | undefined; + chainId?: number | bigint | string | undefined; + gasPrice?: bigint | string | undefined; + maxFeePerGas?: bigint | string | undefined; + maxPriorityFeePerGas?: bigint | string | undefined; + data?: Hex | undefined; + input?: Hex | undefined; + to?: string | null | undefined; + nonce?: number | bigint | string | undefined; + value?: bigint | string | undefined; + gas?: bigint | string | number | undefined; + gasLimit?: bigint | string | number | undefined; + authorizationList?: readonly { + address: string; + r: Hex | bigint; + s: Hex | bigint; + // always need either v or yParity. v is only for backwards compatibility + v?: bigint | number | string; + yParity?: number | bigint | string; + nonce: number | bigint | string; + chainId: number | bigint | string; + }[]; + + blobVersionedHashes?: string[] | undefined; + maxFeePerBlobGas?: bigint | string | undefined; + // Direct blob fields + blobs?: string[] | undefined; + commitments?: string[] | undefined; + proofs?: string[] | undefined; + // Sidecar options - could be in different formats + sidecar?: SingleSidecar | undefined; + sidecars?: MultipleSidecar | undefined; +}; + +/** + * Parse client transaction data into standardized transaction format + */ +function parseTransaction( + clientTx: ClientSideSignTransactionOptions, +): EthereumTypedTransaction { + try { + // Normalize and validate basics first + const normalizedTx = { + // Handle string/data field, prioritizing input + input: normalizeInputData(clientTx), + + // Convert nonce to hex string + nonce: normalizeNonce(clientTx), + + // Convert value to hex string + value: normalizeValue(clientTx), + + // Handle to address, null for contract creation + to: normalizeTo(clientTx), + + // Handle gas/gasLimit field, converting to hex + gasLimit: normalizeGasLimit(clientTx), + }; + + // Determine transaction type + let transaction: EthereumTypedTransaction; + + // First check if type is explicitly provided + if (clientTx.type !== undefined) { + const normalizedType = normalizeTypeField(clientTx.type); + transaction = createTransactionFromType( + normalizedType, + clientTx, + normalizedTx, + ); + } else { + // If no type, infer from available fields + transaction = inferTransactionType(clientTx, normalizedTx); + } + + // Final validation + validateTransaction(transaction); + + return transaction; + } catch (error) { + // Ensure all errors are ParseTransactionError + if (error instanceof ParseTransactionError) { + throw error; + } + + throw new ParseTransactionError( + error instanceof Error ? error.message : String(error), + ); + } +} + +/** + * Convert any numeric value to a standardized hex string + */ +function toHexString(value: number | bigint | string | undefined): string { + if (value === undefined) { + return "0x0"; + } + + let bigIntValue: bigint; + + // Convert to BigInt for consistent handling + if (typeof value === "string") { + // Check if it's already a hex string + if (value.startsWith("0x")) { + return value; + } + // Parse decimal string + bigIntValue = BigInt(value); + } else if (typeof value === "number") { + bigIntValue = BigInt(value); + } else { + bigIntValue = value; + } + + // Convert to lowercase hex string with 0x prefix + // biome-ignore lint/style/useTemplate: + return "0x" + bigIntValue.toString(16); +} + +/** + * Normalize the type field to standard hex format (0x00, 0x01, etc.) + */ +function normalizeTypeField(typeValue: string): string { + // Handle hex format (0x0, 0x01, etc.) + if (typeValue.startsWith("0x")) { + const numericPart = typeValue.substring(2); + return `0x${numericPart.padStart(2, "0")}`; + } + + // Handle numeric format (0, 1, etc.) + const numericValue = Number.parseInt(typeValue, 10); + return `0x${numericValue.toString(16).padStart(2, "0")}`; +} + +/** + * Create transaction based on explicit type + */ +function createTransactionFromType( + normalizedType: string, + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): EthereumTypedTransaction { + switch (normalizedType) { + case "0x00": + return createLegacyTransaction(clientTx, normalizedFields); + case "0x01": + return createEip2930Transaction(clientTx, normalizedFields); + case "0x02": + return createEip1559Transaction(clientTx, normalizedFields); + case "0x03": + return createEip4844Transaction(clientTx, normalizedFields); + case "0x05": + return createEip7702Transaction(clientTx, normalizedFields); + default: + throw new ParseTransactionError( + `Unsupported transaction type: ${normalizedType}`, + ); + } +} + +/** + * Infer transaction type based on available fields + */ +function inferTransactionType( + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): EthereumTypedTransaction { + // Check for EIP-4844 specific fields (blob-related) + if (hasBlobFields(clientTx)) { + return createEip4844Transaction(clientTx, normalizedFields); + } + + // Check for EIP-7702 specific fields (authorization list) + if (clientTx.authorizationList) { + return createEip7702Transaction(clientTx, normalizedFields); + } + + // Check for EIP-1559 specific fields (fee market) + if ( + clientTx.maxFeePerGas !== undefined && + clientTx.maxPriorityFeePerGas !== undefined + ) { + return createEip1559Transaction(clientTx, normalizedFields); + } + + // Check for EIP-2930 specific fields (access list + chain ID) + if (clientTx.accessList !== undefined && clientTx.chainId !== undefined) { + return createEip2930Transaction(clientTx, normalizedFields); + } + + // Check for legacy transaction with chainId + if (clientTx.chainId !== undefined) { + return createLegacyTransaction(clientTx, normalizedFields); + } + + // Default to legacy with no chainId + return createLegacyTransaction(clientTx, normalizedFields); +} + +/** + * Check if transaction has blob-related fields (EIP-4844) + */ +function hasBlobFields(clientTx: ClientSideSignTransactionOptions): boolean { + return ( + clientTx.blobVersionedHashes !== undefined || + clientTx.blobs !== undefined || + clientTx.sidecar !== undefined || + clientTx.sidecars !== undefined || + clientTx.maxFeePerBlobGas !== undefined + ); +} + +/** + * Normalize input/data field + */ +function normalizeInputData( + clientTx: ClientSideSignTransactionOptions, +): string { + const { data, input } = clientTx; + + // If both exist, verify they match + if (data !== undefined && input !== undefined) { + // Check if they're effectively the same (considering empty values) + const isDataEmpty = data === "0x" || data === ""; + const isInputEmpty = input === "0x" || input === ""; + + assert( + data === input || (isDataEmpty && isInputEmpty), + "Data and input fields do not match", + ); + + // Prefer input, but use whichever has content + return input || data; + } + + // If only one exists, use that + if (input !== undefined) return input; + if (data !== undefined) return data; + + // Default to empty hex + return "0x"; +} + +/** + * Normalize nonce to hex string + */ +function normalizeNonce(clientTx: ClientSideSignTransactionOptions): string { + const { nonce } = clientTx; + + if (nonce === undefined) { + return "0x0"; // Default nonce as hex + } + + return toHexString(nonce); +} + +/** + * Normalize value to hex string + */ +function normalizeValue(clientTx: ClientSideSignTransactionOptions): string { + const { value } = clientTx; + + if (value === undefined) { + return "0x0"; // Default value as hex + } + + return toHexString(value); +} + +/** + * Normalize to address + */ +function normalizeTo( + clientTx: ClientSideSignTransactionOptions, +): Address | null { + const { to } = clientTx; + + if (to === undefined || to === null) { + return null; // Contract creation + } + + return to as Address; +} + +/** + * Normalize gas limit to hex string + */ +function normalizeGasLimit(clientTx: ClientSideSignTransactionOptions): string { + const { gas, gasLimit } = clientTx; + + // Prefer gasLimit, fall back to gas + const rawGasLimit = gasLimit !== undefined ? gasLimit : gas; + + assert(rawGasLimit, "Gas limit not specified"); + + return toHexString(rawGasLimit); +} + +/** + * Normalize chain ID to hex string + */ +function normalizeChainId( + chainId: number | bigint | string | undefined, +): string | undefined { + if (chainId === undefined) { + return undefined; + } + + return toHexString(chainId); +} + +/** + * Normalize gas price to hex string + */ +function normalizeGasPrice(value: bigint | string | undefined): string { + assert(value, "Gas price value not specified"); + + return toHexString(value); +} + +/** + * Normalize access list + */ +function normalizeAccessList( + clientTx: ClientSideSignTransactionOptions, +): AccessList { + const { accessList } = clientTx; + + // Always return an array, empty if not provided + if (!accessList) { + return []; + } + + return accessList as AccessList; +} + +/** + * Normalizes the authorization list from client format to standardized format + */ +function normalizeAuthorizationList( + clientAuthList?: readonly { + address: string; + r: string | bigint; + s: string | bigint; + v?: bigint | number | string; + yParity?: number | bigint | string; + nonce: number | bigint | string; + chainId: number | bigint | string; + }[], +): SignedAuthorization[] { + if (!clientAuthList || clientAuthList.length === 0) { + throw new ParseTransactionError( + "Authorization list is required and cannot be empty", + ); + } + + return Array.from(clientAuthList).map((auth, index) => { + // Validate required fields + assert(auth.address, `Authorization at index ${index} is missing address`); + assert(auth.r, `Authorization at index ${index} is missing r value`); + assert(auth.s, `Authorization at index ${index} is missing s value`); + assert(auth.chainId, `Authorization at index ${index} is missing chainId`); + + // Get yParity either from yParity field or derived from v + let yParity: number; + + if (auth.yParity !== undefined) { + // Convert yParity to number (0 or 1) + const rawYParity = + typeof auth.yParity === "string" + ? auth.yParity.startsWith("0x") + ? Number.parseInt(auth.yParity, 16) + : Number.parseInt(auth.yParity, 10) + : Number(auth.yParity); + + // Validate yParity is 0 or 1 + if (rawYParity !== 0 && rawYParity !== 1) { + throw new ParseTransactionError( + `Authorization at index ${index} has invalid yParity: must be 0 or 1`, + ); + } + + yParity = rawYParity; + } else if (auth.v !== undefined) { + // Derive yParity from v + // Note: v is either 27/28 (for legacy) or chainId*2 + 35/36 + const v = + typeof auth.v === "string" + ? auth.v.startsWith("0x") + ? BigInt(auth.v) + : BigInt(auth.v) + : BigInt(auth.v); + + // Extract yParity from v + if (v === 27n || v === 28n) { + // Legacy format + yParity = v === 27n ? 0 : 1; + } else { + // EIP-155 format: v = chainId * 2 + 35 + yParity + const chainId = + typeof auth.chainId === "string" + ? auth.chainId.startsWith("0x") + ? BigInt(auth.chainId) + : BigInt(auth.chainId) + : BigInt(auth.chainId); + + const expectedBase = chainId * 2n + 35n; + if (v === expectedBase) { + yParity = 0; + } else if (v === expectedBase + 1n) { + yParity = 1; + } else { + throw new ParseTransactionError( + `Authorization at index ${index} has invalid v value for the given chainId`, + ); + } + } + } else { + throw new ParseTransactionError( + `Authorization at index ${index} is missing both yParity and v`, + ); + } + + return { + address: auth.address as Address, + chainId: toHexString(auth.chainId), + r: toHexString(auth.r), + s: toHexString(auth.s), + yParity, + }; + }); +} + +/** + * Extract and normalize blob data from various possible formats + */ +function extractBlobData(clientTx: ClientSideSignTransactionOptions): { + blobs: string[]; + commitments: string[]; + proofs: string[]; +} | null { + // Direct fields on the transaction + if (clientTx.blobs && clientTx.commitments && clientTx.proofs) { + return { + blobs: clientTx.blobs, + commitments: clientTx.commitments, + proofs: clientTx.proofs, + }; + } + + // Single sidecar object + if (clientTx.sidecar) { + const { blobs, commitments, proofs } = clientTx.sidecar; + if (blobs && commitments && proofs) { + return { blobs, commitments, proofs }; + } + } + + // Multiple sidecars array + if ( + clientTx.sidecars && + Array.isArray(clientTx.sidecars) && + clientTx.sidecars.length > 0 + ) { + const blobs: string[] = []; + const commitments: string[] = []; + const proofs: string[] = []; + + for (const sidecar of clientTx.sidecars) { + if (sidecar.blob && sidecar.commitment && sidecar.proof) { + blobs.push(sidecar.blob); + commitments.push(sidecar.commitment); + proofs.push(sidecar.proof); + } + } + + if (blobs.length > 0 && commitments.length > 0 && proofs.length > 0) { + return { blobs, commitments, proofs }; + } + } + + return null; +} + +/** + * Create a legacy transaction + */ +function createLegacyTransaction( + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): TxLegacy { + const { chainId, gasPrice } = clientTx; + const { input, nonce, value, to, gasLimit } = normalizedFields; + + assert(gasPrice, "Gas price is required for legacy transactions"); + + return { + type: "0x00", + chainId: normalizeChainId(chainId), // Optional for legacy + nonce, + gasPrice: normalizeGasPrice(gasPrice), + gasLimit, + to, + value, + input, + }; +} + +/** + * Create an EIP-2930 transaction + */ +function createEip2930Transaction( + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): TxEip2930 { + const { chainId, gasPrice } = clientTx; + const { input, nonce, value, to, gasLimit } = normalizedFields; + + assert(chainId, "Chain ID is required for EIP-2930 transactions"); + assert(gasPrice, "Gas price is required for EIP-2930 transactions"); + + return { + type: "0x01", + chainId: normalizeChainId(chainId) as string, // Required for EIP-2930 + nonce, + gasPrice: normalizeGasPrice(gasPrice), + gasLimit, + to, + value, + accessList: normalizeAccessList(clientTx), + input, + }; +} + +/** + * Create an EIP-1559 transaction + */ +function createEip1559Transaction( + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): TxEip1559 { + const { chainId, maxFeePerGas, maxPriorityFeePerGas } = clientTx; + const { input, nonce, value, to, gasLimit } = normalizedFields; + + assert(chainId, "Chain ID is required for EIP-1559 transactions"); + assert(maxFeePerGas, "Max fee per gas is required for EIP-1559 transactions"); + assert( + maxPriorityFeePerGas, + "Max priority fee per gas is required for EIP-1559 transactions", + ); + + return { + type: "0x02", + chainId: normalizeChainId(chainId) as string, + nonce, + gasLimit, + maxFeePerGas: normalizeGasPrice(maxFeePerGas), + maxPriorityFeePerGas: normalizeGasPrice(maxPriorityFeePerGas), + to, + value, + accessList: normalizeAccessList(clientTx), // Always provide access list, empty array if not specified + input, + }; +} + +/** + * Create an EIP-4844 transaction + */ +function createEip4844Transaction( + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): TxEip4844 | TxEip4844WithSidecar { + const { + chainId, + maxFeePerGas, + maxPriorityFeePerGas, + blobVersionedHashes, + maxFeePerBlobGas, + } = clientTx; + const { input, nonce, value, gasLimit } = normalizedFields; + const { to } = normalizedFields; + + // Validate required fields + assert(to !== null, "EIP-4844 transactions require a valid to address"); + assert(chainId, "Chain ID is required for EIP-4844 transactions"); + assert(maxFeePerGas, "Max fee per gas is required for EIP-4844 transactions"); + assert( + maxPriorityFeePerGas, + "Max priority fee per gas is required for EIP-4844 transactions", + ); + assert( + blobVersionedHashes, + "Blob versioned hashes are required for EIP-4844 transactions", + ); + assert( + maxFeePerBlobGas, + "Max fee per blob gas is required for EIP-4844 transactions", + ); + + // Base transaction without sidecar + const baseTransaction: TxEip4844 = { + type: "0x03", + chainId: normalizeChainId(chainId) as string, + nonce, + gasLimit, + maxFeePerGas: normalizeGasPrice(maxFeePerGas), + maxPriorityFeePerGas: normalizeGasPrice(maxPriorityFeePerGas), + to: to as Address, + value, + accessList: normalizeAccessList(clientTx), + blobVersionedHashes, + maxFeePerBlobGas: normalizeGasPrice(maxFeePerBlobGas), + input, + }; + + // Check for blob data in any of the possible formats + const blobData = extractBlobData(clientTx); + + // If we have blob data, include it flattened in the transaction + if (blobData) { + return { + ...baseTransaction, + ...blobData, + } as TxEip4844WithSidecar; + } + + return baseTransaction; +} + +/** + * Create an EIP-7702 transaction + */ +function createEip7702Transaction( + clientTx: ClientSideSignTransactionOptions, + normalizedFields: { + input: string; + nonce: string; + value: string; + to: Address | null; + gasLimit: string; + }, +): TxEip7702 { + const { chainId, maxFeePerGas, maxPriorityFeePerGas, authorizationList } = + clientTx; + const { input, nonce, value, gasLimit } = normalizedFields; + const { to } = normalizedFields; + + // Validations + assert(to !== null, "EIP-7702 transactions require a valid to address"); + assert(chainId, "Chain ID is required for EIP-7702 transactions"); + assert(maxFeePerGas, "Max fee per gas is required for EIP-7702 transactions"); + assert( + maxPriorityFeePerGas, + "Max priority fee per gas is required for EIP-7702 transactions", + ); + assert( + authorizationList, + "Authorization list is required for EIP-7702 transactions", + ); + + return { + type: "0x05", + chainId: normalizeChainId(chainId) as string, + nonce, + gasLimit, + maxFeePerGas: normalizeGasPrice(maxFeePerGas), + maxPriorityFeePerGas: normalizeGasPrice(maxPriorityFeePerGas), + to: to as Address, + value, + accessList: normalizeAccessList(clientTx), + authorizationList: normalizeAuthorizationList(authorizationList), + input, + }; +} + +/** + * Validate that a transaction has all required fields + */ +function validateTransaction(transaction: EthereumTypedTransaction): void { + // Common validations for all transaction types + assert(transaction.nonce, "Transaction nonce is required"); + assert(transaction.value, "Transaction value is required"); + assert(transaction.input, "Transaction input is required"); + + // Type-specific validations + switch (transaction.type) { + case "0x00": // Legacy + validateLegacyTransaction(transaction as TxLegacy); + break; + + case "0x01": // EIP-2930 + validateEip2930Transaction(transaction as TxEip2930); + break; + + case "0x02": // EIP-1559 + validateEip1559Transaction(transaction as TxEip1559); + break; + + case "0x03": // EIP-4844 + // Determine if it has sidecar data + if ("blobs" in transaction) { + validateEip4844WithSidecarTransaction( + transaction as TxEip4844WithSidecar, + ); + } else { + validateEip4844Transaction(transaction as TxEip4844); + } + break; + + case "0x05": // EIP-7702 + validateEip7702Transaction(transaction as TxEip7702); + break; + + default: + throw new ParseTransactionError( + `Unknown transaction type: ${transaction}`, + ); + } +} + +/** + * Validate legacy transaction + */ +function validateLegacyTransaction(tx: TxLegacy): void { + assert(tx.gasPrice, "Legacy transaction requires gasPrice"); + assert(tx.gasLimit, "Legacy transaction requires gasLimit"); +} + +/** + * Validate EIP-2930 transaction + */ +function validateEip2930Transaction(tx: TxEip2930): void { + assert(tx.chainId, "EIP-2930 transaction requires chainId"); + assert(tx.gasPrice, "EIP-2930 transaction requires gasPrice"); + assert(tx.gasLimit, "EIP-2930 transaction requires gasLimit"); + assert(tx.accessList, "EIP-2930 transaction requires accessList"); +} + +/** + * Validate EIP-1559 transaction + */ +function validateEip1559Transaction(tx: TxEip1559): void { + assert(tx.chainId, "EIP-1559 transaction requires chainId"); + assert(tx.maxFeePerGas, "EIP-1559 transaction requires maxFeePerGas"); + assert( + tx.maxPriorityFeePerGas, + "EIP-1559 transaction requires maxPriorityFeePerGas", + ); + assert(tx.gasLimit, "EIP-1559 transaction requires gasLimit"); + assert(tx.accessList, "EIP-1559 transaction requires accessList"); +} + +/** + * Validate EIP-4844 transaction + */ +function validateEip4844Transaction(tx: TxEip4844): void { + assert(tx.chainId, "EIP-4844 transaction requires chainId"); + assert(tx.maxFeePerGas, "EIP-4844 transaction requires maxFeePerGas"); + assert( + tx.maxPriorityFeePerGas, + "EIP-4844 transaction requires maxPriorityFeePerGas", + ); + assert(tx.gasLimit, "EIP-4844 transaction requires gasLimit"); + assert(tx.accessList, "EIP-4844 transaction requires accessList"); + assert( + tx.blobVersionedHashes, + "EIP-4844 transaction requires blobVersionedHashes", + ); + assert(tx.maxFeePerBlobGas, "EIP-4844 transaction requires maxFeePerBlobGas"); +} + +/** + * Validate EIP-4844 transaction with sidecar + */ +function validateEip4844WithSidecarTransaction(tx: TxEip4844WithSidecar): void { + // First validate base EIP-4844 fields + validateEip4844Transaction(tx); + + // Then validate sidecar fields + assert( + tx.blobs && tx.blobs.length > 0, + "EIP-4844 transaction with sidecar requires blobs", + ); + assert( + tx.commitments && tx.commitments.length > 0, + "EIP-4844 transaction with sidecar requires commitments", + ); + assert( + tx.proofs && tx.proofs.length > 0, + "EIP-4844 transaction with sidecar requires proofs", + ); + + // Check counts match + assert( + tx.blobs.length === tx.commitments.length && + tx.blobs.length === tx.proofs.length, + "EIP-4844 transaction with sidecar requires matching counts of blobs, commitments, and proofs", + ); +} + +/** + * Validate EIP-7702 transaction + */ +function validateEip7702Transaction(tx: TxEip7702): void { + assert(tx.chainId, "EIP-7702 transaction requires chainId"); + assert(tx.maxFeePerGas, "EIP-7702 transaction requires maxFeePerGas"); + assert( + tx.maxPriorityFeePerGas, + "EIP-7702 transaction requires maxPriorityFeePerGas", + ); + assert(tx.gasLimit, "EIP-7702 transaction requires gasLimit"); + assert(tx.accessList, "EIP-7702 transaction requires accessList"); + assert( + tx.authorizationList, + "EIP-7702 transaction requires non-empty authorizationList", + () => tx.authorizationList.length > 0, + ); +} + +// Export the main parser and error type +export { parseTransaction, ParseTransactionError }; diff --git a/src/lib/vault-sdk/transaction-types.ts b/src/lib/vault-sdk/transaction-types.ts new file mode 100644 index 000000000..a30d68fbb --- /dev/null +++ b/src/lib/vault-sdk/transaction-types.ts @@ -0,0 +1,144 @@ +// Basic types that will be used across transactions +type Address = string; +type ChainId = string; // Hex string for chain ID +type Bytes = string; // Hex string +type U256 = string; // Hex string for big numbers +type B256 = string; // 32-byte hash as hex string +type Bytes48 = string; // 48-byte value as hex string + +// Common transaction destination type (address or contract creation) +type TxKind = Address | null; // null represents contract creation + +// Access list for EIP-2930 and later +type AccessListEntry = { + address: Address; + storageKeys: string[]; // Array of hex strings representing storage keys +}; +type AccessList = AccessListEntry[]; + +// Authorization for EIP-7702 +type SignedAuthorization = { + chainId: U256; + address: Address; + r: U256; + s: U256; + yParity: number; // 0 or 1 +}; + +// Blob structures for EIP-4844 +type Blob = string; // Raw data as string + +type BlobTransactionSidecar = { + blobs: Blob[]; + commitments: Bytes48[]; + proofs: Bytes48[]; +}; + +// Legacy transaction (pre-EIP-2930) +type TxLegacy = { + type: "0x00"; // Legacy + chainId?: ChainId; // Optional for legacy transactions + nonce: string; // Hex string + gasPrice: string; // Hex string + gasLimit: string; // Hex string + to: TxKind; + value: U256; + input: Bytes; +}; + +// EIP-2930 transaction +type TxEip2930 = { + type: "0x01"; // EIP-2930 + chainId: ChainId; + nonce: string; // Hex string + gasPrice: string; // Hex string + gasLimit: string; // Hex string + to: TxKind; + value: U256; + accessList: AccessList; + input: Bytes; +}; + +// EIP-1559 transaction +type TxEip1559 = { + type: "0x02"; // EIP-1559 + chainId: ChainId; + nonce: string; // Hex string + gasLimit: string; // Hex string + maxFeePerGas: string; // Hex string + maxPriorityFeePerGas: string; // Hex string + to: TxKind; + value: U256; + accessList: AccessList; + input: Bytes; +}; + +// EIP-7702 transaction +type TxEip7702 = { + type: "0x05"; // EIP-7702 + chainId: ChainId; + nonce: string; // Hex string + gasLimit: string; // Hex string + maxFeePerGas: string; // Hex string + maxPriorityFeePerGas: string; // Hex string + to: Address; // Note: different from others, only Address not TxKind + value: U256; + accessList: AccessList; + authorizationList: SignedAuthorization[]; + input: Bytes; +}; + +// Basic EIP-4844 transaction +type TxEip4844 = { + type: "0x03"; // EIP-4844 + chainId: ChainId; + nonce: string; // Hex string + gasLimit: string; // Hex string + maxFeePerGas: string; // Hex string + maxPriorityFeePerGas: string; // Hex string + to: Address; // Note: only Address not TxKind + value: U256; + accessList: AccessList; + blobVersionedHashes: B256[]; + maxFeePerBlobGas: string; // Hex string + input: Bytes; +}; + +// EIP-4844 transaction with sidecar - flattened format +type TxEip4844WithSidecar = TxEip4844 & { + // Flattened sidecar fields + blobs: string[]; + commitments: Bytes48[]; + proofs: Bytes48[]; +}; + +// Union type for all Ethereum transaction types +type EthereumTypedTransaction = + | TxLegacy + | TxEip2930 + | TxEip1559 + | TxEip4844 + | TxEip4844WithSidecar + | TxEip7702; + +export type { + Address, + ChainId, + Bytes, + U256, + B256, + Bytes48, + TxKind, + AccessListEntry, + AccessList, + SignedAuthorization, + Blob, + BlobTransactionSidecar, + TxLegacy, + TxEip2930, + TxEip1559, + TxEip7702, + TxEip4844, + TxEip4844WithSidecar, + EthereumTypedTransaction, +}; diff --git a/src/lib/vault-sdk/types.ts b/src/lib/vault-sdk/types.ts new file mode 100644 index 000000000..0b50d2ea8 --- /dev/null +++ b/src/lib/vault-sdk/types.ts @@ -0,0 +1,583 @@ +import type { + Address, + TypedData, + TypedDataDomain, + TypedDataToPrimitiveTypes, +} from "abitype"; +import type { EthereumTypedTransaction } from "./transaction-types.js"; + +export type Prettify = { + [K in keyof T]: T[K]; +} & {}; + +// Encrypted types +export type EncryptedPayload = { + ephemeralPublicKey: string; + nonce: string; + ciphertext: string; +}; + +// ========== Authentication Types ========== +type AdminKeyAuth = { + adminKey: string; +}; + +type AccessTokenAuth = { + accessToken: string; +}; + +type SessionTokenAuth = { + sessionToken: string; +}; + +// Regular Auth union (excluding RotationCodeAuth) +export type Auth = AdminKeyAuth | AccessTokenAuth | SessionTokenAuth; + +// Separate RotationCodeAuth (used only for rotation) +type RotationCodeAuth = { + rotationCode: string; +}; + +// ========== Base Types ========== +// Represents Address, Bytes, U256, I256 as strings for broad compatibility +type Bytes = string; // e.g., "0x..." +// type HexString = string; // Generic hex string +type BigNumberString = string; // String representation of U256/I256 + +type UnencryptedError = { + message: string; + status: number; + type: string; + details?: string; +}; + +export type UnencryptedErrorResponse = { + error: UnencryptedError; +}; + +type EncryptedError = { + code: string; + message: string; + details?: string; +}; + +type GenericSuccessResponse = { + success: true; + data: Data; + error: null; +}; + +type GenericErrorResponse = { + success: false; + data: null; + error: EncryptedError | UnencryptedError; +}; + +export type VaultError = EncryptedError | UnencryptedError; + +type GenericResponse = + | GenericSuccessResponse + | GenericErrorResponse; + +// ========== Payload Type ========== +export type OmitNever = { + [K in keyof T as T[K] extends never ? never : K]: T[K]; +}; + +export type GenericPayload< + T extends { + operation: string; + auth?: Auth | RotationCodeAuth | never; + options?: Record | never; + data: unknown; + }, +> = { + input: OmitNever<{ + operation: T["operation"]; + options: T["options"]; + auth: T["auth"]; + }>; + output: GenericResponse; +}; + +// ========== Options Types ========== +type CreateServiceAccountOptions = { + metadata: Record; +}; + +type MetadataValue = string | number | boolean; + +type CreateEoaOptions = { + metadata: Record; +}; + +type GetEoasOptions = { + page?: number; + pageSize?: number; +}; + +type PingOptions = { + message: string; +}; + +type SignTransactionOptions = { + transaction: EthereumTypedTransaction; + from: string; +}; + +export type SignAuthorizationOptions = { + from: Address; + authorization: Authorization; // Use the defined type +}; + +export type SignStructuredMessageOptions = { + from: Address; + structuredMessage: StructuredMessageInput; // Use the defined type + chainId?: number; // Keep as number for ChainId +}; + +export type GetAccessTokensOptions = { + page?: number; + pageSize?: number; +}; + +type SignMessageOptions = { + message: string; + from: string; + chainId?: number; + format?: "text" | "hex"; +}; + +type CheckedSignTypedDataOptions< + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, +> = { + typedData: { + domain: TypedDataDomain; + types: Types; + primaryType: PrimaryType; + message: TypedDataToPrimitiveTypes[PrimaryType]; + }; + from: string; +}; + +// biome-ignore lint/suspicious/noExplicitAny: +type SignedTypedDataOptions = CheckedSignTypedDataOptions; + +// ========== User Operation Types ========== + +// Corresponds to Rust UserOperationV06Input +export type UserOperationV06Input = { + sender: Address; + nonce: BigNumberString; // U256 + initCode?: Bytes; // Optional due to #[serde(default)] + callData: Bytes; + callGasLimit: BigNumberString; // U256 + verificationGasLimit: BigNumberString; // U256 + preVerificationGas: BigNumberString; // U256 + maxFeePerGas: BigNumberString; // U256 + maxPriorityFeePerGas: BigNumberString; // U256 + paymasterAndData?: Bytes; // Optional due to #[serde(default)] + signature?: Bytes; // Optional due to #[serde(default)] + entrypoint?: Address; // Optional due to #[serde(default = ...)] +}; + +// Corresponds to Rust UserOperationV07Input +export type UserOperationV07Input = { + sender: Address; + nonce: BigNumberString; // U256 + factory?: Address; // Optional due to #[serde(default)] + factoryData?: Bytes; // Optional due to #[serde(default)] + callData: Bytes; + callGasLimit: BigNumberString; // U256 + verificationGasLimit: BigNumberString; // U256 + preVerificationGas: BigNumberString; // U256 + maxFeePerGas: BigNumberString; // U256 + maxPriorityFeePerGas: BigNumberString; // U256 + paymaster?: Address; // Optional due to #[serde(default)] + paymasterData?: Bytes; // Optional due to #[serde(default)] - Assuming default is empty bytes + paymasterVerificationGasLimit?: BigNumberString; // U256 - Assuming default is 0 + paymasterPostOpGasLimit?: BigNumberString; // U256 - Assuming default is 0 + signature?: Bytes; // Optional due to #[serde(default)] + entrypoint?: Address; // Optional due to #[serde(default = ...)] +}; + +// Corresponds to Rust StructuredMessageInput enum +export type StructuredMessageInput = + | { useropV06: UserOperationV06Input } + | { useropV07: UserOperationV07Input }; + +// ========== Policy Types ========== +type RegexRule = { + pattern: string; +}; + +type NumberRuleOp = "greaterThan" | "lessThan" | "equalTo"; + +type NumberRule = { + op: NumberRuleOp; + value: number | BigNumberString; +}; + +export type Rule = NumberRule | RegexRule; + +type MetadataRule = { + key: string; + rule: Rule; +}; + +// ========== Policy Rule Structs ========== + +// Corresponds to Rust UserOperationV06Rules +export type UserOperationV06Rules = { + sender?: Rule; + nonce?: Rule; + initCode?: Rule; + callData?: Rule; + callGasLimit?: Rule; + verificationGasLimit?: Rule; + preVerificationGas?: Rule; + maxFeePerGas?: Rule; + maxPriorityFeePerGas?: Rule; + paymasterAndData?: Rule; + chainId?: Rule; + entrypoint?: Rule; // Optional, but Rust has a default func +}; + +// Corresponds to Rust UserOperationV07Rules +export type UserOperationV07Rules = { + sender?: Rule; + nonce?: Rule; + factory?: Rule; + factoryData?: Rule; + callData?: Rule; + callGasLimit?: Rule; + verificationGasLimit?: Rule; + preVerificationGas?: Rule; + maxFeePerGas?: Rule; + maxPriorityFeePerGas?: Rule; + paymaster?: Rule; + paymasterVerificationGasLimit?: Rule; + paymasterPostOpGasLimit?: Rule; + paymasterData?: Rule; + chainId?: Rule; + entrypoint?: Rule; // Optional, but Rust has a default func +}; + +// Corresponds to Rust SignAuthorizationRules +export type SignAuthorizationRules = { + chainId?: Rule; + nonce?: Rule; + address?: Rule; +}; + +export type PolicyComponent = + | { + type: "eoa:create"; + requiredMetadataPatterns?: MetadataRule[]; + allowedMetadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:read"; + metadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:signTransaction"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + payloadPatterns: Record; + } + | { + type: "eoa:signMessage"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + chainId?: number; + messagePattern?: string; + } + | { + type: "eoa:signTypedData"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:signAuthorization"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + payloadPatterns?: SignAuthorizationRules; + } + | { + type: "eoa:signStructuredMessage"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + // Define how UserOp rules are applied, e.g., separate for v6/v7 + structuredPatterns: { + useropV06?: UserOperationV06Rules; + useropV07?: UserOperationV07Rules; + }; + }; + +type OwnerType = string; // Define based on your eoa models + +type CreateAccessTokenOptions = { + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; +}; + +type RevokeAccessTokenOptions = { + id: string; // UUID +}; + +// ========== Authorization Types ========== + +// Corresponds to Rust Authorization struct +export type Authorization = { + chainId: BigNumberString; // U256 + address: Address; + nonce: number; // u64 +}; + +// Corresponds to Rust SignedAuthorization struct +// Merges Authorization fields due to #[serde(flatten)] +export type SignedAuthorization = Authorization & { + yParity: number; // U8 (typically 0 or 1) + r: BigNumberString; // U256 + s: BigNumberString; // U256 +}; + +// ========== Response Data Types ========== +type PingData = { + timestamp: number; + pong: string; +}; + +type CreateServiceAccountData = { + id: string; // UUID + adminKey: string; + rotationCode: string; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string +}; + +type GetServiceAccountData = { + id: string; // UUID + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string +}; + +type RotateServiceAccountData = { + newAdminKey: string; + newRotationCode: string; +}; + +type EoaData = { + id: string; // UUID + address: string; + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string +}; + +type GetEoasData = { + items: EoaData[]; + page: number; + pageSize: number; + totalRecords: number; +}; + +type SignTransactionData = { + signature: string; +}; + +type SignMessageData = { + signature: string; +}; + +type SignTypedDataData = { + signature: string; +}; + +type CreateAccessTokenData = { + accessToken: string; + id: string; // UUID + issuerId: string; // UUID + issuerType: OwnerType; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string + revokedAt?: string; // ISO date string +}; + +type RevokeAccessTokenData = { + id: string; // UUID + issuerId: string; // UUID + issuerType: OwnerType; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string + revokedAt?: string; // ISO date string +}; + +// Update SignAuthorizationData to use the defined SignedAuthorization type +export type SignAuthorizationData = { + signedAuthorization: SignedAuthorization; // Use the defined type +}; + +// Add SignStructuredMessageData (as defined previously) +export type SignStructuredMessageData = { + signature: Bytes; + message: string; // This likely represents the UserOp hash in Rust +}; + +// Add AccessTokenData (as defined previously, ensure OwnerType/MetadataValue are correct) +export type AccessTokenData = { + id: string; // UUID + issuerId: string; // UUID + issuerType: OwnerType; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string + revokedAt?: string | null; // ISO date string or null +}; + +// Add GetAccessTokensData (as defined previously) +export type GetAccessTokensData = { + items: AccessTokenData[]; + page: number; + pageSize: number; + totalRecords: number; // Rust uses u64, TS uses number +}; + +// ========== Operation Payloads ========== +export type PingPayload = GenericPayload<{ + operation: "ping"; + options: PingOptions; + auth: never; + data: PingData; +}>; + +export type CreateServiceAccountPayload = GenericPayload<{ + operation: "serviceAccount:create"; + options: CreateServiceAccountOptions; + auth: never; + data: CreateServiceAccountData; +}>; + +export type GetServiceAccountPayload = GenericPayload<{ + operation: "serviceAccount:get"; + options: never; + auth: Auth; + data: GetServiceAccountData; +}>; + +export type RotateServiceAccountPayload = GenericPayload<{ + operation: "serviceAccount:rotate"; + options: never; + auth: RotationCodeAuth; // Only accepts RotationCodeAuth + data: RotateServiceAccountData; +}>; + +export type CreateEoaPayload = GenericPayload<{ + operation: "eoa:create"; + auth: Auth; + options: CreateEoaOptions; + data: EoaData; +}>; + +export type ListEoaPayload = GenericPayload<{ + operation: "eoa:list"; + auth: Auth; + options: GetEoasOptions; + data: GetEoasData; +}>; + +export type SignTransactionPayload = GenericPayload<{ + operation: "eoa:signTransaction"; + auth: Auth; + options: SignTransactionOptions; + data: SignTransactionData; +}>; + +export type SignAuthorizationPayload = GenericPayload<{ + operation: "eoa:signAuthorization"; + auth: Auth; // Assuming Auth is defined as before + options: SignAuthorizationOptions; + data: SignAuthorizationData; +}>; + +// Add SignStructuredMessagePayload (using defined types) +export type SignStructuredMessagePayload = GenericPayload<{ + operation: "eoa:signStructuredMessage"; + auth: Auth; // Assuming Auth is defined as before + options: SignStructuredMessageOptions; + data: SignStructuredMessageData; +}>; + +export type CheckedSignTypedDataPayload< + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, +> = GenericPayload<{ + operation: "eoa:signTypedData"; + auth: Auth; + options: CheckedSignTypedDataOptions; + data: SignTypedDataData; +}>; + +export type SignTypedDataPayload = GenericPayload<{ + operation: "eoa:signTypedData"; + auth: Auth; + options: SignedTypedDataOptions; + data: SignTypedDataData; +}>; + +export type SignMessagePayload = GenericPayload<{ + operation: "eoa:signMessage"; + auth: Auth; + options: SignMessageOptions; + data: SignMessageData; +}>; + +export type CreateAccessTokenPayload = GenericPayload<{ + operation: "accessToken:create"; + auth: Auth; + options: CreateAccessTokenOptions; + data: CreateAccessTokenData; +}>; + +// Add ListAccessTokensPayload (using defined types) +export type ListAccessTokensPayload = GenericPayload<{ + operation: "accessToken:list"; + auth: Auth; + data: GetAccessTokensData; +}>; + +export type RevokeAccessTokenPayload = GenericPayload<{ + operation: "accessToken:revoke"; + auth: Auth; + options: RevokeAccessTokenOptions; + data: RevokeAccessTokenData; +}>; + +// ========== Union of all payloads ========== +export type Payload = + | PingPayload + | CreateServiceAccountPayload + | GetServiceAccountPayload + | RotateServiceAccountPayload + | CreateEoaPayload + | ListEoaPayload + | SignTransactionPayload + | SignMessagePayload + | SignTypedDataPayload + | CreateAccessTokenPayload + | RevokeAccessTokenPayload + | SignAuthorizationPayload + | SignStructuredMessagePayload + | ListAccessTokensPayload; diff --git a/src/lib/webhooks/send-webhook.ts b/src/lib/webhooks/send-webhook.ts new file mode 100644 index 000000000..70d1f4948 --- /dev/null +++ b/src/lib/webhooks/send-webhook.ts @@ -0,0 +1,177 @@ +import assert from "node:assert"; +import crypto, { randomUUID, createHmac } from "node:crypto"; +import { Agent, fetch, type HeadersInit } from "undici"; +import type { WebhookDbEntry } from "../../db/types.js"; +import { env } from "../env.js"; +import { ResultAsync } from "neverthrow"; +import type { WebhookErr } from "../errors.js"; +import { config } from "../config.js"; + +function generateSignature( + body: Record, + timestampSeconds: number, + secret: string, +): string { + const _body = JSON.stringify(body); + const payload = `${timestampSeconds}.${_body}`; + return crypto.createHmac("sha256", secret).update(payload).digest("hex"); +} + +function generateAuthorization(args: { + webhook: WebhookDbEntry; + timestamp: Date; + body: Record; +}): string { + const { webhook, timestamp, body } = args; + + if (env.ENABLE_CUSTOM_HMAC_AUTH) { + assert( + env.CUSTOM_HMAC_AUTH_CLIENT_ID, + 'Missing "CUSTOM_HMAC_AUTH_CLIENT_ID".', + ); + assert( + env.CUSTOM_HMAC_AUTH_CLIENT_SECRET, + 'Missing "CUSTOM_HMAC_AUTH_CLIENT_SECRET"', + ); + + return generateSecretHmac256({ + webhookUrl: webhook.url, + body, + timestamp, + nonce: randomUUID(), + clientId: env.CUSTOM_HMAC_AUTH_CLIENT_ID, + clientSecret: env.CUSTOM_HMAC_AUTH_CLIENT_SECRET, + }); + } + + return `Bearer ${webhook.secret}`; +} + +export function generateRequestHeaders(args: { + webhook: WebhookDbEntry; + body: Record; + timestamp: Date; +}): HeadersInit { + const { webhook, body, timestamp } = args; + + const timestampSeconds = Math.floor(timestamp.getTime() / 1000); + const signature = generateSignature(body, timestampSeconds, webhook.secret); + const authorization = generateAuthorization({ webhook, timestamp, body }); + return { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: authorization, + "x-engine-signature": signature, + "x-engine-timestamp": timestampSeconds.toString(), + }; +} + +export interface WebhookResponse { + ok: boolean; + status: number; + body: string; +} + +export function sendWebhookRequest( + webhook: WebhookDbEntry, + body: Record, +): ResultAsync { + // Setup mTLS dispatcher outside the promise + const headers = generateRequestHeaders({ + webhook, + body, + timestamp: new Date(), + }); + + const dispatcher = + config.decrypted.mtlsCertificate && config.decrypted.mtlsPrivateKey + ? new Agent({ + connect: { + cert: config.decrypted.mtlsCertificate, + key: config.decrypted.mtlsPrivateKey, + rejectUnauthorized: true, + }, + }) + : undefined; + + return ResultAsync.fromPromise( + fetch(webhook.url, { + method: "POST", + headers, + body: JSON.stringify(body), + dispatcher, + }).then(async (resp) => ({ + ok: resp.ok, + status: resp.status, + body: await resp.text(), + })), + (error): WebhookErr => ({ + kind: "webhook", + code: "request_failed", + status: 500, + source: error instanceof Error ? error : undefined, + }), + ); +} + +/** + * Generates an HMAC-256 secret to set in the "Authorization" header. + * + * @param webhookUrl - The URL to call. + * @param body - The request body. + * @param timestamp - The request timestamp. + * @param nonce - A unique string for this request. Should not be re-used. + * @param clientId - Your application's client id. + * @param clientSecret - Your application's client secret. + * @returns + */ +export function generateSecretHmac256(args: { + webhookUrl: string; + body: Record; + timestamp: Date; + nonce: string; + clientId: string; + clientSecret: string; +}): string { + const { webhookUrl, body, timestamp, nonce, clientId, clientSecret } = args; + + // Create the body hash by hashing the payload. + const bodyHash = createHmac("sha256", clientSecret) + .update(JSON.stringify(body), "utf8") + .digest("base64"); + + // Create the signature hash by hashing the signature. + const ts = timestamp.getTime(); // timestamp expected in milliseconds + const httpMethod = "POST"; + const url = new URL(webhookUrl); + const resourcePath = url.pathname; + const host = url.hostname; + const port = url.port + ? Number.parseInt(url.port) + : url.protocol === "https:" + ? 443 + : 80; + + const signature = [ + ts, + nonce, + httpMethod, + resourcePath, + host, + port, + bodyHash, + "", // to insert a newline at the end + ].join("\n"); + + const signatureHash = createHmac("sha256", clientSecret) + .update(signature, "utf8") + .digest("base64"); + + return [ + `MAC id="${clientId}"`, + `ts="${ts}"`, + `nonce="${nonce}"`, + `bodyhash="${bodyHash}"`, + `mac="${signatureHash}"`, + ].join(","); +} diff --git a/src/lib/zod.ts b/src/lib/zod.ts new file mode 100644 index 000000000..58e3b4350 --- /dev/null +++ b/src/lib/zod.ts @@ -0,0 +1,45 @@ +import { getAddress, type Address, type Hex } from "thirdweb"; +import * as z from "zod"; + +/** + * Use the Zod schema to validate the EVM address. + * Uses getAddress from thirdweb/utils to validate the address. + */ +export const exampleEvmAddress = + "0xeb0effdfb4dc5b3d5d3ac6ce29f3ed213e95d675" as const; + +export const exampleBaseSepoliaUsdcAddress = + "0x036CbD53842c5426634e7929541eC2318f3dCF7e" as const; + +export const evmAddressSchema = z + .string() + .superRefine((address, ctx): address is Address => { + try { + getAddress(address); + } catch { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "Invalid EVM address format", + }); + } + return z.NEVER; + }) + .openapi({ + description: "EVM address in hex format", + example: exampleEvmAddress, + }); + +export const hexSchema = z + .string() + .regex(/^0x([0-9a-fA-F]*)$/) as z.ZodType; + +export const timestampsSchema = z.object({ + createdAt: z.string().openapi({ + description: "The timestamp of when this entity was created", + example: "2023-01-01T00:00:00.000Z", + }), + updatedAt: z.string().openapi({ + description: "The timestamp of when the entity was last updated", + example: "2023-01-01T00:00:00.000Z", + }), +}); diff --git a/src/polyfill.ts b/src/polyfill.ts deleted file mode 100644 index f1df8ef43..000000000 --- a/src/polyfill.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as crypto from "node:crypto"; - -if (typeof globalThis.crypto === "undefined") { - // @ts-expect-error - globalThis.crypto = crypto; -} diff --git a/src/prisma/migrations/20230913025746_init/migration.sql b/src/prisma/migrations/20230913025746_init/migration.sql deleted file mode 100644 index 980a768bd..000000000 --- a/src/prisma/migrations/20230913025746_init/migration.sql +++ /dev/null @@ -1,61 +0,0 @@ --- CreateTable -CREATE TABLE "transactions" ( - "id" TEXT NOT NULL, - "chainId" INTEGER NOT NULL, - "fromAddress" TEXT NOT NULL, - "toAddress" TEXT, - "data" TEXT, - "value" TEXT, - "nonce" INTEGER, - "gasLimit" TEXT, - "gasPrice" TEXT, - "maxFeePerGas" TEXT, - "maxPriorityFeePerGas" TEXT, - "transactionType" INTEGER, - "transactionHash" TEXT, - "functionName" TEXT, - "functionArgs" TEXT, - "extension" TEXT, - "deployedContractAddress" TEXT, - "deployedContractType" TEXT, - "queuedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "processedAt" TIMESTAMP(3), - "sentAt" TIMESTAMP(3), - "minedAt" TIMESTAMP(3), - "retryCount" INTEGER NOT NULL DEFAULT 0, - "retryGasValues" BOOLEAN DEFAULT false, - "retryMaxPriorityFeePerGas" TEXT, - "retryMaxFeePerGas" TEXT, - "errorMessage" TEXT, - "sentAtBlockNumber" INTEGER, - "blockNumber" INTEGER, - - CONSTRAINT "transactions_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "wallet_details" ( - "address" TEXT NOT NULL, - "type" TEXT NOT NULL, - "awsKmsKeyId" TEXT, - "awsKmsArn" TEXT, - "gcpKmsKeyRingId" VARCHAR(50), - "gcpKmsKeyId" VARCHAR(50), - "gcpKmsKeyVersionId" VARCHAR(20), - "gcpKmsLocationId" VARCHAR(20), - "gcpKmsResourcePath" TEXT, - - CONSTRAINT "wallet_details_pkey" PRIMARY KEY ("address") -); - --- CreateTable -CREATE TABLE "wallet_nonce" ( - "address" TEXT NOT NULL, - "chainId" INTEGER NOT NULL, - "nonce" INTEGER NOT NULL DEFAULT 0, - - CONSTRAINT "wallet_nonce_pkey" PRIMARY KEY ("address","chainId") -); - --- AddForeignKey -ALTER TABLE "wallet_nonce" ADD CONSTRAINT "wallet_nonce_address_fkey" FOREIGN KEY ("address") REFERENCES "wallet_details"("address") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/src/prisma/migrations/20230913061811_triggers/migration.sql b/src/prisma/migrations/20230913061811_triggers/migration.sql deleted file mode 100644 index d24ef6296..000000000 --- a/src/prisma/migrations/20230913061811_triggers/migration.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE OR REPLACE FUNCTION notify_transactions_insert() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('new_transaction_data', row_to_json(NEW)::text); - RETURN NEW; -END; -$function$; - --- Trigger to return only specific column, to keep it under the size limit -CREATE OR REPLACE FUNCTION notify_transactions_update() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('updated_transaction_data', json_build_object( - 'id', NEW.id - )::text); - RETURN NEW; -END; -$function$; - -CREATE OR REPLACE TRIGGER transactions_insert_trigger - AFTER INSERT ON transactions - FOR EACH ROW - EXECUTE FUNCTION notify_transactions_insert(); - -CREATE OR REPLACE TRIGGER transactions_update_trigger - AFTER UPDATE ON transactions - FOR EACH ROW - EXECUTE FUNCTION notify_transactions_update(); \ No newline at end of file diff --git a/src/prisma/migrations/20230922090743_user_ops/migration.sql b/src/prisma/migrations/20230922090743_user_ops/migration.sql deleted file mode 100644 index b36caa43d..000000000 --- a/src/prisma/migrations/20230922090743_user_ops/migration.sql +++ /dev/null @@ -1,16 +0,0 @@ --- DropForeignKey -ALTER TABLE "wallet_nonce" DROP CONSTRAINT "wallet_nonce_address_fkey"; - --- AlterTable -ALTER TABLE "transactions" ADD COLUMN "accountAddress" TEXT, -ADD COLUMN "callData" TEXT, -ADD COLUMN "callGasLimit" INTEGER, -ADD COLUMN "initCode" TEXT, -ADD COLUMN "paymasterAndData" TEXT, -ADD COLUMN "preVerificationGas" INTEGER, -ADD COLUMN "sender" TEXT, -ADD COLUMN "signerAddress" TEXT, -ADD COLUMN "target" TEXT, -ADD COLUMN "userOpHash" TEXT, -ADD COLUMN "verificationGasLimit" INTEGER, -ALTER COLUMN "fromAddress" DROP NOT NULL; diff --git a/src/prisma/migrations/20230926004337_update_user_ops/migration.sql b/src/prisma/migrations/20230926004337_update_user_ops/migration.sql deleted file mode 100644 index fc3278f34..000000000 --- a/src/prisma/migrations/20230926004337_update_user_ops/migration.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE "transactions" -ALTER COLUMN "callGasLimit" SET DATA TYPE TEXT, -ALTER COLUMN "preVerificationGas" SET DATA TYPE TEXT, -ALTER COLUMN "verificationGasLimit" SET DATA TYPE TEXT; \ No newline at end of file diff --git a/src/prisma/migrations/20230927004337_transactions_cancelled_at_added/migration.sql b/src/prisma/migrations/20230927004337_transactions_cancelled_at_added/migration.sql deleted file mode 100644 index 4b56b9ed9..000000000 --- a/src/prisma/migrations/20230927004337_transactions_cancelled_at_added/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "transactions" ADD COLUMN "cancelledAt" TIMESTAMP(3); diff --git a/src/prisma/migrations/20230927221952_trigger_upd/migration.sql b/src/prisma/migrations/20230927221952_trigger_upd/migration.sql deleted file mode 100644 index 70210b32a..000000000 --- a/src/prisma/migrations/20230927221952_trigger_upd/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ --- AlterTable -CREATE OR REPLACE FUNCTION notify_transactions_insert() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('new_transaction_data', json_build_object( - 'id', NEW.id - )::text); - RETURN NEW; -END; -$function$; \ No newline at end of file diff --git a/src/prisma/migrations/20230929175313_cancelled_tx_table/migration.sql b/src/prisma/migrations/20230929175313_cancelled_tx_table/migration.sql deleted file mode 100644 index 0df06b5aa..000000000 --- a/src/prisma/migrations/20230929175313_cancelled_tx_table/migration.sql +++ /dev/null @@ -1,7 +0,0 @@ --- CreateTable -CREATE TABLE "cancelled_transactions" ( - "queueId" TEXT NOT NULL, - "cancelledByWorkerAt" TIMESTAMP(3), - - CONSTRAINT "cancelled_transactions_pkey" PRIMARY KEY ("queueId") -); diff --git a/src/prisma/migrations/20231003223429_encrypted_json/migration.sql b/src/prisma/migrations/20231003223429_encrypted_json/migration.sql deleted file mode 100644 index d8f415609..000000000 --- a/src/prisma/migrations/20231003223429_encrypted_json/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "wallet_details" ADD COLUMN "encryptedJson" TEXT; diff --git a/src/prisma/migrations/20231010225604_remove_cancelled_txs/migration.sql b/src/prisma/migrations/20231010225604_remove_cancelled_txs/migration.sql deleted file mode 100644 index 4b4928d7e..000000000 --- a/src/prisma/migrations/20231010225604_remove_cancelled_txs/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the `cancelled_transactions` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropTable -DROP TABLE "cancelled_transactions"; diff --git a/src/prisma/migrations/20231016220744_configuration/migration.sql b/src/prisma/migrations/20231016220744_configuration/migration.sql deleted file mode 100644 index 0c101fbd5..000000000 --- a/src/prisma/migrations/20231016220744_configuration/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ --- CreateTable -CREATE TABLE "configuration" ( - "id" TEXT NOT NULL, - "minTxsToProcess" INTEGER NOT NULL, - "maxTxsToProcess" INTEGER NOT NULL, - "minedTxsCronSchedule" TEXT, - "maxTxsToUpdate" INTEGER NOT NULL, - "retryTxsCronSchedule" TEXT, - "minEllapsedBlocksBeforeRetry" INTEGER NOT NULL, - "maxFeePerGasForRetries" TEXT NOT NULL, - "maxPriorityFeePerGasForRetries" TEXT NOT NULL, - "maxRetriesPerTx" INTEGER NOT NULL, - - CONSTRAINT "configuration_pkey" PRIMARY KEY ("id") -); diff --git a/src/prisma/migrations/20231016225111_wallets_configuration/migration.sql b/src/prisma/migrations/20231016225111_wallets_configuration/migration.sql deleted file mode 100644 index 0e7f188e9..000000000 --- a/src/prisma/migrations/20231016225111_wallets_configuration/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "awsAccessKeyId" TEXT, -ADD COLUMN "awsRegion" TEXT, -ADD COLUMN "awsSecretAccessKey" TEXT, -ADD COLUMN "gcpApplicationCredentialEmail" TEXT, -ADD COLUMN "gcpApplicationCredentialPrivateKey" TEXT, -ADD COLUMN "gcpApplicationProjectId" TEXT, -ADD COLUMN "gcpKmsKeyRingId" TEXT, -ADD COLUMN "gcpKmsLocationId" TEXT; diff --git a/src/prisma/migrations/20231016235340_chain_id_string/migration.sql b/src/prisma/migrations/20231016235340_chain_id_string/migration.sql deleted file mode 100644 index f3ad34934..000000000 --- a/src/prisma/migrations/20231016235340_chain_id_string/migration.sql +++ /dev/null @@ -1,16 +0,0 @@ -/* - Warnings: - - - The primary key for the `wallet_nonce` table will be changed. If it partially fails, the table could be left without primary key constraint. - -*/ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "chainOverrides" TEXT; - --- AlterTable -ALTER TABLE "transactions" ALTER COLUMN "chainId" SET DATA TYPE TEXT; - --- AlterTable -ALTER TABLE "wallet_nonce" DROP CONSTRAINT "wallet_nonce_pkey", -ALTER COLUMN "chainId" SET DATA TYPE TEXT, -ADD CONSTRAINT "wallet_nonce_pkey" PRIMARY KEY ("address", "chainId"); diff --git a/src/prisma/migrations/20231017214123_webhook_config/migration.sql b/src/prisma/migrations/20231017214123_webhook_config/migration.sql deleted file mode 100644 index 5da28fe81..000000000 --- a/src/prisma/migrations/20231017214123_webhook_config/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "webhookAuthBearerToken" TEXT, -ADD COLUMN "webhookUrl" TEXT; diff --git a/src/prisma/migrations/20231018202048_auth/migration.sql b/src/prisma/migrations/20231018202048_auth/migration.sql deleted file mode 100644 index 3de27c581..000000000 --- a/src/prisma/migrations/20231018202048_auth/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "authDomain" TEXT NOT NULL DEFAULT '', -ADD COLUMN "authWalletEncryptedJson" TEXT NOT NULL DEFAULT ''; diff --git a/src/prisma/migrations/20231018202837_one_config/migration.sql b/src/prisma/migrations/20231018202837_one_config/migration.sql deleted file mode 100644 index 732f3f023..000000000 --- a/src/prisma/migrations/20231018202837_one_config/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[id]` on the table `configuration` will be added. If there are existing duplicate values, this will fail. - -*/ --- AlterTable -ALTER TABLE "configuration" ALTER COLUMN "id" SET DEFAULT 'default'; - --- CreateIndex -CREATE UNIQUE INDEX "configuration_id_key" ON "configuration"("id"); diff --git a/src/prisma/migrations/20231019225104_auth_tokens/migration.sql b/src/prisma/migrations/20231019225104_auth_tokens/migration.sql deleted file mode 100644 index 70ce96b7c..000000000 --- a/src/prisma/migrations/20231019225104_auth_tokens/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ --- DropIndex -DROP INDEX "configuration_id_key"; - --- CreateTable -CREATE TABLE "permissions" ( - "walletAddress" TEXT NOT NULL, - "permissions" TEXT NOT NULL, - - CONSTRAINT "permissions_pkey" PRIMARY KEY ("walletAddress") -); - --- CreateTable -CREATE TABLE "tokens" ( - "id" TEXT NOT NULL, - "tokenMask" TEXT NOT NULL, - "walletAddress" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "expiresAt" TIMESTAMP(3) NOT NULL, - "revokedAt" TIMESTAMP(3), - "isAccessToken" BOOLEAN NOT NULL, - - CONSTRAINT "tokens_pkey" PRIMARY KEY ("id") -); diff --git a/src/prisma/migrations/20231021091418_webhooks_tbl_config_update/migration.sql b/src/prisma/migrations/20231021091418_webhooks_tbl_config_update/migration.sql deleted file mode 100644 index bb216a32b..000000000 --- a/src/prisma/migrations/20231021091418_webhooks_tbl_config_update/migration.sql +++ /dev/null @@ -1,24 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `webhookAuthBearerToken` on the `configuration` table. All the data in the column will be lost. - - You are about to drop the column `webhookUrl` on the `configuration` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "configuration" -ADD COLUMN "minWalletBalance" TEXT NOT NULL DEFAULT '2000000000000000'; - --- CreateTable -CREATE TABLE "webhooks" ( - "id" SERIAL NOT NULL, - "name" TEXT NOT NULL, - "url" TEXT NOT NULL, - "secret" TEXT, - "evenType" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "revokedAt" TIMESTAMP(3), - - CONSTRAINT "webhooks_pkey" PRIMARY KEY ("id") -); diff --git a/src/prisma/migrations/20231025193415_labels/migration.sql b/src/prisma/migrations/20231025193415_labels/migration.sql deleted file mode 100644 index f4fff3bf8..000000000 --- a/src/prisma/migrations/20231025193415_labels/migration.sql +++ /dev/null @@ -1,21 +0,0 @@ -/* - Warnings: - - - Made the column `secret` on table `webhooks` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "configuration" ALTER COLUMN "minWalletBalance" SET DEFAULT '20000000000000000'; - --- AlterTable -ALTER TABLE "permissions" ADD COLUMN "label" TEXT; - --- AlterTable -ALTER TABLE "tokens" ADD COLUMN "label" TEXT; - --- AlterTable -ALTER TABLE "wallet_details" ADD COLUMN "label" TEXT; - --- AlterTable -ALTER TABLE "webhooks" ALTER COLUMN "name" DROP NOT NULL, -ALTER COLUMN "secret" SET NOT NULL; diff --git a/src/prisma/migrations/20231105235957_relayers/migration.sql b/src/prisma/migrations/20231105235957_relayers/migration.sql deleted file mode 100644 index 02980161b..000000000 --- a/src/prisma/migrations/20231105235957_relayers/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- CreateTable -CREATE TABLE "relayers" ( - "id" TEXT NOT NULL, - "name" TEXT, - "chainId" TEXT NOT NULL, - "backendWalletAddress" TEXT NOT NULL, - "allowedContracts" TEXT, - - CONSTRAINT "relayers_pkey" PRIMARY KEY ("id") -); diff --git a/src/prisma/migrations/20231114220310_relayer_forwarders/migration.sql b/src/prisma/migrations/20231114220310_relayer_forwarders/migration.sql deleted file mode 100644 index 83984844d..000000000 --- a/src/prisma/migrations/20231114220310_relayer_forwarders/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "relayers" ADD COLUMN "allowedForwarders" TEXT; diff --git a/src/prisma/migrations/20231123064817_added_onchain_status_flag_to_tx/migration.sql b/src/prisma/migrations/20231123064817_added_onchain_status_flag_to_tx/migration.sql deleted file mode 100644 index d1954b6d2..000000000 --- a/src/prisma/migrations/20231123064817_added_onchain_status_flag_to_tx/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "transactions" ADD COLUMN "onChainTxStatus" INTEGER; diff --git a/src/prisma/migrations/20231203024522_groups/migration.sql b/src/prisma/migrations/20231203024522_groups/migration.sql deleted file mode 100644 index 1218a0a14..000000000 --- a/src/prisma/migrations/20231203024522_groups/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "transactions" ADD COLUMN "groupId" TEXT; diff --git a/src/prisma/migrations/20231226100100_webhook_config_triggers/migration.sql b/src/prisma/migrations/20231226100100_webhook_config_triggers/migration.sql deleted file mode 100644 index ea173e575..000000000 --- a/src/prisma/migrations/20231226100100_webhook_config_triggers/migration.sql +++ /dev/null @@ -1,65 +0,0 @@ --- Configuration Triggers -CREATE OR REPLACE FUNCTION notify_configuration_insert() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('new_configuration_data', row_to_json(NEW)::text); - RETURN NEW; -END; -$function$; - -CREATE OR REPLACE FUNCTION notify_configuration_update() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('updated_configuration_data', json_build_object( - 'id', NEW.id - )::text); - RETURN NEW; -END; -$function$; - -CREATE OR REPLACE TRIGGER configuration_insert_trigger - AFTER INSERT ON configuration - FOR EACH ROW - EXECUTE FUNCTION notify_configuration_insert(); - -CREATE OR REPLACE TRIGGER configuration_update_trigger - AFTER UPDATE ON configuration - FOR EACH ROW - EXECUTE FUNCTION notify_configuration_update(); - --- Webhooks Triggers -CREATE OR REPLACE FUNCTION notify_webhooks_insert() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('new_webhook_data', row_to_json(NEW)::text); - RETURN NEW; -END; -$function$; - -CREATE OR REPLACE FUNCTION notify_webhooks_update() - RETURNS TRIGGER - LANGUAGE plpgsql -AS $function$ -BEGIN - PERFORM pg_notify('updated_webhook_data', json_build_object( - 'id', NEW.id - )::text); - RETURN NEW; -END; -$function$; - -CREATE OR REPLACE TRIGGER webhooks_insert_trigger - AFTER INSERT ON webhooks - FOR EACH ROW - EXECUTE FUNCTION notify_webhooks_insert(); - -CREATE OR REPLACE TRIGGER webhooks_update_trigger - AFTER UPDATE ON webhooks - FOR EACH ROW - EXECUTE FUNCTION notify_webhooks_update(); \ No newline at end of file diff --git a/src/prisma/migrations/20240110194551_cors_to_configurations/migration.sql b/src/prisma/migrations/20240110194551_cors_to_configurations/migration.sql deleted file mode 100644 index 957eeef1c..000000000 --- a/src/prisma/migrations/20240110194551_cors_to_configurations/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "accessControlAllowOrigin" TEXT NOT NULL DEFAULT 'https://thirdweb.com,https//embed.ipfscdn.io'; diff --git a/src/prisma/migrations/20240116172315_clear_cache_cron_to_config/migration.sql b/src/prisma/migrations/20240116172315_clear_cache_cron_to_config/migration.sql deleted file mode 100644 index c70b99f01..000000000 --- a/src/prisma/migrations/20240116172315_clear_cache_cron_to_config/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "clearCacheCronSchedule" TEXT NOT NULL DEFAULT '*/30 * * * * *'; diff --git a/src/prisma/migrations/20240229013311_add_contract_event_subscriptions/migration.sql b/src/prisma/migrations/20240229013311_add_contract_event_subscriptions/migration.sql deleted file mode 100644 index 5ad4c6145..000000000 --- a/src/prisma/migrations/20240229013311_add_contract_event_subscriptions/migration.sql +++ /dev/null @@ -1,72 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "cursorDelaySeconds" INTEGER NOT NULL DEFAULT 2, -ADD COLUMN "indexerListenerCronSchedule" TEXT, -ADD COLUMN "maxBlocksToIndex" INTEGER NOT NULL DEFAULT 5; - --- CreateTable -CREATE TABLE "contract_subscriptions" ( - "id" TEXT NOT NULL, - "chainId" INTEGER NOT NULL, - "contractAddress" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - - CONSTRAINT "contract_subscriptions_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "contract_event_logs" ( - "chainId" INTEGER NOT NULL, - "blockNumber" INTEGER NOT NULL, - "contractAddress" TEXT NOT NULL, - "transactionHash" TEXT NOT NULL, - "topic0" TEXT, - "topic1" TEXT, - "topic2" TEXT, - "topic3" TEXT, - "data" TEXT NOT NULL, - "eventName" TEXT, - "decodedLog" JSONB, - "timestamp" TIMESTAMP(3) NOT NULL, - "transactionIndex" INTEGER NOT NULL, - "logIndex" INTEGER NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "contract_event_logs_pkey" PRIMARY KEY ("transactionHash","logIndex") -); - --- CreateTable -CREATE TABLE "chain_indexers" ( - "chainId" INTEGER NOT NULL, - "lastIndexedBlock" INTEGER NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "chain_indexers_pkey" PRIMARY KEY ("chainId") -); - --- CreateIndex -CREATE INDEX "contract_subscriptions_chainId_idx" ON "contract_subscriptions"("chainId"); - --- CreateIndex -CREATE INDEX "contract_event_logs_timestamp_idx" ON "contract_event_logs"("timestamp"); - --- CreateIndex -CREATE INDEX "contract_event_logs_blockNumber_idx" ON "contract_event_logs"("blockNumber"); - --- CreateIndex -CREATE INDEX "contract_event_logs_contractAddress_idx" ON "contract_event_logs"("contractAddress"); - --- CreateIndex -CREATE INDEX "contract_event_logs_topic0_idx" ON "contract_event_logs"("topic0"); - --- CreateIndex -CREATE INDEX "contract_event_logs_topic1_idx" ON "contract_event_logs"("topic1"); - --- CreateIndex -CREATE INDEX "contract_event_logs_topic2_idx" ON "contract_event_logs"("topic2"); - --- CreateIndex -CREATE INDEX "contract_event_logs_topic3_idx" ON "contract_event_logs"("topic3"); diff --git a/src/prisma/migrations/20240313203128_add_transaction_receipts/migration.sql b/src/prisma/migrations/20240313203128_add_transaction_receipts/migration.sql deleted file mode 100644 index b151d2a05..000000000 --- a/src/prisma/migrations/20240313203128_add_transaction_receipts/migration.sql +++ /dev/null @@ -1,32 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ALTER COLUMN "maxBlocksToIndex" SET DEFAULT 25; - --- CreateTable -CREATE TABLE "contract_transaction_receipts" ( - "chainId" INTEGER NOT NULL, - "blockNumber" INTEGER NOT NULL, - "contractAddress" TEXT NOT NULL, - "contractId" TEXT NOT NULL, - "transactionHash" TEXT NOT NULL, - "blockHash" TEXT NOT NULL, - "timestamp" TIMESTAMP(3) NOT NULL, - "data" TEXT NOT NULL, - "to" TEXT NOT NULL, - "from" TEXT NOT NULL, - "value" TEXT NOT NULL, - "transactionIndex" INTEGER NOT NULL, - "gasUsed" TEXT NOT NULL, - "effectiveGasPrice" TEXT NOT NULL, - "status" INTEGER NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL -); - --- CreateIndex -CREATE INDEX "contract_transaction_receipts_contractId_timestamp_idx" ON "contract_transaction_receipts"("contractId", "timestamp"); - --- CreateIndex -CREATE INDEX "contract_transaction_receipts_contractId_blockNumber_idx" ON "contract_transaction_receipts"("contractId", "blockNumber"); - --- CreateIndex -CREATE UNIQUE INDEX "contract_transaction_receipts_chainId_transactionHash_key" ON "contract_transaction_receipts"("chainId", "transactionHash"); diff --git a/src/prisma/migrations/20240323005129_add_idempotency_key_backward_compatible/migration.sql b/src/prisma/migrations/20240323005129_add_idempotency_key_backward_compatible/migration.sql deleted file mode 100644 index 8b2b3a53b..000000000 --- a/src/prisma/migrations/20240323005129_add_idempotency_key_backward_compatible/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - A unique constraint covering the columns `[idempotencyKey]` on the table `transactions` will be added. If there are existing duplicate values, this will fail. - -*/ --- AlterTable -ALTER TABLE "transactions" ADD COLUMN "idempotencyKey" TEXT NOT NULL DEFAULT gen_random_uuid(); - --- CreateIndex -CREATE UNIQUE INDEX "transactions_idempotencyKey_key" ON "transactions"("idempotencyKey"); diff --git a/src/prisma/migrations/20240327202800_add_keypairs/migration.sql b/src/prisma/migrations/20240327202800_add_keypairs/migration.sql deleted file mode 100644 index aff4b4e2f..000000000 --- a/src/prisma/migrations/20240327202800_add_keypairs/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- CreateTable -CREATE TABLE "keypairs" ( - "hash" TEXT NOT NULL, - "publicKey" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "keypairs_pkey" PRIMARY KEY ("hash") -); diff --git a/src/prisma/migrations/20240410015450_add_keypair_algorithm/migration.sql b/src/prisma/migrations/20240410015450_add_keypair_algorithm/migration.sql deleted file mode 100644 index 4c806f34a..000000000 --- a/src/prisma/migrations/20240410015450_add_keypair_algorithm/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Added the required column `algorithm` to the `keypairs` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "keypairs" ADD COLUMN "algorithm" TEXT NOT NULL; diff --git a/src/prisma/migrations/20240411235927_add_keypair_label/migration.sql b/src/prisma/migrations/20240411235927_add_keypair_label/migration.sql deleted file mode 100644 index 7f04c3070..000000000 --- a/src/prisma/migrations/20240411235927_add_keypair_label/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "keypairs" ADD COLUMN "label" TEXT, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/src/prisma/migrations/20240510023239_add_webhook_id/migration.sql b/src/prisma/migrations/20240510023239_add_webhook_id/migration.sql deleted file mode 100644 index 39dcb2b68..000000000 --- a/src/prisma/migrations/20240510023239_add_webhook_id/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "contract_subscriptions" ADD COLUMN "webhookId" INTEGER; - --- AddForeignKey -ALTER TABLE "contract_subscriptions" ADD CONSTRAINT "contract_subscriptions_webhookId_fkey" FOREIGN KEY ("webhookId") REFERENCES "webhooks"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/prisma/migrations/20240511011737_set_on_delete_set_null/migration.sql b/src/prisma/migrations/20240511011737_set_on_delete_set_null/migration.sql deleted file mode 100644 index 5a47d158c..000000000 --- a/src/prisma/migrations/20240511011737_set_on_delete_set_null/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- DropForeignKey -ALTER TABLE "contract_subscriptions" DROP CONSTRAINT "contract_subscriptions_webhookId_fkey"; - --- AddForeignKey -ALTER TABLE "contract_subscriptions" ADD CONSTRAINT "contract_subscriptions_webhookId_fkey" FOREIGN KEY ("webhookId") REFERENCES "webhooks"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/src/prisma/migrations/20240513204722_add_contract_sub_retry_delay_to_config/migration.sql b/src/prisma/migrations/20240513204722_add_contract_sub_retry_delay_to_config/migration.sql deleted file mode 100644 index 9092f3e96..000000000 --- a/src/prisma/migrations/20240513204722_add_contract_sub_retry_delay_to_config/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "contractSubscriptionsRetryDelaySeconds" TEXT NOT NULL DEFAULT '10'; diff --git a/src/prisma/migrations/20240603232427_contract_subscription_filters/migration.sql b/src/prisma/migrations/20240603232427_contract_subscription_filters/migration.sql deleted file mode 100644 index ceef2c8f7..000000000 --- a/src/prisma/migrations/20240603232427_contract_subscription_filters/migration.sql +++ /dev/null @@ -1,4 +0,0 @@ --- AlterTable -ALTER TABLE "contract_subscriptions" ADD COLUMN "filterEventLogs" TEXT[] DEFAULT ARRAY[]::TEXT[], -ADD COLUMN "parseEventLogs" BOOLEAN NOT NULL DEFAULT true, -ADD COLUMN "parseTransactionReceipts" BOOLEAN NOT NULL DEFAULT true; diff --git a/src/prisma/migrations/20240604034241_rename_contract_subscription_vars/migration.sql b/src/prisma/migrations/20240604034241_rename_contract_subscription_vars/migration.sql deleted file mode 100644 index 637849854..000000000 --- a/src/prisma/migrations/20240604034241_rename_contract_subscription_vars/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `filterEventLogs` on the `contract_subscriptions` table. All the data in the column will be lost. - - You are about to drop the column `parseEventLogs` on the `contract_subscriptions` table. All the data in the column will be lost. - - You are about to drop the column `parseTransactionReceipts` on the `contract_subscriptions` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "contract_subscriptions" DROP COLUMN "filterEventLogs", -DROP COLUMN "parseEventLogs", -DROP COLUMN "parseTransactionReceipts", -ADD COLUMN "filterEvents" TEXT[] DEFAULT ARRAY[]::TEXT[], -ADD COLUMN "processEventLogs" BOOLEAN NOT NULL DEFAULT true, -ADD COLUMN "processTransactionReceipts" BOOLEAN NOT NULL DEFAULT true; diff --git a/src/prisma/migrations/20240611023057_add_contract_subscriptions_filter_functions/migration.sql b/src/prisma/migrations/20240611023057_add_contract_subscriptions_filter_functions/migration.sql deleted file mode 100644 index 91448e6d7..000000000 --- a/src/prisma/migrations/20240611023057_add_contract_subscriptions_filter_functions/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "contract_subscriptions" ADD COLUMN "filterFunctions" TEXT[] DEFAULT ARRAY[]::TEXT[]; diff --git a/src/prisma/migrations/20240612015710_add_function_name/migration.sql b/src/prisma/migrations/20240612015710_add_function_name/migration.sql deleted file mode 100644 index 5eebd5104..000000000 --- a/src/prisma/migrations/20240612015710_add_function_name/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "contract_transaction_receipts" ADD COLUMN "functionName" TEXT; diff --git a/src/prisma/migrations/20240704112555_ip_allowlist/migration.sql b/src/prisma/migrations/20240704112555_ip_allowlist/migration.sql deleted file mode 100644 index 13a1c415b..000000000 --- a/src/prisma/migrations/20240704112555_ip_allowlist/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "ipAllowlist" TEXT[] DEFAULT ARRAY[]::TEXT[]; diff --git a/src/prisma/migrations/20240731212420_tx_add_composite_idx_1/migration.sql b/src/prisma/migrations/20240731212420_tx_add_composite_idx_1/migration.sql deleted file mode 100644 index b1d0786fe..000000000 --- a/src/prisma/migrations/20240731212420_tx_add_composite_idx_1/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- CreateIndex -CREATE INDEX CONCURRENTLY "transactions_sentAt_minedAt_cancelledAt_errorMessage_queued_idx" ON "transactions"("sentAt", "minedAt", "cancelledAt", "errorMessage", "queuedAt"); diff --git a/src/prisma/migrations/20240731213113_tx_add_composite_idx_2/migration.sql b/src/prisma/migrations/20240731213113_tx_add_composite_idx_2/migration.sql deleted file mode 100644 index ea19fa805..000000000 --- a/src/prisma/migrations/20240731213113_tx_add_composite_idx_2/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- CreateIndex -CREATE INDEX CONCURRENTLY "transactions_sentAt_accountAddress_userOpHash_minedAt_error_idx" ON "transactions"("sentAt", "accountAddress", "userOpHash", "minedAt", "errorMessage", "retryCount"); diff --git a/src/prisma/migrations/20240731213342_tx_add_composite_idx_3/migration.sql b/src/prisma/migrations/20240731213342_tx_add_composite_idx_3/migration.sql deleted file mode 100644 index 0b19d8b6d..000000000 --- a/src/prisma/migrations/20240731213342_tx_add_composite_idx_3/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- CreateIndex -CREATE INDEX CONCURRENTLY "transactions_sentAt_transactionHash_accountAddress_minedAt__idx" ON "transactions"("sentAt", "transactionHash", "accountAddress", "minedAt", "errorMessage", "nonce"); diff --git a/src/prisma/migrations/20240802175702_transaction_tbl_queued_at_idx/migration.sql b/src/prisma/migrations/20240802175702_transaction_tbl_queued_at_idx/migration.sql deleted file mode 100644 index e9ee600ca..000000000 --- a/src/prisma/migrations/20240802175702_transaction_tbl_queued_at_idx/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- CreateIndex -CREATE INDEX CONCURRENTLY "transactions_queuedAt_idx" ON "transactions"("queuedAt"); diff --git a/src/prisma/migrations/20241003051028_wallet_details_credentials/migration.sql b/src/prisma/migrations/20241003051028_wallet_details_credentials/migration.sql deleted file mode 100644 index ee4b3b78b..000000000 --- a/src/prisma/migrations/20241003051028_wallet_details_credentials/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "wallet_details" ADD COLUMN "awsKmsAccessKeyId" TEXT, -ADD COLUMN "awsKmsSecretAccessKey" TEXT, -ADD COLUMN "gcpApplicationCredentialEmail" TEXT, -ADD COLUMN "gcpApplicationCredentialPrivateKey" TEXT; diff --git a/src/prisma/migrations/20241007003342_add_smart_backend_wallet_columns/migration.sql b/src/prisma/migrations/20241007003342_add_smart_backend_wallet_columns/migration.sql deleted file mode 100644 index ed2a58f36..000000000 --- a/src/prisma/migrations/20241007003342_add_smart_backend_wallet_columns/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "wallet_details" ADD COLUMN "accountFactoryAddress" TEXT, -ADD COLUMN "accountSignerAddress" TEXT; diff --git a/src/prisma/migrations/20241022222921_add_entrypoint_address/migration.sql b/src/prisma/migrations/20241022222921_add_entrypoint_address/migration.sql deleted file mode 100644 index 926e7d614..000000000 --- a/src/prisma/migrations/20241022222921_add_entrypoint_address/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "wallet_details" ADD COLUMN "entrypointAddress" TEXT; diff --git a/src/prisma/migrations/20241031010103_add_mtls_configuration/migration.sql b/src/prisma/migrations/20241031010103_add_mtls_configuration/migration.sql deleted file mode 100644 index 9e7a54aac..000000000 --- a/src/prisma/migrations/20241031010103_add_mtls_configuration/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "mtlsCertificateEncrypted" TEXT, -ADD COLUMN "mtlsPrivateKeyEncrypted" TEXT; diff --git a/src/prisma/migrations/20241105091733_chain_id_from_int_to_string/migration.sql b/src/prisma/migrations/20241105091733_chain_id_from_int_to_string/migration.sql deleted file mode 100644 index b941b2312..000000000 --- a/src/prisma/migrations/20241105091733_chain_id_from_int_to_string/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "contract_subscriptions" ALTER COLUMN "chainId" SET DATA TYPE TEXT; diff --git a/src/prisma/migrations/20241106225714_all_chain_ids_to_string/migration.sql b/src/prisma/migrations/20241106225714_all_chain_ids_to_string/migration.sql deleted file mode 100644 index c6604eb7a..000000000 --- a/src/prisma/migrations/20241106225714_all_chain_ids_to_string/migration.sql +++ /dev/null @@ -1,16 +0,0 @@ -/* - Warnings: - - - The primary key for the `chain_indexers` table will be changed. If it partially fails, the table could be left without primary key constraint. - -*/ --- AlterTable -ALTER TABLE "chain_indexers" DROP CONSTRAINT "chain_indexers_pkey", -ALTER COLUMN "chainId" SET DATA TYPE TEXT, -ADD CONSTRAINT "chain_indexers_pkey" PRIMARY KEY ("chainId"); - --- AlterTable -ALTER TABLE "contract_event_logs" ALTER COLUMN "chainId" SET DATA TYPE TEXT; - --- AlterTable -ALTER TABLE "contract_transaction_receipts" ALTER COLUMN "chainId" SET DATA TYPE TEXT; diff --git a/src/prisma/migrations/20250204201526_add_wallet_credentials/migration.sql b/src/prisma/migrations/20250204201526_add_wallet_credentials/migration.sql deleted file mode 100644 index 9776a0c96..000000000 --- a/src/prisma/migrations/20250204201526_add_wallet_credentials/migration.sql +++ /dev/null @@ -1,29 +0,0 @@ --- AlterTable -ALTER TABLE "configuration" ADD COLUMN "walletProviderConfigs" JSONB NOT NULL DEFAULT '{}'; - --- AlterTable -ALTER TABLE "wallet_details" ADD COLUMN "credentialId" TEXT, -ADD COLUMN "platformIdentifiers" JSONB; - --- CreateTable -CREATE TABLE "wallet_credentials" ( - "id" TEXT NOT NULL, - "type" TEXT NOT NULL, - "label" TEXT NOT NULL, - "data" JSONB NOT NULL, - "isDefault" BOOLEAN NOT NULL DEFAULT false, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "deletedAt" TIMESTAMP(3), - - CONSTRAINT "wallet_credentials_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE INDEX "wallet_credentials_type_idx" ON "wallet_credentials"("type"); - --- CreateIndex -CREATE UNIQUE INDEX "wallet_credentials_type_is_default_key" ON "wallet_credentials"("type", "isDefault"); - --- AddForeignKey -ALTER TABLE "wallet_details" ADD CONSTRAINT "wallet_details_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "wallet_credentials"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/src/prisma/migrations/20250207135644_nullable_is_default/migration.sql b/src/prisma/migrations/20250207135644_nullable_is_default/migration.sql deleted file mode 100644 index 3712fa67e..000000000 --- a/src/prisma/migrations/20250207135644_nullable_is_default/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "wallet_credentials" ALTER COLUMN "isDefault" DROP NOT NULL; diff --git a/src/prisma/migrations/migration_lock.toml b/src/prisma/migrations/migration_lock.toml deleted file mode 100644 index fbffa92c2..000000000 --- a/src/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (i.e. Git) -provider = "postgresql" \ No newline at end of file diff --git a/src/prisma/schema.prisma b/src/prisma/schema.prisma deleted file mode 100644 index 1c4a473c4..000000000 --- a/src/prisma/schema.prisma +++ /dev/null @@ -1,337 +0,0 @@ -datasource db { - url = env("POSTGRES_CONNECTION_URL") - provider = "postgresql" -} - -generator client { - provider = "prisma-client-js" -} - -model Configuration { - id String @id @default("default") @map("id") - // Chains - chainOverrides String? @map("chainOverrides") - // Tx Processing - minTxsToProcess Int @map("minTxsToProcess") - maxTxsToProcess Int @map("maxTxsToProcess") - // Tx Updates - minedTxListenerCronSchedule String? @map("minedTxsCronSchedule") - maxTxsToUpdate Int @map("maxTxsToUpdate") - // Tx Retries - retryTxListenerCronSchedule String? @map("retryTxsCronSchedule") - minEllapsedBlocksBeforeRetry Int @map("minEllapsedBlocksBeforeRetry") - maxFeePerGasForRetries String @map("maxFeePerGasForRetries") - maxPriorityFeePerGasForRetries String @map("maxPriorityFeePerGasForRetries") - maxRetriesPerTx Int @map("maxRetriesPerTx") - // Contract Indexer Updates - indexerListenerCronSchedule String? @map("indexerListenerCronSchedule") - maxBlocksToIndex Int @default(25) @map("maxBlocksToIndex") - cursorDelaySeconds Int @default(2) @map("cursorDelaySeconds") - contractSubscriptionsRetryDelaySeconds String @default("10") @map("contractSubscriptionsRetryDelaySeconds") - - // Wallet provider specific configurations, non-credential - walletProviderConfigs Json @default("{}") @map("walletProviderConfigs") /// Eg: { "aws": { "defaultAwsRegion": "us-east-1" }, "gcp": { "defaultGcpKmsLocationId": "us-east1-b" } } - - // Legacy wallet provider credentials - // Use default credentials instead, and store non-credential wallet provider configuration in walletProviderConfig - // AWS - awsAccessKeyId String? @map("awsAccessKeyId") /// global config, precedence goes to WalletDetails - awsSecretAccessKey String? @map("awsSecretAccessKey") /// global config, precedence goes to WalletDetails - awsRegion String? @map("awsRegion") /// global config, treat as "default", store in WalletDetails.awsKmsArn - // GCP - gcpApplicationProjectId String? @map("gcpApplicationProjectId") /// global config, treat as "default", store in WalletDetails.gcpKmsResourcePath - gcpKmsLocationId String? @map("gcpKmsLocationId") /// global config, treat as "default", store in WalletDetails.gcpKmsResourcePath - gcpKmsKeyRingId String? @map("gcpKmsKeyRingId") /// global config, treat as "default", store in WalletDetails.gcpKmsResourcePath - gcpApplicationCredentialEmail String? @map("gcpApplicationCredentialEmail") /// global config, precedence goes to WalletDetails - gcpApplicationCredentialPrivateKey String? @map("gcpApplicationCredentialPrivateKey") /// global config, precedence goes to WalletDetails - // Auth - authDomain String @default("") @map("authDomain") // TODO: Remove defaults on major - authWalletEncryptedJson String @default("") @map("authWalletEncryptedJson") // TODO: Remove defaults on major - // Webhook - webhookUrl String? @map("webhookUrl") - webhookAuthBearerToken String? @map("webhookAuthBearerToken") - // Wallet balance - minWalletBalance String @default("20000000000000000") @map("minWalletBalance") - accessControlAllowOrigin String @default("https://thirdweb.com,https//embed.ipfscdn.io") @map("accessControlAllowOrigin") - ipAllowlist String[] @default([]) @map("ipAllowlist") - clearCacheCronSchedule String @default("*/30 * * * * *") @map("clearCacheCronSchedule") - // mTLS support - mtlsCertificateEncrypted String? - mtlsPrivateKeyEncrypted String? - - @@map("configuration") -} - -model Permissions { - walletAddress String @id @map("walletAddress") - permissions String @map("permissions") - label String? @map("label") - - @@map("permissions") -} - -model Tokens { - id String @id @map("id") - tokenMask String @map("tokenMask") - walletAddress String @map("walletAddress") - createdAt DateTime @default(now()) @map("createdAt") - expiresAt DateTime @map("expiresAt") - revokedAt DateTime? @map("revokedAt") - isAccessToken Boolean @map("isAccessToken") - label String? @map("label") - - @@map("tokens") -} - -model WalletDetails { - address String @id @map("address") - type String @map("type") - label String? @map("label") - - // Local - encryptedJson String? @map("encryptedJson") - - // New approach: platform identifiers + wallet credentials - platformIdentifiers Json? @map("platformIdentifiers") /// Eg: { "awsKmsArn": "..." } or { "gcpKmsResourcePath": "..." } - credentialId String? @map("credentialId") - credential WalletCredentials? @relation(fields: [credentialId], references: [id]) - - // Legacy AWS KMS fields - use platformIdentifiers + WalletCredentials for new wallets - // KMS - awsKmsKeyId String? @map("awsKmsKeyId") /// deprecated and unused, todo: remove with next breaking change. Use awsKmsArn - awsKmsArn String? @map("awsKmsArn") - awsKmsSecretAccessKey String? @map("awsKmsSecretAccessKey") /// if not available, default to: Configuration.awsSecretAccessKey - awsKmsAccessKeyId String? @map("awsKmsAccessKeyId") /// if not available, default to: Configuration.awsAccessKeyId - // GCP - gcpKmsKeyRingId String? @map("gcpKmsKeyRingId") @db.VarChar(50) /// deprecated and unused. Use gcpKmsResourcePath instead, todo: remove with next breaking change - gcpKmsKeyId String? @map("gcpKmsKeyId") @db.VarChar(50) /// deprecated and unused. Use gcpKmsResourcePath instead, todo: remove with next breaking change - gcpKmsKeyVersionId String? @map("gcpKmsKeyVersionId") @db.VarChar(20) /// deprecated and unused. Use gcpKmsResourcePath instead, todo: remove with next breaking change - gcpKmsLocationId String? @map("gcpKmsLocationId") @db.VarChar(20) /// deprecated and unused. Use gcpKmsResourcePath instead, todo: remove with next breaking change - gcpKmsResourcePath String? @map("gcpKmsResourcePath") @db.Text - gcpApplicationCredentialEmail String? @map("gcpApplicationCredentialEmail") /// if not available, default to: Configuration.gcpApplicationCredentialEmail - gcpApplicationCredentialPrivateKey String? @map("gcpApplicationCredentialPrivateKey") /// if not available, default to: Configuration.gcpApplicationCredentialPrivateKey - - // Smart Backend Wallet - accountSignerAddress String? @map("accountSignerAddress") /// this, and either local, aws or gcp encryptedJson, are required for smart wallet - accountFactoryAddress String? @map("accountFactoryAddress") /// optional even for smart wallet, if not available default factory will be used - entrypointAddress String? @map("entrypointAddress") /// optional even for smart wallet, if not available SDK will use default entrypoint - - @@map("wallet_details") -} - -model WalletCredentials { - id String @id @default(uuid()) - type String - label String - data Json - isDefault Boolean? @default(false) - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime? - - wallets WalletDetails[] - - // A maximum of one default credential per type - @@unique([type, isDefault], name: "unique_default_per_type", map: "wallet_credentials_type_is_default_key") - @@index([type]) - @@map("wallet_credentials") -} - -model WalletNonce { - address String @map("address") - chainId String @map("chainId") - nonce Int @default(0) @map("nonce") - - @@id([address, chainId]) - @@map("wallet_nonce") -} - -model Transactions { - id String @id @default(uuid()) @map("id") - // Backward compatibility: default to db-generated UUID. - idempotencyKey String @unique @default(dbgenerated("gen_random_uuid()")) @map("idempotencyKey") - groupId String? @map("groupId") - chainId String @map("chainId") - // Shared - data String? @map("data") - value String? @map("value") - gasLimit String? @map("gasLimit") - nonce Int? @map("nonce") - maxFeePerGas String? @map("maxFeePerGas") - maxPriorityFeePerGas String? @map("maxPriorityFeePerGas") - // Transaction Details - fromAddress String? @map("fromAddress") - toAddress String? @map("toAddress") - gasPrice String? @map("gasPrice") - transactionType Int? @map("transactionType") - transactionHash String? @map("transactionHash") - onChainTxStatus Int? @map("onChainTxStatus") - // User Operation - signerAddress String? @map("signerAddress") - accountAddress String? @map("accountAddress") - target String? @map("target") - sender String? @map("sender") - initCode String? @map("initCode") - callData String? @map("callData") - callGasLimit String? @map("callGasLimit") - verificationGasLimit String? @map("verificationGasLimit") - preVerificationGas String? @map("preVerificationGas") - paymasterAndData String? @map("paymasterAndData") - userOpHash String? @map("userOpHash") - // Enriched Data - functionName String? @map("functionName") - functionArgs String? @map("functionArgs") - extension String? @map("extension") - // TODO: These shouldn't be in here... - deployedContractAddress String? @map("deployedContractAddress") - deployedContractType String? @map("deployedContractType") - // Timestamps - queuedAt DateTime @default(now()) @map("queuedAt") - // @deprecated - processedAt DateTime? @map("processedAt") - sentAt DateTime? @map("sentAt") - minedAt DateTime? @map("minedAt") - cancelledAt DateTime? @map("cancelledAt") - // Retries - retryCount Int @default(0) @map("retryCount") - retryGasValues Boolean? @default(false) @map("retryGasValues") - retryMaxPriorityFeePerGas String? @map("retryMaxPriorityFeePerGas") - retryMaxFeePerGas String? @map("retryMaxFeePerGas") - // Error - errorMessage String? @map("errorMessage") - // Block Numbers - sentAtBlockNumber Int? @map("sentAtBlockNumber") - blockNumber Int? @map("blockNumber") - - @@index([sentAt, minedAt, cancelledAt, errorMessage, queuedAt]) - @@index([sentAt, accountAddress, userOpHash, minedAt, errorMessage, retryCount]) - @@index([sentAt, transactionHash, accountAddress, minedAt, errorMessage, nonce]) - @@index([queuedAt]) - @@map("transactions") -} - -model Webhooks { - id Int @id @default(autoincrement()) @map("id") - name String? @map("name") - url String @map("url") - secret String @map("secret") - eventType String @map("evenType") - createdAt DateTime @default(now()) @map("createdAt") - updatedAt DateTime @updatedAt @map("updatedAt") - revokedAt DateTime? @map("revokedAt") - ContractSubscriptions ContractSubscriptions[] - - @@map("webhooks") -} - -model Relayers { - id String @id @default(uuid()) @map("id") - name String? @map("name") - chainId String @map("chainId") - backendWalletAddress String @map("backendWalletAddress") - allowedContracts String? @map("allowedContracts") - allowedForwarders String? @map("allowedForwarders") - - @@map("relayers") -} - -model ContractSubscriptions { - id String @id @default(uuid()) @map("id") - chainId String - contractAddress String - webhookId Int? - processEventLogs Boolean @default(true) - filterEvents String[] @default([]) // empty array = no filter - processTransactionReceipts Boolean @default(true) - filterFunctions String[] @default([]) // empty array = no filter - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime? - - webhook Webhooks? @relation(fields: [webhookId], references: [id], onDelete: SetNull) - - // optimize distinct lookups - @@index([chainId]) - @@map("contract_subscriptions") -} - -model ContractEventLogs { - chainId String - blockNumber Int - contractAddress String - transactionHash String - topic0 String? - topic1 String? - topic2 String? - topic3 String? - data String - eventName String? - decodedLog Json? - timestamp DateTime - transactionIndex Int - logIndex Int - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@id([transactionHash, logIndex]) - @@index([timestamp]) - @@index([blockNumber]) - @@index([contractAddress]) - @@index([topic0]) - @@index([topic1]) - @@index([topic2]) - @@index([topic3]) - @@map("contract_event_logs") -} - -model ContractTransactionReceipts { - chainId String - blockNumber Int - contractAddress String - contractId String // ${chainId}:${contractAddress} - transactionHash String - blockHash String - timestamp DateTime - data String - functionName String? - - to String - from String - value String - transactionIndex Int - - gasUsed String - effectiveGasPrice String - status Int - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@unique([chainId, transactionHash]) - @@index([contractId, timestamp]) - @@index([contractId, blockNumber]) - @@map("contract_transaction_receipts") -} - -model ChainIndexers { - chainId String @id - lastIndexedBlock Int - - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - - @@map("chain_indexers") -} - -model Keypairs { - hash String @id - publicKey String - algorithm String - label String? - createdAt DateTime @default(now()) - updatedAt DateTime @default(now()) - - @@map("keypairs") -} diff --git a/src/scripts/apply-migrations.ts b/src/scripts/apply-migrations.ts deleted file mode 100644 index 2c12f0915..000000000 --- a/src/scripts/apply-migrations.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { logger } from "../shared/utils/logger"; -import { - acquireLock, - releaseLock, - waitForLock, -} from "../shared/utils/redis/lock"; -import { redis } from "../shared/utils/redis/redis"; - -const MIGRATION_LOCK_TTL_SECONDS = 60; - -const main = async () => { - // Acquire a lock to allow only one host to run migrations. - // Other hosts block until the migration is completed or lock times out. - const acquiredLock = await acquireLock( - "lock:apply-migrations", - MIGRATION_LOCK_TTL_SECONDS, - ); - if (!acquiredLock) { - logger({ - level: "info", - message: "Migration in progress. Waiting for the lock to release...", - service: "server", - }); - await waitForLock("lock:apply-migrations"); - process.exit(0); - } - - try { - await migrateRecycledNonces(); - - logger({ - level: "info", - message: "Completed migrations successfully.", - service: "server", - }); - } catch (e) { - logger({ - level: "error", - message: `Failed to complete migrations: ${e}`, - service: "server", - }); - process.exit(1); - } finally { - await releaseLock("lock:apply-migrations"); - } - - process.exit(0); -}; - -const migrateRecycledNonces = async () => { - const keys = await redis.keys("nonce-recycled:*"); - - // For each `nonce-recycled:*` key that is a "set" in Redis, - // migrate all members to a sorted set with score == nonce. - for (const key of keys) { - const type = await redis.type(key); - if (type !== "set") { - continue; - } - - const members = await redis.smembers(key); - await redis.del(key); - if (members.length > 0) { - const args = members.flatMap((member) => { - const score = Number.parseInt(member); - return Number.isNaN(score) ? [] : [score, member]; - }); - await redis.zadd(key, ...args); - } - } -}; - -main(); diff --git a/src/scripts/setup-db.ts b/src/scripts/setup-db.ts deleted file mode 100644 index d38542756..000000000 --- a/src/scripts/setup-db.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { execSync } from "node:child_process"; -import { prisma } from "../shared/db/client"; - -const main = async () => { - const [{ exists: hasWalletsTable }]: [{ exists: boolean }] = - await prisma.$queryRaw` - SELECT EXISTS ( - SELECT 1 - FROM pg_tables - WHERE schemaname = 'public' - AND tablename = 'wallets' - ); - `; - - const schema = - process.env.NODE_ENV === "production" - ? "./dist/prisma/schema.prisma" - : "./src/prisma/schema.prisma"; - - if (hasWalletsTable) { - execSync(`yarn prisma migrate reset --force --schema ${schema}`, { - stdio: "inherit", - }); - } else { - execSync(`yarn prisma migrate deploy --schema ${schema}`, { - stdio: "inherit", - }); - } - - execSync(`yarn prisma generate --schema ${schema}`, { stdio: "inherit" }); -}; - -main(); diff --git a/src/server/engine.ts b/src/server/engine.ts new file mode 100644 index 000000000..bbdfe3232 --- /dev/null +++ b/src/server/engine.ts @@ -0,0 +1,177 @@ +import { Scalar } from "@scalar/hono-api-reference"; +import { Hono } from "hono"; +import { some } from "hono/combine"; +import { HTTPException } from "hono/http-exception"; +import { logger } from "hono/logger"; +import { secureHeaders } from "hono/secure-headers"; +import { openAPISpecs } from "hono-openapi"; +import { config } from "../lib/config.js"; +import { env } from "../lib/env.js"; +import { + EngineHttpException, + getDefaultErrorMessage, + unwrapError, +} from "../lib/errors.js"; +import { defaultLogger } from "../lib/logger.js"; +import { accessTokenAuth } from "./middleware/auth/access-token.js"; +import { dashboardAuth } from "./middleware/auth/dashboard.js"; +import { secretKeyAuth } from "./middleware/auth/secret-key.js"; +import { webhookAuth } from "./middleware/auth/webhook.js"; +import { correlationId } from "./middleware/correlation-id.js"; +import { createApiCorsMiddleware } from "./middleware/cors.js"; +import { prometheusMiddleware } from "./middleware/prometheus.js"; +import { rateLimitMiddleware } from "./middleware/rate-limit.js"; +import { requestLogger } from "./middleware/request-logger.js"; +import { accountsRoutes } from "./routes/accounts/accounts.js"; +import authRoutes from "./routes/auth/index.js"; +import { chainActionsRouter } from "./routes/chain/index.js"; +import { healthCheckRoute } from "./routes/health.js"; +import { setupQueuesUiRoutes } from "./routes/queues.js"; +import { transactionsRoutes } from "./routes/transactions/index.js"; + +const engineServer = new Hono(); +const engineServerV1 = new Hono(); +const publicRoutes = new Hono(); + +publicRoutes.route("/health", healthCheckRoute); +publicRoutes.route("/system/health", healthCheckRoute); +publicRoutes.get("/", async (c) => { + return c.json({ + message: + "Engine is set up successfully. Manage your Engine from https://thirdweb.com/dashboard/engine.", + }); +}); + +publicRoutes.get( + "/openapi", + openAPISpecs(engineServer, { + documentation: { + info: { + title: "Engine", + version: "3.0.0-rc.0", + description: "API Documentation", + }, + components: { + securitySchemes: { + bearerAuth: { + type: "http", + scheme: "bearer", + bearerFormat: "JWT", + }, + }, + }, + security: [ + { + bearerAuth: [], + }, + ], + }, + }), +); + +publicRoutes.get( + "/docs", + Scalar({ + theme: "kepler", + url: "/openapi", + favicon: + "https://framerusercontent.com/images/6UCnwoW4U3z16zLNLf31n4ZkyY.png", + title: "Engine Core v3 API", + pageTitle: "Engine Core v3 API Reference", + }), +); + +setupQueuesUiRoutes(publicRoutes, "/admin/queues"); +engineServer.route("/", publicRoutes); + +engineServer.use(correlationId); + +const apiCorsMiddleware = createApiCorsMiddleware({ + allowedOrigins: config.accessControlAllowOrigin, +}); + +if (env.NODE_ENV === "development" || env.NODE_ENV === "local") { + engineServer.use(logger()); +} else { + engineServer.use(requestLogger); +} + +engineServer.use( + secureHeaders({ + contentSecurityPolicy: { + defaultSrc: ["'self'"], + }, + xFrameOptions: "DENY", + permissionsPolicy: { + geolocation: [], + camera: [], + microphone: [], + }, + }), +); + +engineServer.use(prometheusMiddleware); +engineServer.use(apiCorsMiddleware); + +engineServer.use(rateLimitMiddleware); + +engineServer.use( + some(secretKeyAuth, webhookAuth, dashboardAuth, accessTokenAuth), +); + +engineServerV1.route("/accounts", accountsRoutes); +engineServerV1.route("/transactions", transactionsRoutes); +engineServerV1.route("/auth", authRoutes); +engineServerV1.route("/", chainActionsRouter); + +engineServer.route("/v1", engineServerV1); + +engineServer.onError((err, c) => { + if (err instanceof HTTPException) { + if (err instanceof EngineHttpException) { + const engineErr = err.engineErr; + return c.json( + { + error: { + ...engineErr, + message: engineErr.message ?? getDefaultErrorMessage(engineErr), + source: unwrapError(engineErr.source), + }, + }, + engineErr.status, + ); + } + const response = err.getResponse(); + return response; + } + + defaultLogger.error("unhandled error", err); + + return c.json( + { + error: { + message: "Internal server error", + source: err, + }, + }, + 500, + ); +}); + +const tls = env.ENABLE_HTTPS + ? { + key: Bun.file("../https/key.pem"), + cert: Bun.file("../https/cert.pem"), + passphrase: env.HTTPS_PASSPHRASE, + } + : {}; + +export function initiateEngineServer() { + Bun.serve({ + port: env.PORT, + tls, + fetch: engineServer.fetch, + idleTimeout: 255, // max value + }); + defaultLogger.info(`Engine is ready and listening on port ${env.PORT}`); +} diff --git a/src/server/index.ts b/src/server/index.ts deleted file mode 100644 index 2628edbae..000000000 --- a/src/server/index.ts +++ /dev/null @@ -1,137 +0,0 @@ -import type { TypeBoxTypeProvider } from "@fastify/type-provider-typebox"; -import fastify, { type FastifyInstance } from "fastify"; -import * as fs from "node:fs"; -import path from "node:path"; -import { URL } from "node:url"; -import { clearCacheCron } from "../shared/utils/cron/clear-cache-cron"; -import { env } from "../shared/utils/env"; -import { logger } from "../shared/utils/logger"; -import { metricsServer } from "../shared/utils/prometheus"; -import { withServerUsageReporting } from "../shared/utils/usage"; -import { updateTxListener } from "./listeners/update-tx-listener"; -import { withAdminRoutes } from "./middleware/admin-routes"; -import { withAuth } from "./middleware/auth"; -import { withCors } from "./middleware/cors"; -import { withEnforceEngineMode } from "./middleware/engine-mode"; -import { withErrorHandler } from "./middleware/error"; -import { withRequestLogs } from "./middleware/logs"; -import { withOpenApi } from "./middleware/open-api"; -import { withPrometheus } from "./middleware/prometheus"; -import { withRateLimit } from "./middleware/rate-limit"; -import { withSecurityHeaders } from "./middleware/security-headers"; -import { withWebSocket } from "./middleware/websocket"; -import { withRoutes } from "./routes"; -import { writeOpenApiToFile } from "./utils/openapi"; - -// The server timeout in milliseconds. -// Source: https://fastify.dev/docs/latest/Reference/Server/#connectiontimeout -const SERVER_CONNECTION_TIMEOUT = 60_000; - -const __dirname = new URL(".", import.meta.url).pathname; - -interface HttpsObject { - https: { - key: Buffer; - cert: Buffer; - passphrase?: string; - }; -} - -export const initServer = async () => { - // Enables the server to run on https://localhost:PORT, if ENABLE_HTTPS is provided. - let httpsObject: HttpsObject | undefined = undefined; - if (env.ENABLE_HTTPS) { - httpsObject = { - https: { - key: fs.readFileSync(path.join(__dirname, "../https/key.pem")), - cert: fs.readFileSync(path.join(__dirname, "../https/cert.pem")), - passphrase: env.HTTPS_PASSPHRASE, - }, - }; - } - - // env.TRUST_PROXY is used to determine if the X-Forwarded-For header should be trusted. - // This option is force enabled for cloud-hosted Engines. - // See: https://fastify.dev/docs/latest/Reference/Server/#trustproxy - const trustProxy = env.TRUST_PROXY || !!env.ENGINE_TIER; - if (trustProxy) { - logger({ - service: "server", - level: "info", - message: "Server is enabled with trustProxy.", - }); - } - - // Start the server with middleware. - const server: FastifyInstance = fastify({ - maxParamLength: 200, - connectionTimeout: SERVER_CONNECTION_TIMEOUT, - disableRequestLogging: true, - trustProxy, - ...(env.ENABLE_HTTPS ? httpsObject : {}), - }).withTypeProvider(); - - // Configure middleware - withErrorHandler(server); - withRequestLogs(server); - withSecurityHeaders(server); - withCors(server); - withRateLimit(server); - withEnforceEngineMode(server); - withServerUsageReporting(server); - withPrometheus(server); - - // Register routes - await withWebSocket(server); - await withAuth(server); - await withOpenApi(server); - await withRoutes(server); - await withAdminRoutes(server); - - await server.ready(); - - // if metrics are enabled, expose the metrics endpoint - if (env.METRICS_ENABLED) { - await metricsServer.ready(); - metricsServer.listen({ - host: env.HOST, - port: env.METRICS_PORT, - }); - } - - server.listen( - { - host: env.HOST, - port: env.PORT, - }, - (err) => { - if (err) { - logger({ - service: "server", - level: "fatal", - message: "Failed to start server", - error: err, - }); - process.exit(1); - } - }, - ); - - const url = `${env.ENABLE_HTTPS ? "https://" : "http://"}localhost:${ - env.PORT - }`; - - logger({ - service: "server", - level: "info", - message: `Engine server is listening on port ${ - env.PORT - }. Add to your dashboard: https://thirdweb.com/dashboard/engine?importUrl=${encodeURIComponent( - url, - )}.`, - }); - - writeOpenApiToFile(server); - await updateTxListener(); - await clearCacheCron("server"); -}; diff --git a/src/server/listeners/update-tx-listener.ts b/src/server/listeners/update-tx-listener.ts deleted file mode 100644 index e7302fd0e..000000000 --- a/src/server/listeners/update-tx-listener.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { knex } from "../../shared/db/client"; -import { TransactionDB } from "../../shared/db/transactions/db"; -import { logger } from "../../shared/utils/logger"; -import { toTransactionSchema } from "../schemas/transaction"; -import { subscriptionsData } from "../schemas/websocket"; -import { - formatSocketMessage, - getStatusMessageAndConnectionStatus, -} from "../utils/websocket"; - -export const updateTxListener = async (): Promise => { - logger({ - service: "server", - level: "info", - message: "Listening for updated transactions", - }); - - const connection = await knex.client.acquireConnection(); - connection.query("LISTEN updated_transaction_data"); - - connection.on( - "notification", - async (msg: { channel: string; payload: string }) => { - const parsedPayload = JSON.parse(msg.payload); - - // Send websocket message - const index = subscriptionsData.findIndex( - (sub) => sub.requestId === parsedPayload.id, - ); - - if (index === -1) { - return; - } - - const userSubscription = subscriptionsData[index]; - const transaction = await TransactionDB.get(parsedPayload.id); - const returnData = transaction ? toTransactionSchema(transaction) : null; - - logger({ - service: "server", - level: "info", - message: `[updateTxListener] Sending websocket update for queueId: ${parsedPayload.id}, status ${returnData?.status}.`, - }); - - const { message, closeConnection } = - await getStatusMessageAndConnectionStatus(returnData); - userSubscription.socket.send( - await formatSocketMessage(returnData, message), - ); - closeConnection ? userSubscription.socket.close() : null; - }, - ); - - connection.on("end", async () => { - logger({ - service: "server", - level: "info", - message: "[updateTxListener] Connection database ended", - }); - - knex.client.releaseConnection(connection); - await knex.destroy(); - - logger({ - service: "server", - level: "info", - message: "[updateTxListener] Released database connection on end", - }); - }); - - connection.on("error", async (err: unknown) => { - logger({ - service: "server", - level: "error", - message: "[updateTxListener] Database connection error", - error: err, - }); - - knex.client.releaseConnection(connection); - await knex.destroy(); - - logger({ - service: "worker", - level: "info", - message: "[updateTxListener] Released database connection on error", - }); - }); -}; diff --git a/src/server/metrics.ts b/src/server/metrics.ts new file mode 100644 index 000000000..b41f159d7 --- /dev/null +++ b/src/server/metrics.ts @@ -0,0 +1,34 @@ +import { Hono } from "hono"; +import { enginePromRegister } from "../lib/prometheus.js"; +import { env } from "../lib/env.js"; +import { initializeLogger } from "../lib/logger.js"; + +const metricsLogger = initializeLogger("metrics"); +const metricsServer = new Hono(); + +metricsServer.get("/metrics", async (c) => { + const metrics = await enginePromRegister.metrics(); + c.header("Content-Type", enginePromRegister.contentType); + return c.body(metrics); +}); + +const tls = env.ENABLE_HTTPS + ? { + key: Bun.file("../https/key.pem"), + cert: Bun.file("../https/cert.pem"), + passphrase: env.HTTPS_PASSPHRASE, + } + : {}; + +if (env.METRICS_ENABLED) { + Bun.serve({ + port: env.METRICS_PORT, + tls: { + ...tls, + passphrase: env.HTTPS_PASSPHRASE, + }, + fetch: metricsServer.fetch, + }); +} + +metricsLogger.info(`Metrics server is listening on port ${env.METRICS_PORT}`); diff --git a/src/server/middleware/admin-routes.ts b/src/server/middleware/admin-routes.ts deleted file mode 100644 index f503a5b9b..000000000 --- a/src/server/middleware/admin-routes.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { createBullBoard } from "@bull-board/api"; -import { BullMQAdapter } from "@bull-board/api/bullMQAdapter"; -import { FastifyAdapter } from "@bull-board/fastify"; -import type { Queue } from "bullmq"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { timingSafeEqual } from "node:crypto"; -import { env } from "../../shared/utils/env"; -import { CancelRecycledNoncesQueue } from "../../worker/queues/cancel-recycled-nonces-queue"; -import { MineTransactionQueue } from "../../worker/queues/mine-transaction-queue"; -import { NonceHealthCheckQueue } from "../../worker/queues/nonce-health-check-queue"; -import { NonceResyncQueue } from "../../worker/queues/nonce-resync-queue"; -import { ProcessEventsLogQueue } from "../../worker/queues/process-event-logs-queue"; -import { ProcessTransactionReceiptsQueue } from "../../worker/queues/process-transaction-receipts-queue"; -import { PruneTransactionsQueue } from "../../worker/queues/prune-transactions-queue"; -import { SendTransactionQueue } from "../../worker/queues/send-transaction-queue"; -import { SendWebhookQueue } from "../../worker/queues/send-webhook-queue"; - -export const ADMIN_QUEUES_BASEPATH = "/admin/queues"; -const ADMIN_ROUTES_USERNAME = "admin"; -const ADMIN_ROUTES_PASSWORD = env.THIRDWEB_API_SECRET_KEY; - -// Add queues to monitor here. -const QUEUES: Queue[] = [ - SendWebhookQueue.q, - ProcessEventsLogQueue.q, - ProcessTransactionReceiptsQueue.q, - SendTransactionQueue.q, - MineTransactionQueue.q, - CancelRecycledNoncesQueue.q, - PruneTransactionsQueue.q, - NonceResyncQueue.q, - NonceHealthCheckQueue.q, -]; - -export const withAdminRoutes = async (fastify: FastifyInstance) => { - fastify.after(async () => { - // Create a new route for Bullboard routes. - const serverAdapter = new FastifyAdapter(); - serverAdapter.setBasePath(ADMIN_QUEUES_BASEPATH); - - createBullBoard({ - queues: QUEUES.map((q) => new BullMQAdapter(q)), - serverAdapter, - }); - - await fastify.register(serverAdapter.registerPlugin(), { - basePath: ADMIN_QUEUES_BASEPATH, - prefix: ADMIN_QUEUES_BASEPATH, - }); - - fastify.addHook("onRequest", async (req, reply) => { - if (req.url.startsWith(ADMIN_QUEUES_BASEPATH)) { - const authHeader = req.headers.authorization; - - if (!authHeader || !authHeader.startsWith("Basic ")) { - reply - .status(StatusCodes.UNAUTHORIZED) - .header("WWW-Authenticate", 'Basic realm="Admin Routes"') - .send({ error: "Unauthorized" }); - return; - } - - // Parse the basic auth credentials (`Basic `). - const base64Credentials = authHeader.split(" ")[1]; - const credentials = Buffer.from(base64Credentials, "base64").toString( - "utf8", - ); - const [username, password] = credentials.split(":"); - - if (!assertAdminBasicAuth(username, password)) { - reply - .status(StatusCodes.UNAUTHORIZED) - .header("WWW-Authenticate", 'Basic realm="Admin Routes"') - .send({ error: "Unauthorized" }); - return; - } - } - }); - }); -}; - -const assertAdminBasicAuth = (username: string, password: string) => { - if (username === ADMIN_ROUTES_USERNAME) { - try { - const buf1 = Buffer.from(password.padEnd(100)); - const buf2 = Buffer.from(ADMIN_ROUTES_PASSWORD.padEnd(100)); - return timingSafeEqual(buf1, buf2); - } catch {} - } - return false; -}; diff --git a/src/server/middleware/auth.ts b/src/server/middleware/auth.ts deleted file mode 100644 index fb21508da..000000000 --- a/src/server/middleware/auth.ts +++ /dev/null @@ -1,546 +0,0 @@ -import { parseJWT } from "@thirdweb-dev/auth"; -import { - ThirdwebAuth, - getToken as getJWT, - type ThirdwebAuthUser, -} from "@thirdweb-dev/auth/fastify"; -import { AsyncWallet } from "@thirdweb-dev/wallets/evm/wallets/async"; -import type { FastifyInstance } from "fastify"; -import type { FastifyRequest } from "fastify/types/request"; -import jsonwebtoken, { type JwtPayload } from "jsonwebtoken"; -import { createHash } from "node:crypto"; -import { validate as uuidValidate } from "uuid"; -import { getPermissions } from "../../shared/db/permissions/get-permissions"; -import { createToken } from "../../shared/db/tokens/create-token"; -import { revokeToken } from "../../shared/db/tokens/revoke-token"; -import { WebhooksEventTypes } from "../../shared/schemas/webhooks"; -import { THIRDWEB_DASHBOARD_ISSUER, handleSiwe } from "../../shared/utils/auth"; -import { getAccessToken } from "../../shared/utils/cache/access-token"; -import { getAuthWallet } from "../../shared/utils/cache/auth-wallet"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { getWebhooksByEventType } from "../../shared/utils/cache/get-webhook"; -import { getKeypair } from "../../shared/utils/cache/keypair"; -import { env } from "../../shared/utils/env"; -import { logger } from "../../shared/utils/logger"; -import { sendWebhookRequest } from "../../shared/utils/webhook"; -import { Permission } from "../../shared/schemas/auth"; -import { ADMIN_QUEUES_BASEPATH } from "./admin-routes"; -import { OPENAPI_ROUTES } from "./open-api"; - -export type TAuthData = never; -export type TAuthSession = { permissions: string }; - -interface AuthResponse { - isAuthed: boolean; - user?: ThirdwebAuthUser; - // If error is provided, return an error immediately. - error?: string; -} - -declare module "fastify" { - interface FastifyRequest { - user: ThirdwebAuthUser; - } -} - -export async function withAuth(server: FastifyInstance) { - const config = await getConfig(); - - // Configure the ThirdwebAuth fastify plugin - const { authRouter, authMiddleware, getUser } = ThirdwebAuth< - TAuthData, - TAuthSession - >({ - // TODO: Domain needs to be pulled from config as well - domain: config.authDomain, - // We use an async wallet here to load wallet from config every time - wallet: new AsyncWallet({ - getSigner: async () => { - const authWallet = await getAuthWallet(); - return authWallet.getSigner(); - }, - cacheSigner: false, - }), - callbacks: { - onLogin: async (walletAddress) => { - // When a user logs in, we check for their permissions in the database - const res = await getPermissions({ walletAddress }); - - // And we add their permissions as a scope to their JWT - return { - // TODO: Replace with default permissions - permissions: res?.permissions || "none", - }; - }, - onToken: async (jwt) => { - // When a new JWT is generated, we save it in the database - await createToken({ jwt, isAccessToken: false }); - }, - onLogout: async (_, req) => { - const jwt = getJWT(req); - if (!jwt) { - return; - } - - const { payload } = parseJWT(jwt); - - try { - await revokeToken({ id: payload.jti }); - } catch { - logger({ - service: "server", - level: "error", - message: `[Auth] Failed to revoke token ${payload.jti}`, - }); - } - }, - }, - }); - - // Setup the auth router and auth middleware - await server.register(authRouter, { prefix: "/auth" }); - await server.register(authMiddleware); - - // Decorate the request with a null user - server.decorateRequest("user", null); - - // Add auth validation middleware to check for authenticated requests - // Note: in the onRequest hook, request.body will always be undefined, because the body parsing happens before the preValidation hook. - // https://fastify.dev/docs/latest/Reference/Hooks/#onrequest - server.addHook("preValidation", async (req, res) => { - // Skip auth check in sandbox mode - if (env.ENGINE_MODE === "sandbox") { - return; - } - let message = - "Please provide a valid access token or other authentication. See: https://portal.thirdweb.com/engine/features/access-tokens"; - - try { - const { isAuthed, user, error } = await onRequest({ req, getUser }); - if (isAuthed) { - if (user) { - req.user = user; - } - // Allow this request to proceed. - return; - } - if (error) { - message = error; - } - } catch (err: unknown) { - logger({ - service: "server", - level: "warn", - message: "Error authenticating user", - error: err, - }); - } - - return res.status(401).send({ - error: "Unauthorized", - message, - }); - }); -} - -export const onRequest = async ({ - req, - getUser, -}: { - req: FastifyRequest; - getUser: ReturnType>["getUser"]; -}): Promise => { - // Handle websocket auth separately. - if (req.headers.upgrade?.toLowerCase() === "websocket") { - return handleWebsocketAuth(req, getUser); - } - - const publicRoutesResp = handlePublicEndpoints(req); - if (publicRoutesResp.isAuthed) { - return publicRoutesResp; - } - - const jwt = getJWT(req); - if (jwt) { - const decoded = jsonwebtoken.decode(jwt, { complete: true }); - if (decoded) { - const payload = decoded.payload as JwtPayload; - const header = decoded.header; - - // Get the public key from the `iss` payload field. - const publicKey = payload.iss; - if (publicKey) { - const authWallet = await getAuthWallet(); - if (publicKey === (await authWallet.getAddress())) { - return await handleAccessToken(jwt, req, getUser); - } - if (publicKey === THIRDWEB_DASHBOARD_ISSUER) { - return await handleDashboardAuth(jwt); - } - return await handleKeypairAuth({ jwt, req, publicKey }); - } - - // Get the public key hash from the `kid` header. - const publicKeyHash = header.kid; - if (publicKeyHash) { - return await handleKeypairAuth({ jwt, req, publicKeyHash }); - } - } - } - - const secretKeyResp = await handleSecretKey(req); - if (secretKeyResp.isAuthed) { - return secretKeyResp; - } - - const authWebhooksResp = await handleAuthWebhooks(req); - if (authWebhooksResp.isAuthed) { - return authWebhooksResp; - } - - // Unauthorized: no auth patterns matched. - return { isAuthed: false }; -}; - -/** - * Handles unauthed routes. - * @param req FastifyRequest - * @returns AuthResponse - */ -const handlePublicEndpoints = (req: FastifyRequest): AuthResponse => { - if (req.method === "GET") { - if ( - req.url === "/favicon.ico" || - req.url === "/" || - req.url === "/system/health" || - OPENAPI_ROUTES.includes(req.url) || - req.url.startsWith("/auth/user") || - req.url.startsWith("/transaction/status") - ) { - return { isAuthed: true }; - } - } else if (req.method === "POST") { - if ( - req.url.startsWith("/auth/payload") || - req.url.startsWith("/auth/login") || - req.url.startsWith("/auth/switch-account") || - req.url.startsWith("/auth/logout") - ) { - return { isAuthed: true }; - } - - if (req.url.startsWith("/relayer/")) { - const relayerId = req.url.slice("/relayer/".length); - if (uuidValidate(relayerId)) { - // "Relay transaction" endpoint which handles its own authentication. - return { isAuthed: true }; - } - } - } - - // Admin routes enforce their own auth. - if (req.url.startsWith(ADMIN_QUEUES_BASEPATH)) { - return { isAuthed: true }; - } - - return { isAuthed: false }; -}; - -/** - * Handle websocket request: auth via access token - * Allow a request that provides a non-revoked access token for an owner/admin - * Handle websocket auth separately. - * @param req FastifyRequest - * @param getUser - * @returns AuthResponse - * @async - */ -const handleWebsocketAuth = async ( - req: FastifyRequest, - getUser: ReturnType>["getUser"], -): Promise => { - const { token: jwt } = req.query as { token: string }; - - const token = await getAccessToken({ jwt }); - if (token && token.revokedAt === null) { - // Set as a header for `getUsers` to parse the token. - req.headers.authorization = `Bearer ${jwt}`; - const user = await getUser(req); - - const { isAllowed, ip } = await checkIpInAllowlist(req); - if (!isAllowed) { - logger({ - service: "server", - level: "error", - message: `Unauthorized IP address: ${ip}`, - }); - return { - isAuthed: false, - error: - "Unauthorized IP address. See: https://portal.thirdweb.com/engine/features/security", - }; - } - - if ( - user?.session?.permissions === Permission.Owner || - user?.session?.permissions === Permission.Admin - ) { - return { isAuthed: true, user }; - } - } - - // Destroy the websocket connection. - req.raw.socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n"); - req.raw.socket.destroy(); - return { isAuthed: false }; -}; - -/** - * Auth via keypair. - * Allow a request that provides a JWT signed by an ES256 private key - * matching the configured public key. - * @param jwt string - * @param req FastifyRequest - * @param publicKey string - * @returns AuthResponse - */ -const handleKeypairAuth = async (args: { - jwt: string; - req: FastifyRequest; - publicKey?: string; - publicKeyHash?: string; -}): Promise => { - // The keypair auth feature must be explicitly enabled. - if (!env.ENABLE_KEYPAIR_AUTH) { - return { isAuthed: false }; - } - - const { jwt, req, publicKey, publicKeyHash } = args; - - let error: string | undefined; - try { - const keypair = await getKeypair({ publicKey, publicKeyHash }); - if (!keypair) { - error = "The provided public key is incorrect or not added to Engine."; - throw error; - } - - // The JWT is valid if `verify` did not throw. - const payload = jsonwebtoken.verify(jwt, keypair.publicKey, { - algorithms: [keypair.algorithm as jsonwebtoken.Algorithm], - }) as jsonwebtoken.JwtPayload; - - // If `bodyHash` is provided, it must match a hash of the POST request body. - if ( - req.method === "POST" && - payload?.bodyHash && - payload.bodyHash !== hashRequestBody(req) - ) { - error = - "The request body does not match the hash in the access token. See: https://portal.thirdweb.com/engine/features/keypair-authentication"; - throw error; - } - - const { isAllowed, ip } = await checkIpInAllowlist(req); - if (!isAllowed) { - logger({ - service: "server", - level: "error", - message: `Unauthorized IP address: ${ip}`, - }); - throw new Error( - "Unauthorized IP address. See: https://portal.thirdweb.com/engine/features/security", - ); - } - return { isAuthed: true }; - } catch (e) { - if (e instanceof jsonwebtoken.TokenExpiredError) { - error = "Keypair token is expired."; - } else if (!error) { - // Default error. - error = - 'Error parsing "Authorization" header. See: https://portal.thirdweb.com/engine/features/access-tokens'; - } - } - - return { isAuthed: false, error }; -}; - -/** - * Auth via access token. - * Allow a request that provides a non-revoked access token for an owner/admin. - * @param jwt string - * @param req FastifyRequest - * @param getUser - * @returns AuthResponse - * @async - */ -const handleAccessToken = async ( - jwt: string, - req: FastifyRequest, - getUser: ReturnType>["getUser"], -): Promise => { - let token: Awaited> = null; - - try { - token = await getAccessToken({ jwt }); - } catch (_e) { - // Missing or invalid signature. This will occur if the JWT not intended for this auth pattern. - return { isAuthed: false }; - } - - if (!token || token.revokedAt) { - return { isAuthed: false }; - } - - const user = await getUser(req); - - if ( - user?.session?.permissions !== Permission.Owner && - user?.session?.permissions !== Permission.Admin - ) { - return { isAuthed: false }; - } - - const { isAllowed, ip } = await checkIpInAllowlist(req); - if (!isAllowed) { - logger({ - service: "server", - level: "error", - message: `Unauthorized IP address: ${ip}`, - }); - return { - isAuthed: false, - error: - "Unauthorized IP address. See: https://portal.thirdweb.com/engine/features/security", - }; - } - - return { isAuthed: true, user }; -}; - -/** - * Auth via dashboard. - * Allow a request that provides a dashboard JWT. - * @param jwt string - * @returns AuthResponse - * @async - */ -const handleDashboardAuth = async (jwt: string): Promise => { - const user = - (await handleSiwe(jwt, "thirdweb.com", THIRDWEB_DASHBOARD_ISSUER)) || - (await handleSiwe(jwt, "thirdweb-preview.com", THIRDWEB_DASHBOARD_ISSUER)); - if (user) { - const res = await getPermissions({ walletAddress: user.address }); - if ( - res?.permissions === Permission.Owner || - res?.permissions === Permission.Admin - ) { - return { - isAuthed: true, - user: { - address: user.address, - session: { - permissions: res.permissions, - }, - }, - }; - } - } - - return { isAuthed: false }; -}; - -/** - * Auth via thirdweb secret key. - * Allow a request that provides the thirdweb secret key used to init Engine. - * - * @param req FastifyRequest - * @returns - */ -const handleSecretKey = async (req: FastifyRequest): Promise => { - const thirdwebApiSecretKey = req.headers.authorization?.split(" ")[1]; - if (thirdwebApiSecretKey === env.THIRDWEB_API_SECRET_KEY) { - const authWallet = await getAuthWallet(); - return { - isAuthed: true, - user: { - address: await authWallet.getAddress(), - session: { - permissions: Permission.Admin, - }, - }, - }; - } - - return { isAuthed: false }; -}; - -/** - * Auth via auth webhooks - * Allow a request if it satisfies all configured auth webhooks. - * Must have at least one auth webhook. - * @param req FastifyRequest - * @returns AuthResponse - * @async - */ -const handleAuthWebhooks = async ( - req: FastifyRequest, -): Promise => { - const authWebhooks = await getWebhooksByEventType(WebhooksEventTypes.AUTH); - if (authWebhooks.length > 0) { - const authResponses = await Promise.all( - authWebhooks.map(async (webhook) => { - const { ok } = await sendWebhookRequest(webhook, { - url: req.url, - method: req.method, - headers: req.headers, - params: req.params, - query: req.query, - cookies: req.cookies, - body: req.body, - }); - return ok; - }), - ); - - if (authResponses.every((ok) => !!ok)) { - return { isAuthed: true }; - } - } - - return { isAuthed: false }; -}; - -const hashRequestBody = (req: FastifyRequest): string => { - return createHash("sha256") - .update(JSON.stringify(req.body), "utf8") - .digest("hex"); -}; - -/** - * Check if the request IP is in the allowlist. - * Fetches cached config if available. - * @param req FastifyRequest - * @returns boolean - * @async - */ -const checkIpInAllowlist = async ( - req: FastifyRequest, -): Promise<{ isAllowed: boolean; ip: string }> => { - let ip = req.ip; - const trustProxy = env.TRUST_PROXY || !!env.ENGINE_TIER; - if (trustProxy && req.headers["cf-connecting-ip"]) { - ip = req.headers["cf-connecting-ip"] as string; - } - - const config = await getConfig(); - if (config.ipAllowlist.length === 0) { - return { isAllowed: true, ip }; - } - - return { - isAllowed: config.ipAllowlist.includes(ip), - ip, - }; -}; diff --git a/src/server/middleware/auth/access-token.ts b/src/server/middleware/auth/access-token.ts new file mode 100644 index 000000000..d940747d4 --- /dev/null +++ b/src/server/middleware/auth/access-token.ts @@ -0,0 +1,41 @@ +import { createAuth } from "thirdweb/auth"; +import type { JWTPayload } from "thirdweb/utils"; +import { engineErrToHttpException, type AuthErr } from "../../../lib/errors.js"; +import { err, ok, ResultAsync } from "neverthrow"; +import { extractJwt, mapJwtError } from "./shared.js"; +import { createMiddleware } from "hono/factory"; +import { getAccessToken } from "../../../lib/access-tokens.js"; +import { checkPermissions } from "../../../lib/permissions.js"; +import { config } from "../../../lib/config.js"; +import { adminAccount } from "../../../lib/admin-account.js"; + +function verifyJwt(jwt: string): ResultAsync { + const auth = createAuth({ + domain: config.authDomain, + adminAccount, + }); + + return ResultAsync.fromPromise(auth.verifyJWT({ jwt }), mapJwtError).andThen( + (result) => + result.valid ? ok(result.parsedJWT) : err(mapJwtError(result.error)), + ); +} + +export const accessTokenAuth = createMiddleware(async (c, next) => { + const auth = await extractJwt(c.req.header("authorization")) + .asyncAndThen(verifyJwt) + .andThen((payload) => getAccessToken(payload.jti)) + .andThen(({ accountAddress }) => + checkPermissions({ + address: accountAddress, + allowedPermissions: ["ADMIN", "OWNER"], + }), + ); + + if (auth.isErr()) { + throw engineErrToHttpException(auth.error); + } + + c.set("user", auth.value); + await next(); +}); diff --git a/src/server/middleware/auth/dashboard.ts b/src/server/middleware/auth/dashboard.ts new file mode 100644 index 000000000..3b6b707fd --- /dev/null +++ b/src/server/middleware/auth/dashboard.ts @@ -0,0 +1,59 @@ +import { createAuth } from "thirdweb/auth"; +import type { Permission } from "../../../db/types.js"; +import { + engineErrToHttpException, + type AuthErr, + type DbErr, +} from "../../../lib/errors.js"; +import { err, ok, type Result, ResultAsync } from "neverthrow"; +import { getAddress, type JWTPayload } from "thirdweb/utils"; +import { createMiddleware } from "hono/factory"; +import { extractJwt, mapJwtError } from "./shared.js"; +import { checkPermissions } from "../../../lib/permissions.js"; + +const THIRDWEB_DASHBOARD_ISSUER = "0x016757dDf2Ab6a998a4729A80a091308d9059E17"; + +export type AuthResult = Result< + { address: string; permissions: Permission }, + AuthErr | DbErr +>; + +function verifyJwt(jwt: string): ResultAsync { + const prodAuth = createAuth({ + domain: "thirdweb.com", + // @ts-expect-error We only want to verify recovered signer + adminAccount: { address: THIRDWEB_DASHBOARD_ISSUER }, + }); + + const previewAuth = createAuth({ + domain: "thirdweb-preview.com", + // @ts-expect-error We only want to verify recovered signer + adminAccount: { address: THIRDWEB_DASHBOARD_ISSUER }, + }); + + return ResultAsync.fromPromise(prodAuth.verifyJWT({ jwt }), mapJwtError) + .orElse(() => + ResultAsync.fromPromise(previewAuth.verifyJWT({ jwt }), mapJwtError), + ) + .andThen((result) => + result.valid ? ok(result.parsedJWT) : err(mapJwtError(result.error)), + ); +} + +export const dashboardAuth = createMiddleware(async (c, next) => { + const auth = await extractJwt(c.req.header("authorization")) + .asyncAndThen(verifyJwt) + .andThen((payload) => + checkPermissions({ + address: getAddress(payload.sub), + allowedPermissions: ["ADMIN", "OWNER"], + }), + ); + + if (auth.isErr()) { + throw engineErrToHttpException(auth.error); + } + + c.set("user", auth.value); + await next(); +}); diff --git a/src/server/middleware/auth/keypair.ts b/src/server/middleware/auth/keypair.ts new file mode 100644 index 000000000..2b7865741 --- /dev/null +++ b/src/server/middleware/auth/keypair.ts @@ -0,0 +1,99 @@ +import { errAsync, okAsync, ResultAsync } from "neverthrow"; +import { + engineErrToHttpException, + type AuthErr, + type DbErr, +} from "../../../lib/errors.js"; +import { decode, verify } from "hono/jwt"; +import { getKeypair } from "../../../lib/keypairs.js"; +import { createMiddleware } from "hono/factory"; +import { env } from "../../../lib/env.js"; +import { HTTPException } from "hono/http-exception"; +import { extractJwt } from "./shared.js"; +import type { KeypairDbEntry } from "../../../db/types.js"; +import { createHash } from "node:crypto"; + +function checkKeypairAuth({ + jwt, + actualBodyHash, +}: { + jwt: string; + actualBodyHash: string; +}): ResultAsync { + // First decode without verification to get the keypair info + const decoded = decode(jwt); + + // Get keypair from our DB + return getKeypair({ + publicKey: decoded.payload.iss as string, + publicKeyHash: decoded.header.kid as string, + }) + .andThrough(() => { + if (decoded.payload.bodyHash) { + const actualBodyHashBytes = Buffer.from(actualBodyHash, "hex"); + const expectedBodyHashBytes = Buffer.from( + decoded.payload.bodyHash as string, + "hex" + ); + + if (!actualBodyHashBytes.equals(expectedBodyHashBytes)) { + return errAsync({ + kind: "auth", + code: "invalid_body_hash", + status: 401, + } as AuthErr); + } + } + + return okAsync("ok"); + }) + .andThrough((keypair) => + // Verify signature with keypair + ResultAsync.fromPromise( + // Assuming verifyJWT handles ES256/RS256 etc based on algorithm + verify(jwt, keypair.publicKey, keypair.algorithm), + + (): AuthErr => + ({ + kind: "auth", + code: "invalid_signature", + status: 401, + } as const) + ) + ) + .mapErr((err) => { + if (err.kind === "keypair") { + return { + kind: "auth", + code: "invalid_keypair", + status: 401, + } as AuthErr; + } + return err; + }); +} + +export const keypairAuth = createMiddleware(async (c, next) => { + if (!env.ENABLE_KEYPAIR_AUTH) { + throw new HTTPException(403, { + message: "Keypair authentication is not enabled", + }); + } + + const actualBodyHash = await c.req + .arrayBuffer() + .then((buffer) => + createHash("sha256").update(new Uint8Array(buffer)).digest("hex") + ); + + const result = await extractJwt(c.req.header("authorization")).asyncAndThen( + (jwt) => checkKeypairAuth({ jwt, actualBodyHash }) + ); + + if (result.isErr()) { + throw engineErrToHttpException(result.error); + } + + c.set("keypair", result.value); + await next(); +}); diff --git a/src/server/middleware/auth/secret-key.ts b/src/server/middleware/auth/secret-key.ts new file mode 100644 index 000000000..73ba8d238 --- /dev/null +++ b/src/server/middleware/auth/secret-key.ts @@ -0,0 +1,23 @@ +import { createMiddleware } from "hono/factory"; +import { env } from "../../../lib/env.js"; +import { engineErrToHttpException } from "../../../lib/errors.js"; +import { extractJwt } from "./shared.js"; + +export const secretKeyAuth = createMiddleware(async (c, next) => { + const secretKey = extractJwt(c.req.header("authorization")); + + if (secretKey.isErr()) { + throw engineErrToHttpException(secretKey.error); + } + + if (secretKey.value === env.THIRDWEB_API_SECRET_KEY) { + return await next(); + } + + throw engineErrToHttpException({ + kind: "auth", + code: "invalid_jwt", + status: 401, + message: "Invalid secret key", + } as const); +}); diff --git a/src/server/middleware/auth/shared.ts b/src/server/middleware/auth/shared.ts new file mode 100644 index 000000000..43ec25d67 --- /dev/null +++ b/src/server/middleware/auth/shared.ts @@ -0,0 +1,83 @@ +import { err, ok, type Result } from "neverthrow"; +import type { AuthErr, HttpErrStatusCode } from "../../../lib/errors.js"; + +export function extractJwt( + authHeader: string | undefined, +): Result { + if (!authHeader?.startsWith("Bearer ")) { + return err({ + kind: "auth", + code: "missing_auth_header", + status: 401, + }); + } + + const jwt = authHeader.split(" ")[1]; + + if (!jwt) { + return err({ + kind: "auth", + code: "malformed_auth_header", + status: 401 as HttpErrStatusCode, + }); + } + return ok(jwt); +} + +export function mapJwtError(error: string | Error | unknown): AuthErr { + const message = error instanceof Error ? error.message : String(error); + + // Categorize standard JWT validation errors + if (message.includes("Invalid JWT ID")) { + return { + kind: "auth", + code: "invalid_jwt", + status: 401, + message: "Invalid JWT ID", + } as const; + } + + if (message.includes("domain")) { + return { + kind: "auth", + code: "invalid_jwt", + status: 401, + message: "Invalid token domain", + } as const; + } + + if (message.includes("expired")) { + return { + kind: "auth", + code: "expired_jwt", + status: 401, + message: "Token has expired", + } as const; + } + + if (message.includes("invalid before")) { + return { + kind: "auth", + code: "invalid_jwt", + status: 401, + message: "Token not yet valid", + } as const; + } + + if (message.includes("issuer address")) { + return { + kind: "auth", + code: "invalid_signature", + status: 401, + message: "Invalid token issuer", + } as const; + } + + // Default case for unknown errors + return { + kind: "auth", + code: "invalid_jwt", + status: 401, + source: error instanceof Error ? error : undefined, + } as const; +} diff --git a/src/server/middleware/auth/types.ts b/src/server/middleware/auth/types.ts new file mode 100644 index 000000000..c4395d5bb --- /dev/null +++ b/src/server/middleware/auth/types.ts @@ -0,0 +1,19 @@ +import type { Permission } from "../../../db/types.js"; + +export type AuthContext = { + Variables: { + user?: { + address: string; + permissions: Permission[]; + }; + keypair?: { + createdAt: Date; + hash: string; + label: string | null; + updatedAt: Date; + deletedAt: Date | null; + publicKey: string; + algorithm: "RS256" | "ES256" | "PS256"; + }; + }; +}; \ No newline at end of file diff --git a/src/server/middleware/auth/webhook.ts b/src/server/middleware/auth/webhook.ts new file mode 100644 index 000000000..5a5c48706 --- /dev/null +++ b/src/server/middleware/auth/webhook.ts @@ -0,0 +1,62 @@ +import type { Context } from "hono"; +import { createMiddleware } from "hono/factory"; +import { okAsync, ResultAsync } from "neverthrow"; +import { + engineErrToHttpException, + mapDbError, + type AuthErr, + type DbErr, + type WebhookErr, +} from "../../../lib/errors.js"; +import { db } from "../../../db/connection.js"; +import { sendWebhookRequest } from "../../../lib/webhooks/send-webhook.js"; +import { getCookie } from "hono/cookie"; + +function checkWebhookAuth( + c: Context, +): ResultAsync { + return ResultAsync.fromPromise( + db.query.webhooks.findMany({ + where: (webhooks, { or, eq }) => or(eq(webhooks.eventType, "AUTH")), + }), + mapDbError, + ).andThen((webhooks) => { + if (webhooks.length === 0) { + return okAsync(false); + } + + const webhookRequests = webhooks.map((webhook) => + sendWebhookRequest(webhook, { + url: c.req.url, + method: c.req.method, + headers: c.req.header(), + params: c.req.param(), + query: c.req.query(), + cookies: getCookie(c), + body: c.req.json(), + }), + ); + + return ResultAsync.combine(webhookRequests).map((responses) => + responses.every((r) => r.ok), + ); + }); +} + +export const webhookAuth = createMiddleware(async (c, next) => { + const result = await checkWebhookAuth(c); + if (result.isErr()) { + throw result.error; + } + + if (!result.value) { + throw engineErrToHttpException({ + code: "webhook_auth_failed", + kind: "auth", + status: 401, + message: "Webhook authentication failed", + } as AuthErr); + } + + await next(); +}); diff --git a/src/server/middleware/correlation-id.ts b/src/server/middleware/correlation-id.ts new file mode 100644 index 000000000..48ebada70 --- /dev/null +++ b/src/server/middleware/correlation-id.ts @@ -0,0 +1,22 @@ +import { createMiddleware } from "hono/factory"; + +export const correlationId = createMiddleware<{ + Variables: { correlationId: string }; +}>(async (ctx, next) => { + // Check if the correlation-id header exists + let correlationId = ctx.req.header("x-correlation-id"); + + // If the header does not exist, generate a new one + if (!correlationId) { + correlationId = crypto.randomUUID(); + } + + // Set the correlationId in the context + ctx.set("correlationId", correlationId); + + // Proceed to the next middleware or route handler + await next(); + + // Ensure the correlation-id header is set in the response + ctx.header("x-correlation-id", correlationId); +}); diff --git a/src/server/middleware/cors.ts b/src/server/middleware/cors.ts index de7e15231..e79214244 100644 --- a/src/server/middleware/cors.ts +++ b/src/server/middleware/cors.ts @@ -1,96 +1,52 @@ -import type { FastifyInstance } from "fastify"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { ADMIN_QUEUES_BASEPATH } from "./admin-routes"; +import { createMiddleware } from "hono/factory"; -const STANDARD_METHODS = "GET,POST,DELETE,PUT,PATCH,HEAD,PUT,PATCH,POST,DELETE"; -const DEFAULT_ALLOWED_HEADERS = [ - "Authorization", - "Content-Type", - "ngrok-skip-browser-warning", -]; +import { cors } from "hono/cors"; +import { HTTPException } from "hono/http-exception"; -export function withCors(server: FastifyInstance) { - server.addHook("onRequest", async (request, reply) => { - const origin = request.headers.origin; +// For standard API routes with configurable origins +export function createApiCorsMiddleware(config: { allowedOrigins: string[] }) { + return cors({ + origin: (origin) => { + if (!origin) return undefined; - // Allow backend calls (no origin header). - if (!origin) { - return; - } - - // Allow admin routes to be accessed from the same host. - if (request.url.startsWith(ADMIN_QUEUES_BASEPATH)) { - const host = request.headers.host; - const originHost = new URL(origin).host; - if (originHost !== host) { - reply.code(403).send({ error: "Invalid origin" }); - return; - } - return; - } - - const config = await getConfig(); - const allowedOrigins = config.accessControlAllowOrigin - .split(",") - .map(sanitizeOrigin); - - // Always set `Vary: Origin` to prevent caching issues even on invalid origins. - reply.header("Vary", "Origin"); - - if (isAllowedOrigin(origin, allowedOrigins)) { - // Set CORS headers if valid origin. - reply.header("Access-Control-Allow-Origin", origin); - reply.header("Access-Control-Allow-Methods", STANDARD_METHODS); - - // Handle preflight requests - if (request.method === "OPTIONS") { - const requestedHeaders = - request.headers["access-control-request-headers"]; - reply.header( - "Access-Control-Allow-Headers", - requestedHeaders ?? DEFAULT_ALLOWED_HEADERS.join(","), - ); - - reply.header("Cache-Control", "public, max-age=3600"); - reply.header("Access-Control-Max-Age", "3600"); - reply.code(204).send(); - return; - } - } else { - reply.code(403).send({ error: "Invalid origin." }); - return; - } - }); -} - -function isAllowedOrigin(origin: string, allowedOrigins: string[]) { - return ( - allowedOrigins - // Check if the origin matches any allowed origins. - .some((allowed) => { + const isOriginAllowed = config.allowedOrigins.some((allowed) => { if (allowed === "https://thirdweb-preview.com/") { return /^https?:\/\/.*\.thirdweb-preview\.com$/.test(origin); } if (allowed === "https://thirdweb-dev.com/") { return /^https?:\/\/.*\.thirdweb-dev\.com$/.test(origin); } - - // Allow wildcards in the origin. For example "foo.example.com" matches "*.example.com" if (allowed.includes("*")) { const wildcardPattern = allowed.replace(/\*/g, ".*"); const regex = new RegExp(`^${wildcardPattern}$`); return regex.test(origin); } - - // Otherwise check for an exact match. return origin === allowed; - }) - ); + }); + + return isOriginAllowed ? origin : undefined; + }, + allowMethods: ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"], + allowHeaders: [ + "Authorization", + "Content-Type", + "ngrok-skip-browser-warning", + ], + maxAge: 3600, + }); } -function sanitizeOrigin(origin: string) { - if (origin.endsWith("/")) { - return origin.slice(0, -1); +// For admin routes that only allow same-origin requests +export const sameOriginMiddleware = createMiddleware(async (c, next) => { + const origin = c.req.header("origin"); + if (!origin) return await next(); + + const host = c.req.header("host"); + const originHost = new URL(origin).host; + + if (originHost !== host) { + throw new HTTPException(403, { message: "Invalid origin" }); } - return origin; -} + + return await next(); +}); diff --git a/src/server/middleware/engine-mode.ts b/src/server/middleware/engine-mode.ts deleted file mode 100644 index 9abd2c220..000000000 --- a/src/server/middleware/engine-mode.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { env } from "../../shared/utils/env"; - -export function withEnforceEngineMode(server: FastifyInstance) { - if (env.ENGINE_MODE === "sandbox") { - server.addHook("onRequest", async (request, reply) => { - if (request.method !== "GET") { - return reply.status(405).send({ - statusCode: 405, - error: "Engine is in read-only mode. Only GET requests are allowed.", - message: - "Engine is in read-only mode. Only GET requests are allowed.", - }); - } - }); - } -} diff --git a/src/server/middleware/error.ts b/src/server/middleware/error.ts deleted file mode 100644 index 92dbf8200..000000000 --- a/src/server/middleware/error.ts +++ /dev/null @@ -1,136 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { ReasonPhrases, StatusCodes } from "http-status-codes"; -import { ZodError } from "zod"; -import { env } from "../../shared/utils/env"; -import { parseEthersError } from "../../shared/utils/ethers"; - -export type CustomError = { - message: string; - statusCode: number; - code: string; - stack?: string; -}; - -export const createCustomError = ( - message: string, - statusCode: number, - code: string, -): CustomError => ({ - message, - statusCode, - code, -}); - -export const customDateTimestampError = (date: string): CustomError => - createCustomError( - `Invalid date: ${date}. Needs to new Date() / new Date().toISOstring() / new Date().getTime() / Unix Epoch`, - StatusCodes.BAD_REQUEST, - "INVALID_DATE_TIME", - ); - -export const badAddressError = (address: string): CustomError => - createCustomError( - `Invalid address: ${address}. Needs to be a valid EVM address`, - StatusCodes.BAD_REQUEST, - "INVALID_ADDRESS", - ); - -export const badChainError = (chain: string | number): CustomError => - createCustomError( - `Invalid chain: ${chain}. If this is a custom chain, add it to chain overrides.`, - StatusCodes.BAD_REQUEST, - "INVALID_CHAIN", - ); - -const flipObject = (data: object) => - Object.fromEntries(Object.entries(data).map(([key, value]) => [value, key])); - -const isZodError = (err: unknown): boolean => { - return Boolean( - err && (err instanceof ZodError || (err as ZodError).name === "ZodError"), - ); -}; - -export function withErrorHandler(server: FastifyInstance) { - server.setErrorHandler( - (error: string | Error | CustomError | ZodError, _request, reply) => { - if (typeof error === "string") { - return reply.status(StatusCodes.INTERNAL_SERVER_ERROR).send({ - error: { - statusCode: 500, - code: "INTERNAL_SERVER_ERROR", - message: error || ReasonPhrases.INTERNAL_SERVER_ERROR, - }, - }); - } - - // Ethers Error Codes - if (parseEthersError(error)) { - return reply.status(StatusCodes.BAD_REQUEST).send({ - error: { - code: "BAD_REQUEST", - message: "code" in error ? error.code : error.message, - reason: error.message, - statusCode: 400, - stack: env.NODE_ENV === "production" ? undefined : error.stack, - }, - }); - } - - // Zod Typings Errors - if (isZodError(error)) { - const _error = error as ZodError; - let parsedMessage: unknown; - - try { - parsedMessage = JSON.parse(_error.message); - } catch (e) { - console.error("Failed to parse error message:", e); - } - const errorObject = - Array.isArray(parsedMessage) && parsedMessage.length > 0 - ? parsedMessage[0] - : {}; - - return reply.status(StatusCodes.BAD_REQUEST).send({ - error: { - code: "BAD_REQUEST", - message: errorObject.message ?? "Invalid Request", - reason: errorObject ?? undefined, - statusCode: 400, - stack: env.NODE_ENV === "production" ? undefined : _error.stack, - }, - }); - } - - if ("statusCode" in error && "code" in error) { - // Transform unexpected errors into a standard payload - const statusCode = - error.statusCode ?? StatusCodes.INTERNAL_SERVER_ERROR; - const code = - error.code ?? - flipObject(StatusCodes)[statusCode] ?? - StatusCodes.INTERNAL_SERVER_ERROR; - - const message = error.message ?? ReasonPhrases.INTERNAL_SERVER_ERROR; - return reply.status(statusCode).send({ - error: { - code, - message, - statusCode, - stack: env.NODE_ENV === "production" ? undefined : error.stack, - }, - }); - } - - reply.status(StatusCodes.INTERNAL_SERVER_ERROR).send({ - error: { - statusCode: 500, - code: "INTERNAL_SERVER_ERROR", - message: error.message || ReasonPhrases.INTERNAL_SERVER_ERROR, - stack: env.NODE_ENV === "production" ? undefined : error.stack, - }, - }); - }, - ); -} diff --git a/src/server/middleware/logs.ts b/src/server/middleware/logs.ts deleted file mode 100644 index b0c494343..000000000 --- a/src/server/middleware/logs.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { stringify } from "thirdweb/utils"; -import { logger } from "../../shared/utils/logger"; -import { ADMIN_QUEUES_BASEPATH } from "./admin-routes"; -import { OPENAPI_ROUTES } from "./open-api"; - -const SKIP_LOG_PATHS = new Set([ - "", - "/", - "/favicon.ico", - "/system/health", - "/static", - ...OPENAPI_ROUTES, - // Skip these routes case of importing sensitive details. - "/backend-wallet/import", - "/configuration/wallets", -]); - -export function withRequestLogs(server: FastifyInstance) { - server.addHook("onSend", async (request, reply, payload) => { - if ( - request.method === "OPTIONS" || - !request.routeOptions.url || - SKIP_LOG_PATHS.has(request.routeOptions.url) || - request.routeOptions.url.startsWith(ADMIN_QUEUES_BASEPATH) - ) { - return payload; - } - - const { method, routeOptions, headers, params, query, body } = request; - const { statusCode, elapsedTime } = reply; - const isError = statusCode >= 400; - - const extractedHeaders = { - "x-backend-wallet-address": headers["x-backend-wallet-address"], - "x-idempotency-key": headers["x-idempotency-key"], - "x-account-address": headers["x-account-address"], - "x-account-factory-address": headers["x-account-factory-address"], - "x-account-salt": headers["x-account-salt"], - }; - - const paramsStr = - params && Object.keys(params).length - ? `params=${stringify(params)}` - : undefined; - const queryStr = - query && Object.keys(query).length - ? `querystring=${stringify(query)}` - : undefined; - const bodyStr = - body && Object.keys(body).length ? `body=${stringify(body)}` : undefined; - const payloadStr = isError ? `payload=${payload}` : undefined; - - logger({ - service: "server", - level: isError ? "error" : "info", - message: [ - `[Request complete - ${statusCode}]`, - `method=${method}`, - `path=${routeOptions.url}`, - `headers=${stringify(extractedHeaders)}`, - paramsStr, - queryStr, - bodyStr, - `duration=${elapsedTime.toFixed(1)}ms`, - payloadStr, - ].join(" "), - }); - - return payload; - }); -} diff --git a/src/server/middleware/open-api.ts b/src/server/middleware/open-api.ts deleted file mode 100644 index 6a995d221..000000000 --- a/src/server/middleware/open-api.ts +++ /dev/null @@ -1,42 +0,0 @@ -import swagger from "@fastify/swagger"; -import type { FastifyInstance } from "fastify"; - -export const OPENAPI_ROUTES = ["/json", "/openapi.json", "/json/"]; - -export async function withOpenApi(server: FastifyInstance) { - await server.register(swagger, { - openapi: { - info: { - title: "thirdweb Engine", - description: - "Engine is an open-source, backend server that reads, writes, and deploys contracts at production scale.", - version: "1.0.0", - license: { - name: "Apache 2.0", - url: "http://www.apache.org/licenses/LICENSE-2.0.html", - }, - }, - components: { - securitySchemes: { - bearerAuth: { - type: "http", - scheme: "bearer", - bearerFormat: "JWT", - description: "To authenticate server-side requests", - }, - }, - }, - security: [ - { - bearerAuth: [], - }, - ], - }, - }); - - for (const path of OPENAPI_ROUTES) { - server.get(path, {}, async (_, res) => { - res.send(server.swagger()); - }); - } -} diff --git a/src/server/middleware/prometheus.ts b/src/server/middleware/prometheus.ts index 29a54b252..c7cbed67d 100644 --- a/src/server/middleware/prometheus.ts +++ b/src/server/middleware/prometheus.ts @@ -1,29 +1,29 @@ -import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; -import { env } from "../../shared/utils/env"; -import { recordMetrics } from "../../shared/utils/prometheus"; +import { createMiddleware } from "hono/factory"; +import { env } from "../../lib/env.js"; +import { recordMetrics } from "../../lib/prometheus.js"; -export function withPrometheus(server: FastifyInstance) { +export const prometheusMiddleware = createMiddleware(async (c, next) => { if (!env.METRICS_ENABLED) { + await next(); return; } - server.addHook( - "onResponse", - async (req: FastifyRequest, res: FastifyReply) => { - const { method } = req; - const url = req.routeOptions.url; - const { statusCode } = res; - const duration = res.elapsedTime; + const startTime = performance.now(); - recordMetrics({ - event: "response_sent", - params: { - endpoint: url ?? "", - statusCode: statusCode.toString(), - duration: duration, - method: method, - }, - }); + await next(); + + const duration = performance.now() - startTime; + const method = c.req.method; + const url = new URL(c.req.url).pathname; + const status = c.res.status; + + recordMetrics({ + event: "response_sent", + params: { + endpoint: url, + statusCode: status.toString(), + duration, + method, }, - ); -} + }); +}); diff --git a/src/server/middleware/rate-limit.ts b/src/server/middleware/rate-limit.ts index 67cda82c7..7eb30223c 100644 --- a/src/server/middleware/rate-limit.ts +++ b/src/server/middleware/rate-limit.ts @@ -1,29 +1,20 @@ -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { env } from "../../shared/utils/env"; -import { redis } from "../../shared/utils/redis/redis"; -import { createCustomError } from "./error"; -import { OPENAPI_ROUTES } from "./open-api"; +import { createMiddleware } from "hono/factory"; +import { HTTPException } from "hono/http-exception"; +import { redis } from "../../lib/redis.js"; +import { env } from "../../lib/env.js"; -const SKIP_RATELIMIT_PATHS = ["/", ...OPENAPI_ROUTES]; +export const rateLimitMiddleware = createMiddleware(async (_c, next) => { + const epochTimeInMinutes = Math.floor(Date.now() / (1000 * 60)); + const key = `rate-limit:global:${epochTimeInMinutes}`; -export function withRateLimit(server: FastifyInstance) { - server.addHook("onRequest", async (request, _reply) => { - if (SKIP_RATELIMIT_PATHS.includes(request.url)) { - return; - } + const count = await redis.incr(key); + redis.expire(key, 2 * 60); - const epochTimeInMinutes = Math.floor(new Date().getTime() / (1000 * 60)); - const key = `rate-limit:global:${epochTimeInMinutes}`; - const count = await redis.incr(key); - redis.expire(key, 2 * 60); + if (count > env.GLOBAL_RATE_LIMIT_PER_MIN) { + throw new HTTPException(429, { + message: `Too many requests. Please reduce your calls to ${env.GLOBAL_RATE_LIMIT_PER_MIN} requests/minute or update the "GLOBAL_RATE_LIMIT_PER_MIN" env var.`, + }); + } - if (count > env.GLOBAL_RATE_LIMIT_PER_MIN) { - throw createCustomError( - `Too many requests. Please reduce your calls to ${env.GLOBAL_RATE_LIMIT_PER_MIN} requests/minute or update the "GLOBAL_RATE_LIMIT_PER_MIN" env var.`, - StatusCodes.TOO_MANY_REQUESTS, - "TOO_MANY_REQUESTS", - ); - } - }); -} + await next(); +}); diff --git a/src/server/middleware/request-logger.ts b/src/server/middleware/request-logger.ts new file mode 100644 index 000000000..2e4253c97 --- /dev/null +++ b/src/server/middleware/request-logger.ts @@ -0,0 +1,76 @@ +import { initializeLogger } from "../../lib/logger.js"; +import { createMiddleware } from "hono/factory"; + +const httpLogger = initializeLogger("http"); + +export const requestLogger = createMiddleware(async (c, next) => { + const startTime = performance.now(); + const method = c.req.method; + const path = c.req.path; + const correlationId = c.get("correlationId"); + + // Initialize request metadata + const requestMetadata: Record = { + correlationId, + method, + path, + query: Object.fromEntries(new URL(c.req.url).searchParams.entries()), + }; + + // Handle request body based on content type + const contentType = c.req.header("content-type"); + if (method !== "GET" && method !== "HEAD") { + try { + if (contentType?.includes("application/json")) { + const bodyClone = await c.req.raw.clone().json(); + requestMetadata.body = bodyClone; + } else { + requestMetadata.body = `[${contentType}]`; + } + } catch (error) { + requestMetadata.bodyParseError = + error instanceof Error ? error.message : "Unknown error"; + } + } + + // Log the incoming request + httpLogger.http(`${method} ${path}`, requestMetadata); + + try { + await next(); + + const responseTime = Math.round(performance.now() - startTime); + const status = c.res.status; + + // For non-200 responses, try to get the response body + // only log response body if non-200 response + let responseBody: unknown; + if (status !== 200) { + try { + responseBody = await c.res.clone().json(); + } catch { + // Response might not be JSON + responseBody = "Unable to parse response body"; + } + } + + // Log the response + httpLogger.http(`${method} ${path} completed`, { + ...requestMetadata, + status, + responseTime, + ...(responseBody ? { response: responseBody } : {}), + }); + } catch (error) { + const responseTime = Math.round(performance.now() - startTime); + + // Log the error with all context + httpLogger.error(`${method} ${path} failed`, { + ...requestMetadata, + responseTime, + error, + }); + + throw error; + } +}); diff --git a/src/server/middleware/security-headers.ts b/src/server/middleware/security-headers.ts deleted file mode 100644 index 5096d4811..000000000 --- a/src/server/middleware/security-headers.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { FastifyInstance } from "fastify"; - -export function withSecurityHeaders(server: FastifyInstance) { - server.addHook("onSend", async (_request, reply, payload) => { - reply.header( - "Strict-Transport-Security", - "max-age=31536000; includeSubDomains; preload", - ); - reply.header("Content-Security-Policy", "default-src 'self';"); - reply.header("X-Frame-Options", "DENY"); - reply.header("X-Content-Type-Options", "nosniff"); - reply.header("Referrer-Policy", "no-referrer"); - reply.header( - "Permissions-Policy", - "geolocation=(), camera=(), microphone=()", - ); - - return payload; - }); -} diff --git a/src/server/middleware/thirdweb-client.ts b/src/server/middleware/thirdweb-client.ts new file mode 100644 index 000000000..7edd17088 --- /dev/null +++ b/src/server/middleware/thirdweb-client.ts @@ -0,0 +1,48 @@ +import type { Factory } from "hono/factory"; +import { getThirdwebClient } from "../../lib/thirdweb-client.js"; +import { onchainRoutesFactory } from "../routes/chain/factory.js"; +import type { Context } from "hono"; + +export const thirdwebClientMiddleware = onchainRoutesFactory.createMiddleware( + async (c, next) => { + const thirdwebSecretKey = c.req.header("x-thirdweb-secret-key"); + const thirdwebClientId = c.req.header("x-thirdweb-client-id"); + const thirdwebServiceKey = c.req.header("x-thirdweb-service-key"); + + if (thirdwebSecretKey) { + const thirdwebClient = getThirdwebClient({ + secretKey: thirdwebSecretKey, + clientId: thirdwebClientId, + }); + c.set("thirdwebClient", thirdwebClient); + } else if (thirdwebClientId && thirdwebServiceKey) { + const thirdwebClient = getThirdwebClient({ + clientId: thirdwebClientId, + serviceKey: thirdwebServiceKey, + }); + c.set("thirdwebClient", thirdwebClient); + } + + c.set("thirdwebServiceKey", thirdwebServiceKey); + c.set("thirdwebClientId", thirdwebClientId); + c.set("thirdwebSecretKey", thirdwebSecretKey); + + await next(); + }, +); + +type ExtractEnvFromFactory = F extends Factory ? E : never; + +export function getThirdwebCredentialsFromContext( + c: Context>, +) { + const thirdwebServiceKey = c.get("thirdwebServiceKey"); + const thirdwebClientId = c.get("thirdwebClientId"); + const thirdwebSecretKey = c.get("thirdwebSecretKey"); + + return { + thirdwebServiceKey, + thirdwebClientId, + thirdwebSecretKey, + }; +} diff --git a/src/server/middleware/websocket.ts b/src/server/middleware/websocket.ts deleted file mode 100644 index b84363dd3..000000000 --- a/src/server/middleware/websocket.ts +++ /dev/null @@ -1,23 +0,0 @@ -import WebSocketPlugin from "@fastify/websocket"; -import type { FastifyInstance } from "fastify"; -import { logger } from "../../shared/utils/logger"; - -export async function withWebSocket(server: FastifyInstance) { - await server.register(WebSocketPlugin, { - errorHandler: ( - error, - conn /* SocketStream */, - _req /* FastifyRequest */, - _reply /* FastifyReply */, - ) => { - logger({ - service: "websocket", - level: "error", - message: `Websocket error: ${error}`, - }); - // Do stuff - // destroy/close connection - conn.destroy(error); - }, - }); -} diff --git a/src/server/routes/accounts/accounts.ts b/src/server/routes/accounts/accounts.ts new file mode 100644 index 000000000..31e6f22f2 --- /dev/null +++ b/src/server/routes/accounts/accounts.ts @@ -0,0 +1,328 @@ +import { and, count, eq, isNull } from "drizzle-orm"; +import { Hono } from "hono"; +import { describeRoute } from "hono-openapi"; +import { resolver, validator as zValidator } from "hono-openapi/zod"; +import { err, ok, ResultAsync, safeTry } from "neverthrow"; +import type { Address } from "thirdweb"; +import { + DEFAULT_ACCOUNT_FACTORY_V0_7, + ENTRYPOINT_ADDRESS_v0_7, +} from "thirdweb/wallets/smart"; +import * as z from "zod"; +import { db } from "../../../db/connection.js"; +import { eoas, smartAccounts } from "../../../db/schema.js"; +import { + accountCreateSchema, + accountResponseSchema, + provisionAccount, +} from "../../../lib/accounts/accounts.js"; +import { getSmartAccount } from "../../../lib/accounts/smart.js"; +import { + engineErrToHttpException, + mapDbError, + zErrorMapper, + type AccountErr, + type DbErr, +} from "../../../lib/errors.js"; +import { evmAddressSchema } from "../../../lib/zod.js"; +import { + requestPaginationSchema, + wrapPaginatedResponseSchema, + wrapResponseSchema, +} from "../../schemas/shared-api-schemas.js"; +import { getDisplayAddress } from "../../../lib/evm.js"; + +export const accountsRoutes = new Hono(); + +accountsRoutes.post( + "/", + zValidator("json", accountCreateSchema, zErrorMapper), + describeRoute({ + summary: "Create Account", + description: + "Create a new engine managed account. Also automatically provisions a default smart account to use with the new account.", + operationId: "createAccount", + tags: ["Accounts"], + responses: { + 201: { + description: "Account created successfully with default smart account", + content: { + "application/json": { + schema: resolver(wrapResponseSchema(accountResponseSchema)), + }, + }, + }, + }, + }), + async (c) => { + const params = c.req.valid("json"); + const resultChain = safeTry(async function* () { + const provisionedResponse = yield* provisionAccount(params); + const provisionedAccount = provisionedResponse.account; + + const [dbEoaEntry] = yield* ResultAsync.fromPromise( + db + .insert(eoas) + .values({ + address: provisionedResponse.account.address as Address, + type: params.type, + encryptedJson: + "encryptedJson" in provisionedResponse + ? provisionedResponse.encryptedJson + : undefined, + platformIdentifiers: + "platformIdentifiers" in provisionedResponse + ? provisionedResponse.platformIdentifiers + : undefined, + label: params.label, + }) + .returning(), + mapDbError, + ); + + if (!dbEoaEntry) { + return err({ + kind: "database", + code: "query_failed", + } as DbErr); + } + + const smartAccount = yield* getSmartAccount({ + adminAccount: provisionedAccount, + accountFactoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7, + entrypointAddress: ENTRYPOINT_ADDRESS_v0_7, + }); + + const [dbSmartAccountEntry] = yield* ResultAsync.fromPromise( + db + .insert(smartAccounts) + .values({ + address: smartAccount.address as Address, + signerAddress: provisionedAccount.address as Address, + label: `Default Smart Account for ${getDisplayAddress( + provisionedAccount.address, + )}`, + factoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7, + entrypointAddress: ENTRYPOINT_ADDRESS_v0_7, + accountSalt: null, + }) + .returning(), + mapDbError, + ); + + if (!dbEoaEntry) { + return err({ + kind: "database", + code: "query_failed", + message: "Unable to insert newly created smart account", + } as DbErr); + } + + return ok({ + ...dbEoaEntry, + encryptedJson: undefined, + smartAccounts: [dbSmartAccountEntry], + }); + }); + + const result = await resultChain; + + if (result.isOk()) { + return c.json({ + result: result.value, + }); + } + throw engineErrToHttpException(result.error); + }, +); + +accountsRoutes.get( + "/", + describeRoute({ + summary: "Get All Accounts", + description: + "Get all your engine managed accounts with their smart accounts", + tags: ["Accounts"], + operationId: "getAllAccounts", + responses: { + 200: { + description: "Accounts", + content: { + "application/json": { + schema: resolver( + wrapPaginatedResponseSchema(accountResponseSchema), + ), + }, + }, + }, + }, + }), + zValidator("query", requestPaginationSchema, zErrorMapper), + async (c) => { + const params = c.req.valid("query"); + const skip = (params.page - 1) * params.limit; + + const combined = await ResultAsync.combine([ + ResultAsync.fromPromise( + db.query.eoas.findMany({ + offset: skip, + limit: params.limit, + where: (eoas, { isNull }) => isNull(eoas.deletedAt), + columns: { + encryptedJson: false, + }, + with: { + smartAccounts: { + where: (smartAccounts, { isNull }) => + isNull(smartAccounts.deletedAt), + }, + }, + }), + mapDbError, + ), + ResultAsync.fromPromise( + db.select({ count: count() }).from(eoas).where(isNull(eoas.deletedAt)), + mapDbError, + ), + ]); + + if (combined.isErr()) { + throw engineErrToHttpException(combined.error); + } + + const [data, countObject] = combined.value; + + const totalCount = countObject[0]?.count; + + if (!totalCount) + throw engineErrToHttpException({ + code: "query_failed", + kind: "database", + status: 500, + message: "Count query returned no response for eoas", + }); + + return c.json({ + result: { + result: data, + pagination: { + totalCount, + page: params.page, + limit: params.limit, + }, + }, + }); + }, +); + +accountsRoutes.delete( + "/:address", + describeRoute({ + summary: "Delete Account", + description: + "Delete an account by address. Deleting an EOA account will also delete any associated smart accounts. Deleting a smart account will only delete the smart account.", + tags: ["Accounts"], + operationId: "deleteAccount", + responses: { + 200: { + description: "Account deleted", + content: { + "application/json": { + schema: resolver( + z.union([ + wrapResponseSchema(z.literal("EOA Account deleted")), + wrapResponseSchema(z.literal("Smart Account deleted")), + ]), + ), + }, + }, + }, + }, + }), + zValidator("param", z.object({ address: evmAddressSchema }), zErrorMapper), + async (c) => { + const { address } = c.req.valid("param"); + + const resultChain = safeTry(async function* () { + // First check if address is an EOA + const eoaResult = yield* ResultAsync.fromPromise( + db.query.eoas.findFirst({ + where: (eoas, { eq, isNull }) => + and(eq(eoas.address, address), isNull(eoas.deletedAt)), + }), + mapDbError, + ); + + if (eoaResult) { + // Delete EOA and all associated smart accounts + // Update EOA + yield* ResultAsync.fromPromise( + db + .update(eoas) + .set({ + deletedAt: new Date(), + }) + .where(eq(eoas.address, address)), + mapDbError, + ); + + // Update all associated smart accounts + yield* ResultAsync.fromPromise( + db + .update(smartAccounts) + .set({ + deletedAt: new Date(), + }) + .where(eq(smartAccounts.signerAddress, address)), + mapDbError, + ); + + return ok("EOA Account deleted"); + } + + // // If not EOA, check if it's a smart account + const smartAccountResult = yield* ResultAsync.fromPromise( + db.query.smartAccounts.findFirst({ + where: (smartAccounts, { eq, isNull }) => + and( + eq(smartAccounts.address, address), + isNull(smartAccounts.deletedAt), + ), + }), + mapDbError, + ); + + if (smartAccountResult) { + // Delete just this smart account + yield* ResultAsync.fromPromise( + db + .update(smartAccounts) + .set({ + deletedAt: new Date(), + }) + .where(eq(smartAccounts.address, address)), + mapDbError, + ); + + return ok("Smart Account deleted"); + } + + return err({ + kind: "account", + code: "account_not_found", + message: "Account not found", + status: 400, + } as AccountErr); + }); + + const result = await resultChain; + + if (result.isOk()) { + return c.json({ + result: result.value, + }); + } + + throw engineErrToHttpException(result.error); + }, +); diff --git a/src/server/routes/admin/nonces.ts b/src/server/routes/admin/nonces.ts deleted file mode 100644 index d09e6493a..000000000 --- a/src/server/routes/admin/nonces.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - type Address, - eth_getTransactionCount, - getAddress, - getRpcClient, -} from "thirdweb"; -import { - getUsedBackendWallets, - lastUsedNonceKey, - recycledNoncesKey, - sentNoncesKey, -} from "../../../shared/db/wallets/wallet-nonce"; -import { getChain } from "../../../shared/utils/chain"; -import { redis } from "../../../shared/utils/redis/redis"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { walletWithAddressParamSchema } from "../../schemas/wallet"; - -export const responseBodySchema = Type.Object({ - result: Type.Array( - Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Backend wallet address", - }, - chainId: Type.Integer({ - description: "Chain ID", - examples: [80002], - }), - onchainNonce: Type.Integer({ - description: "Last mined nonce", - examples: [0], - }), - lastUsedNonce: Type.Integer({ - description: "Last incremented nonce sent to the RPC", - examples: [0], - }), - sentNonces: Type.Array(Type.Integer(), { - description: - "Nonces that were successfully sent to the RPC but not mined yet (in descending order)", - examples: [[2, 1, 0]], - }), - recycledNonces: Type.Array(Type.Integer(), { - examples: [[3, 2, 1]], - description: - "Nonces that were acquired but failed to be sent to the blockchain, waiting to be recycled or cancelled (in descending order)", - }), - }), - ), -}); - -responseBodySchema.example = { - result: [ - { - walletAddress: "0xcedf3b4d8f7f1f7e0f7f0f7f0f7f0f7f0f7f0f7f", - onchainNonce: 2, - lastUsedNonce: 8, - recycledNonces: [6, 7], - chainId: 80002, - }, - ], -}; - -const walletWithAddressQuerySchema = Type.Partial(walletWithAddressParamSchema); - -export async function getNonceDetailsRoute(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/admin/nonces", - schema: { - summary: "Get nonce status details for wallets", - description: - "Admin route to get nonce status details for all wallets filtered by address and chain ", - tags: ["Admin"], - operationId: "nonceDetails", - querystring: walletWithAddressQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { walletAddress, chain } = request.query; - const result = await getNonceDetails({ - walletAddress: walletAddress ? getAddress(walletAddress) : undefined, - chainId: chain ? Number.parseInt(chain) : undefined, - }); - - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} - -export const getNonceDetails = async ({ - walletAddress, - chainId, -}: { - walletAddress?: Address; - chainId?: number; -} = {}) => { - const usedBackendWallets = await getUsedBackendWallets( - chainId, - walletAddress, - ); - - const pipeline = redis.pipeline(); - const onchainNoncePromises: Promise[] = []; - - const keyMap = usedBackendWallets.map(({ chainId, walletAddress }) => { - pipeline.get(lastUsedNonceKey(chainId, walletAddress)); - pipeline.smembers(sentNoncesKey(chainId, walletAddress)); - pipeline.smembers(recycledNoncesKey(chainId, walletAddress)); - - onchainNoncePromises.push(getLastUsedOnchainNonce(chainId, walletAddress)); - - return { chainId, walletAddress }; - }); - - const [pipelineResults, onchainNonces] = await Promise.all([ - pipeline.exec(), - Promise.all(onchainNoncePromises), - ]); - - if (!pipelineResults) { - throw new Error("Failed to execute Redis pipeline"); - } - - return keyMap.map((key, index) => { - const pipelineOffset = index * 3; - const [lastUsedNonceResult, sentNoncesResult, recycledNoncesResult] = - pipelineResults.slice(pipelineOffset, pipelineOffset + 3); - - return { - walletAddress: key.walletAddress, - chainId: key.chainId, - onchainNonce: onchainNonces[index], - lastUsedNonce: Number.parseInt(lastUsedNonceResult[1] as string) ?? 0, - sentNonces: (sentNoncesResult[1] as string[]) - .map((nonce) => Number.parseInt(nonce)) - .sort((a, b) => b - a), - recycledNonces: (recycledNoncesResult[1] as string[]) - .map((nonce) => Number.parseInt(nonce)) - .sort((a, b) => b - a), - }; - }); -}; - -/* - * Get the last used nonce onchain - * @param chainId Chain ID - * @param walletAddress Wallet address - * @returns Next unused nonce - */ -export const getLastUsedOnchainNonce = async ( - chainId: number, - walletAddress: string, -) => { - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - - // The next unused nonce = transactionCount. - const transactionCount = await eth_getTransactionCount(rpcRequest, { - address: walletAddress, - blockTag: "latest", - }); - - const onchainNonce = transactionCount - 1; - return onchainNonce; -}; diff --git a/src/server/routes/admin/transaction.ts b/src/server/routes/admin/transaction.ts deleted file mode 100644 index ea317ebd6..000000000 --- a/src/server/routes/admin/transaction.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { Queue } from "bullmq"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { stringify } from "thirdweb/utils"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { getConfig } from "../../../shared/utils/cache/get-config"; -import { maybeDate } from "../../../shared/utils/primitive-types"; -import { redis } from "../../../shared/utils/redis/redis"; -import { MineTransactionQueue } from "../../../worker/queues/mine-transaction-queue"; -import { SendTransactionQueue } from "../../../worker/queues/send-transaction-queue"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestSchema = Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), -}); - -const jobSchema = Type.Object({ - queue: Type.String(), - jobId: Type.String(), - timestamp: Type.String(), - processedOn: Type.Optional(Type.String()), - finishedOn: Type.Optional(Type.String()), - lines: Type.Array(Type.String()), -}); - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - raw: Type.Any(), - jobs: Type.Array(jobSchema), - }), -}); - -responseBodySchema.example = { - result: { - raw: { - queueId: "9eb88b00-f04f-409b-9df7-7dcc9003bc35", - }, - jobs: [ - { - queue: "transactions-1-send", - jobId: "430235bb-4430-47d2-9373-845454f2375e:0", - timestamp: "2024-07-30T22:02:14.057Z", - processedOn: "2024-07-30T22:02:14.062Z", - finishedOn: "2024-07-30T22:02:14.832Z", - lines: ["..."], - }, - { - queue: "transactions-2-mine", - jobId: "430235bb-4430-47d2-9373-845454f2375e", - timestamp: "2024-07-30T22:02:14.828Z", - processedOn: "2024-07-30T22:02:17.748Z", - finishedOn: "2024-07-30T22:02:17.977Z", - lines: ["..."], - }, - ], - }, -}; - -export async function getTransactionDetails(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/admin/transaction-details/:queueId", - schema: { - summary: "Get transaction details", - description: "Get raw logs and details for a transaction by queueId.", - tags: ["Admin"], - operationId: "transactionDetails", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { queueId } = request.params; - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - throw createCustomError( - "Transaction not found.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_FOUND", - ); - } - - const config = await getConfig(); - const jobs: Static[] = []; - - // SentTransaction jobs. - for ( - let resendCount = 0; - resendCount < config.maxRetriesPerTx; - resendCount++ - ) { - const jobDetails = await getJobDetails({ - queue: SendTransactionQueue.q, - jobId: SendTransactionQueue.jobId({ queueId, resendCount }), - }); - if (jobDetails) { - jobs.push(jobDetails); - } - } - - // MineTransaction job. - const jobDetails = await getJobDetails({ - queue: MineTransactionQueue.q, - jobId: MineTransactionQueue.jobId({ queueId }), - }); - if (jobDetails) { - jobs.push(jobDetails); - } - - reply.status(StatusCodes.OK).send({ - result: { - raw: JSON.parse(stringify(transaction)), - jobs, - }, - }); - }, - }); -} - -const getJobDetails = async (args: { - queue: Queue; - jobId: string; -}): Promise | null> => { - const { queue, jobId } = args; - const job = await queue.getJob(jobId); - if (!job) { - return null; - } - - const key = `bull:${queue.name}:${jobId}:logs`; - const lines = await redis.lrange(key, 0, -1); - return { - queue: queue.name, - jobId, - timestamp: maybeDate(job.timestamp).toISOString(), - processedOn: maybeDate(job.processedOn)?.toISOString(), - finishedOn: maybeDate(job.finishedOn)?.toISOString(), - lines, - }; -}; diff --git a/src/server/routes/auth/access-tokens.ts b/src/server/routes/auth/access-tokens.ts new file mode 100644 index 000000000..6f5528e80 --- /dev/null +++ b/src/server/routes/auth/access-tokens.ts @@ -0,0 +1,108 @@ +import { describeRoute } from "hono-openapi"; +import { resolver, validator } from "hono-openapi/zod"; +import { ResultAsync } from "neverthrow"; +import { encodeJWT } from "thirdweb/utils"; +import * as z from "zod"; +import { db } from "../../../db/connection.js"; +import { accessTokenDbEntrySchema } from "../../../db/derived-schemas.js"; +import { tokens } from "../../../db/schema.js"; +import { adminAccount } from "../../../lib/admin-account.js"; +import { config } from "../../../lib/config.js"; +import { + engineErrToHttpException, + mapDbError, + zErrorMapper, +} from "../../../lib/errors.js"; +import { wrapResponseSchema } from "../../schemas/shared-api-schemas.js"; +import { authRoutesFactory } from "./factory.js"; + +export const createAccessTokenRoute = authRoutesFactory.createHandlers( + validator( + "json", + z.object({ + label: z.string(), + }), + zErrorMapper, + ), + describeRoute({ + tags: ["Auth"], + operationId: "createAccessToken", + summary: "Create Access Token", + description: "Create an access token for a client", + responses: { + 200: { + description: "Access token created successfully", + content: { + "application/json": { + schema: resolver( + wrapResponseSchema( + accessTokenDbEntrySchema.extend({ + accessToken: z.string().openapi({ + description: "The access token created", + }), + }), + ), + ), + }, + }, + }, + }, + }), + async (c) => { + const { label } = c.req.valid("json"); + + const user = c.get("user"); + + const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 100); + + const id = crypto.randomUUID(); + const jwt = await encodeJWT({ + account: adminAccount, + payload: { + iss: adminAccount.address, + sub: user?.address ?? adminAccount.address, + aud: config.authDomain, + nbf: new Date(), + // Set to expire in 100 years + exp: expiresAt, + iat: new Date(), + ctx: { + permissions: user?.permissions ?? ["ADMIN"], + }, + jti: id, + }, + }); + + const dbResult = await ResultAsync.fromPromise( + db + .insert(tokens) + .values({ + id, + accountAddress: user?.address ?? adminAccount.address, + isAccessToken: true, + label: label, + expiresAt, + tokenMask: `${jwt.slice(0, 10)}...${jwt.slice(-10)}`, + }) + .returning(), + mapDbError, + ); + + if (dbResult.isErr()) { + throw engineErrToHttpException(dbResult.error); + } + + const createdToken = dbResult.value[0]; + + if (!createdToken) { + throw engineErrToHttpException({ + kind: "database", + code: "query_failed", + status: 500, + message: "Failed to create access token", + }); + } + + return c.json({ result: { accessToken: jwt, ...createdToken } }); + }, +); diff --git a/src/server/routes/auth/access-tokens/create.ts b/src/server/routes/auth/access-tokens/create.ts deleted file mode 100644 index 53502150d..000000000 --- a/src/server/routes/auth/access-tokens/create.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { buildJWT } from "@thirdweb-dev/auth"; -import { LocalWallet } from "@thirdweb-dev/wallets"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { createToken } from "../../../../shared/db/tokens/create-token"; -import { accessTokenCache } from "../../../../shared/utils/cache/access-token"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { env } from "../../../../shared/utils/env"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { AccessTokenSchema } from "./get-all"; - -const requestBodySchema = Type.Object({ - label: Type.Optional(Type.String()), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - ...AccessTokenSchema.properties, - accessToken: Type.String(), - }), -}); - -export async function createAccessToken(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/access-tokens/create", - schema: { - summary: "Create a new access token", - description: "Create a new access token", - tags: ["Access Tokens"], - operationId: "createAccessToken", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { label } = req.body; - - const config = await getConfig(); - const wallet = new LocalWallet(); - - // TODO: Remove this with next breaking change - try { - // First try to load the wallet using the encryption password - await wallet.import({ - encryptedJson: config.authWalletEncryptedJson, - password: env.ENCRYPTION_PASSWORD, - }); - } catch { - // If that fails, try the thirdweb api secret key for backwards compatibility - await wallet.import({ - encryptedJson: config.authWalletEncryptedJson, - password: env.THIRDWEB_API_SECRET_KEY, - }); - - // If that works, save the wallet using the encryption password for the future - const authWalletEncryptedJson = await wallet.export({ - strategy: "encryptedJson", - password: env.ENCRYPTION_PASSWORD, - }); - - await updateConfiguration({ - authWalletEncryptedJson, - }); - } - - const jwt = await buildJWT({ - wallet, - payload: { - iss: await wallet.getAddress(), - sub: req.user.address, - aud: config.authDomain, - nbf: new Date(), - // Set to expire in 100 years - exp: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 100), - iat: new Date(), - ctx: req.user.session, - }, - }); - - const token = await createToken({ jwt, isAccessToken: true, label }); - - accessTokenCache.clear(); - - res.status(StatusCodes.OK).send({ - result: { - ...token, - createdAt: token.createdAt.toISOString(), - expiresAt: token.expiresAt.toISOString(), - accessToken: jwt, - }, - }); - }, - }); -} diff --git a/src/server/routes/auth/access-tokens/get-all.ts b/src/server/routes/auth/access-tokens/get-all.ts deleted file mode 100644 index f71adc643..000000000 --- a/src/server/routes/auth/access-tokens/get-all.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAccessTokens } from "../../../../shared/db/tokens/get-access-tokens"; -import { AddressSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const AccessTokenSchema = Type.Object({ - id: Type.String(), - tokenMask: Type.String(), - walletAddress: AddressSchema, - createdAt: Type.String(), - expiresAt: Type.String(), - label: Type.Union([Type.String(), Type.Null()]), -}); - -const responseBodySchema = Type.Object({ - result: Type.Array(AccessTokenSchema), -}); - -export async function getAllAccessTokens(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/auth/access-tokens/get-all", - schema: { - summary: "Get all access tokens", - description: "Get all access tokens", - tags: ["Access Tokens"], - operationId: "listAccessTokens", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const accessTokens = await getAccessTokens(); - res.status(StatusCodes.OK).send({ - result: accessTokens.map((token) => ({ - ...token, - createdAt: token.createdAt.toISOString(), - expiresAt: token.expiresAt.toISOString(), - })), - }); - }, - }); -} diff --git a/src/server/routes/auth/access-tokens/revoke.ts b/src/server/routes/auth/access-tokens/revoke.ts deleted file mode 100644 index 5f1bc10da..000000000 --- a/src/server/routes/auth/access-tokens/revoke.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { revokeToken } from "../../../../shared/db/tokens/revoke-token"; -import { accessTokenCache } from "../../../../shared/utils/cache/access-token"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - id: Type.String(), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function revokeAccessToken(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/access-tokens/revoke", - schema: { - summary: "Revoke an access token", - description: "Revoke an access token", - tags: ["Access Tokens"], - operationId: "revokeAccessTokens", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - await revokeToken({ id: req.body.id }); - - accessTokenCache.clear(); - - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/auth/access-tokens/update.ts b/src/server/routes/auth/access-tokens/update.ts deleted file mode 100644 index 9f9fe0cbf..000000000 --- a/src/server/routes/auth/access-tokens/update.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateToken } from "../../../../shared/db/tokens/update-token"; -import { accessTokenCache } from "../../../../shared/utils/cache/access-token"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - id: Type.String(), - label: Type.Optional(Type.String()), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function updateAccessToken(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/access-tokens/update", - schema: { - summary: "Update an access token", - description: "Update an access token", - tags: ["Access Tokens"], - operationId: "updateAccessTokens", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { id, label } = req.body; - await updateToken({ id, label }); - - accessTokenCache.clear(); - - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/auth/factory.ts b/src/server/routes/auth/factory.ts new file mode 100644 index 000000000..42b8c6d01 --- /dev/null +++ b/src/server/routes/auth/factory.ts @@ -0,0 +1,4 @@ +import { createFactory } from "hono/factory"; +import type { AuthContext } from "../../middleware/auth/types.js"; + +export const authRoutesFactory = createFactory(); diff --git a/src/server/routes/auth/index.ts b/src/server/routes/auth/index.ts new file mode 100644 index 000000000..0323fdc93 --- /dev/null +++ b/src/server/routes/auth/index.ts @@ -0,0 +1,8 @@ +import { Hono } from "hono"; +import { createAccessTokenRoute } from "./access-tokens.js"; + +const authRoutes = new Hono(); + +authRoutes.post("/access-tokens", ...createAccessTokenRoute); + +export default authRoutes; diff --git a/src/server/routes/auth/keypair/add.ts b/src/server/routes/auth/keypair/add.ts deleted file mode 100644 index b2af520b4..000000000 --- a/src/server/routes/auth/keypair/add.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { type Keypairs, Prisma } from "@prisma/client"; -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { insertKeypair } from "../../../../shared/db/keypair/insert"; -import { isWellFormedPublicKey } from "../../../../shared/utils/crypto"; -import { createCustomError } from "../../../middleware/error"; -import { - KeypairAlgorithmSchema, - KeypairSchema, - toKeypairSchema, -} from "../../../../shared/schemas/keypair"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - publicKey: Type.String({ - description: - "The public key of your keypair beginning with '-----BEGIN PUBLIC KEY-----'.", - }), - algorithm: KeypairAlgorithmSchema, - label: Type.Optional(Type.String()), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - keypair: KeypairSchema, - }), -}); - -export async function addKeypair(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/keypair/add", - schema: { - summary: "Add public key", - description: "Add the public key for a keypair", - tags: ["Keypair"], - operationId: "add", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { publicKey: publicKeyRaw, algorithm, label } = req.body; - const publicKey = publicKeyRaw.trim(); - - if (!isWellFormedPublicKey(publicKey)) { - throw createCustomError( - "Invalid public key. Make sure it starts with '-----BEGIN PUBLIC KEY-----'.", - StatusCodes.BAD_REQUEST, - "INVALID_PUBLIC_KEY", - ); - } - - let keypair: Keypairs; - try { - keypair = await insertKeypair({ - publicKey, - algorithm, - label, - }); - } catch (e) { - if (e instanceof Prisma.PrismaClientKnownRequestError) { - if (e.code === "P2002") { - throw createCustomError( - "Public key already imported.", - StatusCodes.BAD_REQUEST, - "PUBLIC_KEY_EXISTS", - ); - } - } - throw e; - } - - res.status(StatusCodes.OK).send({ - result: { - keypair: toKeypairSchema(keypair), - }, - }); - }, - }); -} diff --git a/src/server/routes/auth/keypair/list.ts b/src/server/routes/auth/keypair/list.ts deleted file mode 100644 index ca6bb6698..000000000 --- a/src/server/routes/auth/keypair/list.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { listKeypairs } from "../../../../shared/db/keypair/list"; -import { - KeypairSchema, - toKeypairSchema, -} from "../../../../shared/schemas/keypair"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const responseBodySchema = Type.Object({ - result: Type.Array(KeypairSchema), -}); - -export async function listPublicKeys(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/auth/keypair/get-all", - schema: { - summary: "List public keys", - description: "List the public keys configured with Engine", - tags: ["Keypair"], - operationId: "list", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const keypairs = await listKeypairs(); - - res.status(StatusCodes.OK).send({ - result: keypairs.map(toKeypairSchema), - }); - }, - }); -} diff --git a/src/server/routes/auth/keypair/remove.ts b/src/server/routes/auth/keypair/remove.ts deleted file mode 100644 index e7d4f7b54..000000000 --- a/src/server/routes/auth/keypair/remove.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { deleteKeypair } from "../../../../shared/db/keypair/delete"; -import { keypairCache } from "../../../../shared/utils/cache/keypair"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - hash: Type.String(), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function removePublicKey(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/keypair/remove", - schema: { - summary: "Remove public key", - description: "Remove the public key for a keypair", - tags: ["Keypair"], - operationId: "remove", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { hash } = req.body; - - await deleteKeypair({ hash }); - keypairCache.clear(); - - res.status(StatusCodes.OK).send({ - result: { success: true }, - }); - }, - }); -} diff --git a/src/server/routes/auth/permissions/get-all.ts b/src/server/routes/auth/permissions/get-all.ts deleted file mode 100644 index 2d8cab721..000000000 --- a/src/server/routes/auth/permissions/get-all.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { prisma } from "../../../../shared/db/client"; -import { AddressSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const responseBodySchema = Type.Object({ - result: Type.Array( - Type.Object({ - walletAddress: AddressSchema, - permissions: Type.String(), - label: Type.Union([Type.String(), Type.Null()]), - }), - ), -}); - -export async function getAllPermissions(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/auth/permissions/get-all", - schema: { - summary: "Get all permissions", - description: "Get all users with their corresponding permissions", - tags: ["Permissions"], - operationId: "listAdmins", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const permissions = await prisma.permissions.findMany(); - res.status(StatusCodes.OK).send({ - result: permissions, - }); - }, - }); -} diff --git a/src/server/routes/auth/permissions/grant.ts b/src/server/routes/auth/permissions/grant.ts deleted file mode 100644 index d524a6b65..000000000 --- a/src/server/routes/auth/permissions/grant.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updatePermissions } from "../../../../shared/db/permissions/update-permissions"; -import { AddressSchema } from "../../../schemas/address"; -import { permissionsSchema } from "../../../../shared/schemas/auth"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - walletAddress: AddressSchema, - permissions: permissionsSchema, - label: Type.Optional(Type.String()), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function grantPermissions(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/permissions/grant", - schema: { - summary: "Grant permissions to user", - description: "Grant permissions to a user", - tags: ["Permissions"], - operationId: "grantAdmin", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { walletAddress, permissions, label } = req.body; - await updatePermissions({ - walletAddress, - permissions, - label, - }); - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/auth/permissions/revoke.ts b/src/server/routes/auth/permissions/revoke.ts deleted file mode 100644 index acea77853..000000000 --- a/src/server/routes/auth/permissions/revoke.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { deletePermissions } from "../../../../shared/db/permissions/delete-permissions"; -import { AddressSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - walletAddress: AddressSchema, -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function revokePermissions(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/auth/permissions/revoke", - schema: { - summary: "Revoke permissions from user", - description: "Revoke a user's permissions", - tags: ["Permissions"], - operationId: "revokeAdmin", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { walletAddress } = req.body; - await deletePermissions({ - walletAddress, - }); - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/cancel-nonces.ts b/src/server/routes/backend-wallet/cancel-nonces.ts deleted file mode 100644 index 1627aeced..000000000 --- a/src/server/routes/backend-wallet/cancel-nonces.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { eth_getTransactionCount, getRpcClient } from "thirdweb"; -import { checksumAddress } from "thirdweb/utils"; -import { getChain } from "../../../shared/utils/chain"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { sendCancellationTransaction } from "../../../shared/utils/transaction/cancel-transaction"; -import { - requestQuerystringSchema, - standardResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { - walletChainParamSchema, - walletHeaderSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -const requestSchema = walletChainParamSchema; - -const requestBodySchema = Type.Object({ - toNonce: Type.Number({ - description: - "The nonce to cancel up to, inclusive. Example: If the onchain nonce is 10 and 'toNonce' is 15, this request will cancel nonces: 11, 12, 13, 14, 15", - examples: ["42"], - }), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object( - { - cancelledNonces: Type.Array(Type.Number()), - }, - { - examples: [ - { - result: { - cancelledNonces: [11, 12, 13, 14, 15], - }, - }, - ], - }, - ), -}); - -export async function cancelBackendWalletNoncesRoute(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/cancel-nonces", - schema: { - summary: "Cancel nonces", - description: - "Cancel all nonces up to the provided nonce. This is useful to unblock a backend wallet that has transactions waiting for nonces to be mined.", - tags: ["Backend Wallet"], - operationId: "cancelNonces", - params: requestSchema, - body: requestBodySchema, - headers: walletHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { toNonce } = request.body; - const { "x-backend-wallet-address": walletAddress } = - request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const from = checksumAddress(walletAddress); - - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - - // Cancel starting from the next unused onchain nonce. - const transactionCount = await eth_getTransactionCount(rpcRequest, { - address: walletAddress, - blockTag: "latest", - }); - - const cancelledNonces: number[] = []; - for (let nonce = transactionCount; nonce <= toNonce; nonce++) { - await sendCancellationTransaction({ - chainId, - from, - nonce, - }); - cancelledNonces.push(nonce); - } - - reply.status(StatusCodes.OK).send({ - result: { - cancelledNonces, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/create.ts b/src/server/routes/backend-wallet/create.ts deleted file mode 100644 index 107fde4a6..000000000 --- a/src/server/routes/backend-wallet/create.ts +++ /dev/null @@ -1,260 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAddress } from "thirdweb"; -import { - DEFAULT_ACCOUNT_FACTORY_V0_7, - ENTRYPOINT_ADDRESS_v0_7, -} from "thirdweb/wallets/smart"; -import { - LegacyWalletType, - WalletType, - CircleWalletType, -} from "../../../shared/schemas/wallet"; -import { getConfig } from "../../../shared/utils/cache/get-config"; -import { createCustomError } from "../../middleware/error"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { - CreateAwsKmsWalletError, - createAwsKmsWalletDetails, -} from "../../utils/wallets/create-aws-kms-wallet"; -import { - CreateGcpKmsWalletError, - createGcpKmsWalletDetails, -} from "../../utils/wallets/create-gcp-kms-wallet"; -import { createLocalWalletDetails } from "../../utils/wallets/create-local-wallet"; -import { - createSmartAwsWalletDetails, - createSmartGcpWalletDetails, - createSmartLocalWalletDetails, -} from "../../utils/wallets/create-smart-wallet"; -import { - CircleWalletError, - createCircleWalletDetails, -} from "../../utils/wallets/circle"; -import assert from "node:assert"; - -const requestBodySchema = Type.Union([ - // Base schema for non-circle wallet types - Type.Object({ - label: Type.Optional(Type.String()), - type: Type.Optional(Type.Union([Type.Enum(LegacyWalletType)])), - }), - - // Schema for circle and smart:circle wallet types - Type.Object({ - label: Type.Optional(Type.String()), - type: Type.Union([Type.Enum(CircleWalletType)]), - isTestnet: Type.Optional( - Type.Boolean({ - description: - "If your engine is configured with a testnet API Key for Circle, you can only create testnet wallets and send testnet transactions. Enable this field for testnet wallets. NOTE: A production API Key cannot be used for testnet transactions, and a testnet API Key cannot be used for production transactions. See: https://developers.circle.com/w3s/sandbox-vs-production", - }), - ), - credentialId: Type.String(), - walletSetId: Type.Optional(Type.String()), - }), -]); - -const responseSchema = Type.Object({ - result: Type.Object({ - walletAddress: AddressSchema, - status: Type.String(), - type: Type.Enum(WalletType), - }), -}); - -responseSchema.example = { - result: { - walletAddress: "0x....", - status: "success", - type: WalletType.local, - }, -}; - -export const createBackendWallet = async (fastify: FastifyInstance) => { - fastify.withTypeProvider().route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/create", - schema: { - summary: "Create backend wallet", - description: "Create a backend wallet.", - tags: ["Backend Wallet"], - operationId: "create", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - const { label } = req.body; - - let walletAddress: string; - const config = await getConfig(); - - const walletType = - req.body.type ?? - config.walletConfiguration.legacyWalletType_removeInNextBreakingChange; - - switch (walletType) { - case WalletType.local: - walletAddress = await createLocalWalletDetails({ label }); - break; - case WalletType.awsKms: - try { - walletAddress = await createAwsKmsWalletDetails({ label }); - } catch (e) { - if (e instanceof CreateAwsKmsWalletError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "CREATE_AWS_KMS_WALLET_ERROR", - ); - } - throw e; - } - break; - case WalletType.gcpKms: - try { - walletAddress = await createGcpKmsWalletDetails({ label }); - } catch (e) { - if (e instanceof CreateGcpKmsWalletError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "CREATE_GCP_KMS_WALLET_ERROR", - ); - } - throw e; - } - break; - case CircleWalletType.circle: - { - // we need this if here for typescript to statically type the credentialId and walletSetId - assert(req.body.type === "circle", "Expected circle wallet type"); - const { credentialId, walletSetId, isTestnet } = req.body; - - try { - const wallet = await createCircleWalletDetails({ - label, - isSmart: false, - credentialId, - walletSetId, - isTestnet: isTestnet, - }); - - walletAddress = getAddress(wallet.address); - } catch (e) { - if (e instanceof CircleWalletError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "CREATE_CIRCLE_WALLET_ERROR", - ); - } - throw e; - } - } - break; - - case CircleWalletType.smartCircle: - { - // we need this if here for typescript to statically type the credentialId and walletSetId - assert(req.body.type === "smart:circle", "Expected circle wallet type"); - const { credentialId, walletSetId, isTestnet } = req.body; - - try { - const wallet = await createCircleWalletDetails({ - label, - isSmart: true, - credentialId, - walletSetId, - isTestnet: isTestnet, - }); - - walletAddress = getAddress(wallet.address); - } catch (e) { - if (e instanceof CircleWalletError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "CREATE_CIRCLE_WALLET_ERROR", - ); - } - throw e; - } - } - break; - - case WalletType.smartAwsKms: - try { - const smartAwsWallet = await createSmartAwsWalletDetails({ - label, - accountFactoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7, - entrypointAddress: ENTRYPOINT_ADDRESS_v0_7, - }); - - walletAddress = getAddress(smartAwsWallet.address); - } catch (e) { - if (e instanceof CreateAwsKmsWalletError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "CREATE_AWS_KMS_WALLET_ERROR", - ); - } - throw e; - } - break; - case WalletType.smartGcpKms: - try { - const smartGcpWallet = await createSmartGcpWalletDetails({ - label, - accountFactoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7, - entrypointAddress: ENTRYPOINT_ADDRESS_v0_7, - }); - walletAddress = getAddress(smartGcpWallet.address); - } catch (e) { - if (e instanceof CreateGcpKmsWalletError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "CREATE_GCP_KMS_WALLET_ERROR", - ); - } - throw e; - } - break; - case WalletType.smartLocal: - { - const smartLocalWallet = await createSmartLocalWalletDetails({ - label, - accountFactoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7, - entrypointAddress: ENTRYPOINT_ADDRESS_v0_7, - }); - walletAddress = getAddress(smartLocalWallet.address); - } - break; - default: - throw createCustomError( - "Unkown wallet type", - StatusCodes.BAD_REQUEST, - "CREATE_WALLET_ERROR", - ); - } - - reply.status(StatusCodes.OK).send({ - result: { - walletAddress, - type: walletType as WalletType, - status: "success", - }, - }); - }, - }); -}; diff --git a/src/server/routes/backend-wallet/get-all.ts b/src/server/routes/backend-wallet/get-all.ts deleted file mode 100644 index 1ae8e26b4..000000000 --- a/src/server/routes/backend-wallet/get-all.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAllWallets } from "../../../shared/db/wallets/get-all-wallets"; -import { - standardResponseSchema, - walletDetailsSchema, -} from "../../schemas/shared-api-schemas"; - -const QuerySchema = Type.Object({ - page: Type.Integer({ - description: "The page of wallets to get.", - examples: ["1"], - default: "1", - minimum: 1, - }), - limit: Type.Integer({ - description: "The number of wallets to get per page.", - examples: ["10"], - default: "10", - minimum: 1, - }), -}); - -const responseSchema = Type.Object({ - result: Type.Array(walletDetailsSchema), -}); - -responseSchema.example = { - result: [ - { - address: "0xe201a491a204e4a78e60033ae8ed39036b55bacb", - type: "local", - label: "my-wallet", - awsKmsKeyId: null, - awsKmsArn: null, - gcpKmsKeyId: null, - gcpKmsKeyRingId: null, - gcpKmsLocationId: null, - gcpKmsKeyVersionId: null, - gcpKmsResourcePath: null, - }, - ], -}; -export async function getAll(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/backend-wallet/get-all", - schema: { - summary: "Get all backend wallets", - description: "Get all backend wallets.", - tags: ["Backend Wallet"], - operationId: "getAll", - querystring: QuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, res) => { - const wallets = await getAllWallets({ - page: req.query.page, - limit: req.query.limit, - }); - - res.status(StatusCodes.OK).send({ - result: wallets, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/get-balance.ts b/src/server/routes/backend-wallet/get-balance.ts deleted file mode 100644 index 0bd588668..000000000 --- a/src/server/routes/backend-wallet/get-balance.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { AddressSchema } from "../../schemas/address"; -import { - currencyValueSchema, - standardResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { walletWithAddressParamSchema } from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -import { getChain } from "../../../shared/utils/chain"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { getWalletBalance } from "thirdweb/wallets"; - -const responseSchema = Type.Object({ - result: Type.Object({ - walletAddress: AddressSchema, - ...currencyValueSchema.properties, - }), -}); - -responseSchema.example = { - result: { - walletAddress: "0x...", - name: "ERC20", - symbol: "", - decimals: "18", - value: "0", - displayValue: "0.0", - }, -}; - -export async function getBalance(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/backend-wallet/:chain/:walletAddress/get-balance", - schema: { - summary: "Get balance", - description: "Get the native balance for a backend wallet.", - tags: ["Backend Wallet"], - operationId: "getBalance", - params: walletWithAddressParamSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, walletAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - - const balanceData = await getWalletBalance({ - client: thirdwebClient, - address: walletAddress, - chain: await getChain(chainId), - }); - - reply.status(StatusCodes.OK).send({ - result: { - walletAddress, - ...balanceData, - value: balanceData.value.toString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/get-nonce.ts b/src/server/routes/backend-wallet/get-nonce.ts deleted file mode 100644 index f6ef216b3..000000000 --- a/src/server/routes/backend-wallet/get-nonce.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { inspectNonce } from "../../../shared/db/wallets/wallet-nonce"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { walletWithAddressParamSchema } from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -const requestSchema = walletWithAddressParamSchema; - -const responseSchema = Type.Object({ - result: Type.Object({ - nonce: Type.Integer(), - }), -}); - -responseSchema.example = { - result: { - nonce: 100, - }, -}; - -export const getBackendWalletNonce = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/backend-wallet/:chain/:walletAddress/get-nonce", - schema: { - summary: "Get nonce", - description: - "Get the last used nonce for this backend wallet. This value managed by Engine may differ from the onchain value. Use `/backend-wallet/reset-nonces` if this value looks incorrect while idle.", - tags: ["Backend Wallet"], - operationId: "getNonce", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - const { chain, walletAddress } = req.params; - const chainId = await getChainIdFromChain(chain); - const nonce = await inspectNonce(chainId, walletAddress as Address); - - reply.status(StatusCodes.OK).send({ - result: { - nonce, - }, - }); - }, - }); -}; diff --git a/src/server/routes/backend-wallet/get-transactions-by-nonce.ts b/src/server/routes/backend-wallet/get-transactions-by-nonce.ts deleted file mode 100644 index 2dd31196b..000000000 --- a/src/server/routes/backend-wallet/get-transactions-by-nonce.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { getNonceMap } from "../../../shared/db/wallets/nonce-map"; -import { normalizeAddress } from "../../../shared/utils/primitive-types"; -import type { AnyTransaction } from "../../../shared/utils/transaction/types"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { - TransactionSchema, - toTransactionSchema, -} from "../../schemas/transaction"; -import { walletWithAddressParamSchema } from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -const requestParamsSchema = walletWithAddressParamSchema; - -const requestQuerySchema = Type.Object({ - fromNonce: Type.Integer({ - description: "The earliest nonce, inclusive.", - examples: [100], - minimum: 0, - }), - toNonce: Type.Optional( - Type.Integer({ - description: - "The latest nonce, inclusive. If omitted, queries up to the latest sent nonce.", - examples: [100], - minimum: 0, - }), - ), -}); - -const responseBodySchema = Type.Object({ - result: Type.Array( - Type.Object({ - nonce: Type.Integer(), - // Returns the transaction details by default. - // Falls back to the queueId if the transaction details have been pruned. - transaction: Type.Union([TransactionSchema, Type.String()]), - }), - ), -}); - -export async function getTransactionsForBackendWalletByNonce( - fastify: FastifyInstance, -) { - fastify.route<{ - Querystring: Static; - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/backend-wallet/:chain/:walletAddress/get-transactions-by-nonce", - schema: { - summary: "Get recent transactions by nonce", - description: - "Get recent transactions for this backend wallet, sorted by descending nonce.", - tags: ["Backend Wallet"], - operationId: "getTransactionsForBackendWalletByNonce", - querystring: requestQuerySchema, - params: requestParamsSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { chain, walletAddress: _walletAddress } = req.params; - const { fromNonce, toNonce } = req.query; - const chainId = await getChainIdFromChain(chain); - const walletAddress = normalizeAddress(_walletAddress); - - // Get queueIds. - const nonceMap = await getNonceMap({ - chainId, - walletAddress, - fromNonce, - toNonce, - }); - - // Build map of { queueId => transaction }. - const queueIds = nonceMap.map(({ queueId }) => queueId); - const transactions = await TransactionDB.bulkGet(queueIds); - const transactionsMap = new Map(); - for (const transaction of transactions) { - transactionsMap.set(transaction.queueId, transaction); - } - - // Hydrate the transaction, if found. - const result = nonceMap.map(({ nonce, queueId }) => { - const transaction = transactionsMap.get(queueId); - return { - nonce, - transaction: transaction ? toTransactionSchema(transaction) : queueId, - }; - }); - - res.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/get-transactions.ts b/src/server/routes/backend-wallet/get-transactions.ts deleted file mode 100644 index 2ee855562..000000000 --- a/src/server/routes/backend-wallet/get-transactions.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAddress } from "thirdweb"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { PaginationSchema } from "../../schemas/pagination"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { - TransactionSchema, - toTransactionSchema, -} from "../../schemas/transaction"; -import { walletWithAddressParamSchema } from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -const requestParamsSchema = walletWithAddressParamSchema; - -const requestQuerySchema = Type.Object({ - ...PaginationSchema.properties, - status: Type.Union( - [ - // Note: 'queued' returns all transcations, not just transactions currently queued. - Type.Literal("queued"), - Type.Literal("mined"), - Type.Literal("cancelled"), - Type.Literal("errored"), - ], - { - description: - "The status to query: 'queued', 'mined', 'errored', or 'cancelled'. Default: 'queued'", - default: "queued", - }, - ), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - transactions: Type.Array(TransactionSchema), - }), -}); - -export async function getTransactionsForBackendWallet( - fastify: FastifyInstance, -) { - fastify.route<{ - Querystring: Static; - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/backend-wallet/:chain/:walletAddress/get-all-transactions", - schema: { - summary: "Get recent transactions", - description: "Get recent transactions for this backend wallet.", - tags: ["Backend Wallet"], - operationId: "getTransactionsForBackendWallet", - querystring: requestQuerySchema, - params: requestParamsSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { chain, walletAddress: _walletAddress } = req.params; - const { page, limit, status } = req.query; - const chainId = await getChainIdFromChain(chain); - const walletAddress = getAddress(_walletAddress); - - const { transactions } = await TransactionDB.getTransactionListByStatus({ - status, - page, - limit, - }); - const filtered = transactions.filter( - (t) => t.chainId === chainId && t.from === walletAddress, - ); - - res.status(StatusCodes.OK).send({ - result: { - transactions: filtered.map(toTransactionSchema), - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/import.ts b/src/server/routes/backend-wallet/import.ts deleted file mode 100644 index 4ffb2c469..000000000 --- a/src/server/routes/backend-wallet/import.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../shared/utils/cache/get-config"; -import { createCustomError } from "../../middleware/error"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { getGcpKmsResourcePath } from "../../utils/wallets/gcp-kms-resource-path"; -import { importAwsKmsWallet } from "../../utils/wallets/import-aws-kms-wallet"; -import { importGcpKmsWallet } from "../../utils/wallets/import-gcp-kms-wallet"; -import { importLocalWallet } from "../../utils/wallets/import-local-wallet"; - -const RequestBodySchema = Type.Intersect([ - Type.Object({ - label: Type.Optional( - Type.String({ - description: "Optional label for the imported wallet", - }), - ), - }), - Type.Union([ - Type.Object({ - awsKmsArn: Type.String({ - description: "AWS KMS key ARN", - examples: [ - "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", - ], - }), - credentials: Type.Optional( - Type.Object( - { - awsAccessKeyId: Type.String({ description: "AWS Access Key ID" }), - awsSecretAccessKey: Type.String({ - description: "AWS Secret Access Key", - }), - }, - { - description: - "Optional AWS credentials to use for importing the wallet, if not provided, the default AWS credentials will be used (if available).", - }, - ), - ), - }), - // TODO: with next breaking change, only require GCP KMS resource path - Type.Object({ - gcpKmsKeyId: Type.String({ - description: "GCP KMS key ID", - examples: ["12345678-1234-1234-1234-123456789012"], - }), - gcpKmsKeyVersionId: Type.String({ - description: "GCP KMS key version ID", - examples: ["1"], - }), - credentials: Type.Optional( - Type.Object( - { - email: Type.String({ description: "GCP service account email" }), - privateKey: Type.String({ - description: "GCP service account private key", - }), - }, - { - description: - "Optional GCP credentials to use for importing the wallet, if not provided, the default GCP credentials will be used (if available).", - }, - ), - ), - }), - Type.Object({ - privateKey: Type.String({ - description: "The private key of the wallet to import", - }), - }), - Type.Object({ - mnemonic: Type.String({ - description: "The mnemonic phrase of the wallet to import", - }), - }), - Type.Object({ - encryptedJson: Type.String({ - description: "The encrypted JSON of the wallet to import", - }), - password: Type.String({ - description: "The password used to encrypt the encrypted JSON", - }), - }), - ]), -]); - -RequestBodySchema.examples = [ - { - privateKey: - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - }, - { - mnemonic: - "crouch cabbage puppy sunset fever adjust giggle blanket maze loyal wreck dream", - }, - { - encryptedJson: "", - password: "password123", - }, - { - awsKmsArn: - "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", - }, - { - gcpKmsKeyId: "12345678-1234-1234-1234-123456789012", - gcpKmsKeyVersionId: "1", - }, -]; - -const ResponseSchema = Type.Object({ - result: Type.Object({ - walletAddress: AddressSchema, - status: Type.String(), - }), -}); - -ResponseSchema.example = { - result: { - walletAddress: "0x....", - status: "success", - }, -}; - -export const importBackendWallet = async (fastify: FastifyInstance) => { - fastify.route<{ - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/backend-wallet/import", - schema: { - summary: "Import backend wallet", - description: "Import an existing wallet as a backend wallet.", - tags: ["Backend Wallet"], - operationId: "import", - body: RequestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: ResponseSchema, - }, - }, - handler: async (request, reply) => { - let walletAddress: string | undefined; - const body = request.body; - const config = await getConfig(); - - // AWS KMS - if ("awsKmsArn" in body) { - const { awsKmsArn, label, credentials } = body; - - const secretAccessKey = - credentials?.awsSecretAccessKey ?? - config.walletConfiguration.aws?.awsSecretAccessKey; - const accessKeyId = - credentials?.awsAccessKeyId ?? - config.walletConfiguration.aws?.awsAccessKeyId; - - if (!(accessKeyId && secretAccessKey)) { - throw createCustomError( - `Please provide 'awsAccessKeyId' and 'awsSecretAccessKey' to import a wallet. Can be provided as configuration or as credential with the request.`, - StatusCodes.BAD_REQUEST, - "MISSING_PARAMETERS", - ); - } - - walletAddress = await importAwsKmsWallet({ - awsKmsArn, - crendentials: { - accessKeyId, - secretAccessKey, - }, - label, - }); - } - - if ("gcpKmsKeyId" in body && !walletAddress) { - const { gcpKmsKeyId, gcpKmsKeyVersionId, credentials, label } = body; - - const email = - credentials?.email ?? - config.walletConfiguration.gcp?.gcpApplicationCredentialEmail; - const privateKey = - credentials?.privateKey ?? - config.walletConfiguration.gcp?.gcpApplicationCredentialPrivateKey; - - if (!(email && privateKey)) { - throw createCustomError( - `Please provide 'email' and 'privateKey' to import a wallet. Can be provided as configuration or as credential with the request.`, - StatusCodes.BAD_REQUEST, - "MISSING_PARAMETERS", - ); - } - - // TODO: with next breaking change, only require GCP KMS resource path - // import endpoint does not currently have resource path in the request body - // so we rely on the global configuration for these values - if ( - !( - config.walletConfiguration.gcp?.defaultGcpKmsKeyRingId && - config.walletConfiguration.gcp?.defaultGcpApplicationProjectId && - config.walletConfiguration.gcp?.defaultGcpKmsLocationId - ) - ) { - throw createCustomError( - "GCP KMS location ID, project ID, and key ring ID are required configuration for this wallet type", - StatusCodes.BAD_REQUEST, - "MISSING_PARAMETERS", - ); - } - - const gcpKmsResourcePath = getGcpKmsResourcePath({ - locationId: config.walletConfiguration.gcp.defaultGcpKmsLocationId, - keyRingId: config.walletConfiguration.gcp.defaultGcpKmsKeyRingId, - cryptoKeyId: gcpKmsKeyId, - projectId: - config.walletConfiguration.gcp.defaultGcpApplicationProjectId, - versionId: gcpKmsKeyVersionId, - }); - - const walletAddress = await importGcpKmsWallet({ - gcpKmsResourcePath, - credentials: { - email, - privateKey, - }, - label, - }); - - return reply.status(StatusCodes.OK).send({ - result: { - walletAddress, - status: "success", - }, - }); - } - - if ("privateKey" in body && !walletAddress) { - walletAddress = await importLocalWallet({ - method: "privateKey", - privateKey: body.privateKey, - label: body.label, - }); - } - - if ("mnemonic" in body && !walletAddress) { - walletAddress = await importLocalWallet({ - method: "mnemonic", - mnemonic: body.mnemonic, - label: body.label, - }); - } - - if ("encryptedJson" in body && !walletAddress) { - walletAddress = await importLocalWallet({ - method: "encryptedJson", - encryptedJson: body.encryptedJson, - password: body.password, - label: body.label, - }); - } - - if (!walletAddress) { - throw createCustomError( - "Invalid request body, please provide a valid wallet import method", - StatusCodes.BAD_REQUEST, - "INVALID_REQUEST", - ); - } - - reply.status(StatusCodes.OK).send({ - result: { - walletAddress, - status: "success", - }, - }); - }, - }); -}; diff --git a/src/server/routes/backend-wallet/remove.ts b/src/server/routes/backend-wallet/remove.ts deleted file mode 100644 index ab4cf4752..000000000 --- a/src/server/routes/backend-wallet/remove.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { deleteWalletDetails } from "../../../shared/db/wallets/delete-wallet-details"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestParamSchema = Type.Object({ - walletAddress: AddressSchema, -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - status: "success", - }, -}; - -export const removeBackendWallet = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "DELETE", - url: "/backend-wallet/:walletAddress", - schema: { - summary: "Remove backend wallet", - description: - "Remove an existing backend wallet. NOTE: This is an irreversible action for local wallets. Ensure any funds are transferred out before removing a local wallet.", - tags: ["Backend Wallet"], - operationId: "removeBackendWallet", - params: requestParamSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - const { walletAddress } = req.params; - - await deleteWalletDetails(walletAddress as Address); - - reply.status(StatusCodes.OK).send({ - result: { - status: "success", - }, - }); - }, - }); -}; diff --git a/src/server/routes/backend-wallet/reset-nonces.ts b/src/server/routes/backend-wallet/reset-nonces.ts deleted file mode 100644 index 74f2d237a..000000000 --- a/src/server/routes/backend-wallet/reset-nonces.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAddress } from "thirdweb"; -import { - deleteNoncesForBackendWallets, - getUsedBackendWallets, - syncLatestNonceFromOnchain, -} from "../../../shared/db/wallets/wallet-nonce"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - chainId: Type.Optional( - Type.Number({ - description: "The chain ID to reset nonces for.", - }), - ), - walletAddress: Type.Optional({ - ...AddressSchema, - description: - "The backend wallet address to reset nonces for. Omit to reset all backend wallets.", - }), - syncOnchainNonces: Type.Boolean({ - description: - "Resync nonces to match the onchain transaction count for your backend wallets. (Default: true)", - default: true, - }), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - status: Type.String(), - count: Type.Number({ - description: "The number of backend wallets processed.", - }), - }), -}); - -responseSchema.example = { - result: { - status: "success", - count: 1, - }, -}; - -export const resetBackendWalletNoncesRoute = async ( - fastify: FastifyInstance, -) => { - fastify.route<{ - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/backend-wallet/reset-nonces", - schema: { - summary: "Reset nonces", - description: - "Reset nonces for all backend wallets. This is for debugging purposes and does not impact held tokens.", - tags: ["Backend Wallet"], - operationId: "resetNonces", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - const { - chainId, - walletAddress: _walletAddress, - syncOnchainNonces, - } = req.body; - - // If chain+wallet are provided, only process that wallet. - // Otherwise process all used wallets that has nonce state. - const backendWallets = - chainId && _walletAddress - ? [{ chainId, walletAddress: getAddress(_walletAddress) }] - : await getUsedBackendWallets(); - - const BATCH_SIZE = 50; - for (let i = 0; i < backendWallets.length; i += BATCH_SIZE) { - const batch = backendWallets.slice(i, i + BATCH_SIZE); - - // Delete nonce state for these backend wallets. - await deleteNoncesForBackendWallets(backendWallets); - - if (syncOnchainNonces) { - // Resync nonces for these backend wallets. - await Promise.allSettled( - batch.map(({ chainId, walletAddress }) => - syncLatestNonceFromOnchain(chainId, walletAddress), - ), - ); - } - } - - reply.status(StatusCodes.OK).send({ - result: { - status: "success", - count: backendWallets.length, - }, - }); - }, - }); -}; diff --git a/src/server/routes/backend-wallet/send-transaction-batch-atomic.ts b/src/server/routes/backend-wallet/send-transaction-batch-atomic.ts deleted file mode 100644 index 80506b6e8..000000000 --- a/src/server/routes/backend-wallet/send-transaction-batch-atomic.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address, Hex } from "thirdweb"; -import { insertTransaction } from "../../../shared/utils/transaction/insert-transaction"; -import { - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { - maybeAddress, - walletChainParamSchema, - walletWithAAHeaderSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; -import { - getWalletDetails, - isSmartBackendWallet, - type ParsedWalletDetails, - WalletDetailsError, -} from "../../../shared/db/wallets/get-wallet-details"; -import { createCustomError } from "../../middleware/error"; -import { RawTransactionParamsSchema } from "../../schemas/transaction/raw-transaction-parms"; - -const requestBodySchema = Type.Object({ - transactions: Type.Array(RawTransactionParamsSchema, { - minItems: 1, - }), -}); - -export async function sendTransactionBatchAtomicRoute(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/send-transaction-batch-atomic", - schema: { - summary: "Send a batch of raw transactions atomically", - description: - "Send a batch of raw transactions in a single UserOp. Transactions will be sent in-order and atomically. Can only be used with smart wallets.", - tags: ["Backend Wallet"], - operationId: "sendTransactionBatchAtomic", - params: walletChainParamSchema, - body: requestBodySchema, - headers: Type.Omit(walletWithAAHeaderSchema, ["x-transaction-mode"]), - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - "x-backend-wallet-address": fromAddress, - "x-idempotency-key": idempotencyKey, - "x-account-address": accountAddress, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - const shouldSimulate = request.query.simulateTx ?? false; - const transactionRequests = request.body.transactions; - - const hasSmartHeaders = !!accountAddress; - - // check that we either use SBW, or send using EOA with smart wallet headers - if (!hasSmartHeaders) { - let backendWallet: ParsedWalletDetails | undefined; - - try { - backendWallet = await getWalletDetails({ - address: fromAddress, - }); - } catch (e: unknown) { - if (e instanceof WalletDetailsError) { - throw createCustomError( - `Failed to get wallet details for backend wallet ${fromAddress}. ${e.message}`, - StatusCodes.BAD_REQUEST, - "WALLET_DETAILS_ERROR", - ); - } - } - - if (!backendWallet) { - throw createCustomError( - "Failed to get wallet details for backend wallet. See: https://portal.thirdweb.com/engine/troubleshooting", - StatusCodes.INTERNAL_SERVER_ERROR, - "WALLET_DETAILS_ERROR", - ); - } - - if (!isSmartBackendWallet(backendWallet)) { - throw createCustomError( - "Backend wallet is not a smart wallet, and x-account-address is not provided. Either use a smart backend wallet or provide x-account-address. This endpoint can only be used with smart wallets.", - StatusCodes.BAD_REQUEST, - "BACKEND_WALLET_NOT_SMART", - ); - } - } - - if (transactionRequests.length === 0) { - throw createCustomError( - "No transactions provided", - StatusCodes.BAD_REQUEST, - "NO_TRANSACTIONS_PROVIDED", - ); - } - - const queueId = await insertTransaction({ - insertedTransaction: { - transactionMode: undefined, - isUserOp: false, - chainId, - from: fromAddress as Address, - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt: accountSalt, - batchOperations: transactionRequests.map((transactionRequest) => ({ - to: transactionRequest.toAddress as Address | undefined, - data: transactionRequest.data as Hex, - value: BigInt(transactionRequest.value), - })), - }, - shouldSimulate, - idempotencyKey, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/send-transaction-batch.ts b/src/server/routes/backend-wallet/send-transaction-batch.ts deleted file mode 100644 index 26bd08290..000000000 --- a/src/server/routes/backend-wallet/send-transaction-batch.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address, Hex } from "thirdweb"; -import { insertTransaction } from "../../../shared/utils/transaction/insert-transaction"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../schemas/tx-overrides"; -import { - walletChainParamSchema, - walletHeaderSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; -import { parseTransactionOverrides } from "../../utils/transaction-overrides"; - -const requestBodySchema = Type.Array( - Type.Object({ - toAddress: Type.Optional(AddressSchema), - data: Type.String({ - examples: ["0x..."], - }), - value: Type.String({ - examples: ["10000000"], - }), - ...txOverridesWithValueSchema.properties, - }), -); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - queueIds: Type.Array(Type.String()), - }), -}); - -export async function sendTransactionBatch(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/send-transaction-batch", - schema: { - summary: "Send a batch of raw transactions", - description: - "Send a batch of raw transactions with transaction parameters", - tags: ["Backend Wallet"], - operationId: "sendTransactionBatch", - params: walletChainParamSchema, - body: requestBodySchema, - headers: walletHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - "x-backend-wallet-address": fromAddress, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const transactionRequests = request.body; - - const queueIds: string[] = []; - for (const transactionRequest of transactionRequests) { - const { toAddress, data, value, txOverrides } = transactionRequest; - - const queueId = await insertTransaction({ - insertedTransaction: { - isUserOp: false, - chainId, - transactionMode, - from: fromAddress as Address, - to: toAddress as Address | undefined, - data: data as Hex, - value: BigInt(value), - ...parseTransactionOverrides(txOverrides), - }, - }); - queueIds.push(queueId); - } - - reply.status(StatusCodes.OK).send({ - result: { - queueIds, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/send-transaction.ts b/src/server/routes/backend-wallet/send-transaction.ts deleted file mode 100644 index 13e2a8f3a..000000000 --- a/src/server/routes/backend-wallet/send-transaction.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address, Hex } from "thirdweb"; -import { insertTransaction } from "../../../shared/utils/transaction/insert-transaction"; -import { AddressSchema } from "../../schemas/address"; -import { - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { txOverridesSchema } from "../../schemas/tx-overrides"; -import { - maybeAddress, - walletChainParamSchema, - walletWithAAHeaderSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; -import { parseTransactionOverrides } from "../../utils/transaction-overrides"; - -const requestBodySchema = Type.Object({ - toAddress: Type.Optional(AddressSchema), - data: Type.String({ - examples: ["0x..."], - }), - value: Type.String({ - examples: ["10000000"], - }), - ...txOverridesSchema.properties, -}); - -requestBodySchema.examples = [ - { - toAddress: "0x7a0ce8524bea337f0bee853b68fabde145dac0a0", - data: "0x449a52f800000000000000000000000043cae0d7fe86c713530e679ce02574743b2ee9fc0000000000000000000000000000000000000000000000000de0b6b3a7640000", - value: "0x00", - txOverrides: { - gas: "50000", - }, - }, -]; - -export async function sendTransaction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/send-transaction", - schema: { - summary: "Send a transaction", - description: "Send a transaction with transaction parameters", - tags: ["Backend Wallet"], - operationId: "sendTransaction", - params: walletChainParamSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { toAddress, data, value, txOverrides } = request.body; - const { simulateTx } = request.query; - const { - "x-backend-wallet-address": fromAddress, - "x-idempotency-key": idempotencyKey, - "x-account-address": accountAddress, - "x-account-factory-address": accountFactoryAddress, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - - let queueId: string; - if (accountAddress) { - queueId = await insertTransaction({ - insertedTransaction: { - isUserOp: true, - chainId, - from: fromAddress as Address, - to: toAddress as Address | undefined, - data: data as Hex, - value: BigInt(value), - accountAddress: accountAddress as Address, - signerAddress: fromAddress as Address, - target: toAddress as Address | undefined, - transactionMode: undefined, - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - ...parseTransactionOverrides(txOverrides), - }, - shouldSimulate: simulateTx, - idempotencyKey, - }); - } else { - queueId = await insertTransaction({ - insertedTransaction: { - isUserOp: false, - chainId, - from: fromAddress as Address, - to: toAddress as Address | undefined, - data: data as Hex, - transactionMode: transactionMode, - value: BigInt(value), - ...parseTransactionOverrides(txOverrides), - }, - shouldSimulate: simulateTx, - idempotencyKey, - }); - } - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/sign-message.ts b/src/server/routes/backend-wallet/sign-message.ts deleted file mode 100644 index fa3bb0cfe..000000000 --- a/src/server/routes/backend-wallet/sign-message.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { isHex, type Hex } from "thirdweb"; -import { arbitrumSepolia } from "thirdweb/chains"; -import { - getWalletDetails, - isSmartBackendWallet, -} from "../../../shared/db/wallets/get-wallet-details"; -import { walletDetailsToAccount } from "../../../shared/utils/account"; -import { getChain } from "../../../shared/utils/chain"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { walletHeaderSchema } from "../../schemas/wallet"; - -const requestBodySchema = Type.Object({ - message: Type.String(), - isBytes: Type.Optional(Type.Boolean()), - chainId: Type.Optional(Type.Number()), -}); - -const responseBodySchema = Type.Object({ - result: Type.String(), -}); - -export async function signMessageRoute(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/sign-message", - schema: { - summary: "Sign a message", - description: "Send a message", - tags: ["Backend Wallet"], - operationId: "signMessage", - body: requestBodySchema, - headers: walletHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { message, isBytes, chainId } = request.body; - const { "x-backend-wallet-address": walletAddress } = - request.headers as Static; - - if (isBytes && !isHex(message)) { - throw createCustomError( - '"isBytes" is true but message is not hex.', - StatusCodes.BAD_REQUEST, - "INVALID_MESSAGE", - ); - } - - const walletDetails = await getWalletDetails({ - address: walletAddress, - }); - - if (isSmartBackendWallet(walletDetails) && !chainId) { - throw createCustomError( - "Chain ID is required for signing messages with smart wallets.", - StatusCodes.BAD_REQUEST, - "CHAIN_ID_REQUIRED", - ); - } - - const chain = chainId ? await getChain(chainId) : arbitrumSepolia; - - const { account } = await walletDetailsToAccount({ - walletDetails, - chain, - }); - - const messageToSign = isBytes ? { raw: message as Hex } : message; - const signedMessage = await account.signMessage({ - message: messageToSign, - }); - - reply.status(StatusCodes.OK).send({ - result: signedMessage, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/sign-transaction.ts b/src/server/routes/backend-wallet/sign-transaction.ts deleted file mode 100644 index 3cab7e0a7..000000000 --- a/src/server/routes/backend-wallet/sign-transaction.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAccount } from "../../../shared/utils/account"; -import { - getChecksumAddress, - maybeBigInt, - maybeInt, -} from "../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { walletHeaderSchema } from "../../schemas/wallet"; -import { - prepareTransaction, - toSerializableTransaction, - type Hex, -} from "thirdweb"; -import { getChain } from "../../../shared/utils/chain"; - -const requestBodySchema = Type.Object({ - transaction: Type.Object({ - to: Type.Optional(Type.String()), - nonce: Type.Optional(Type.String()), - gasLimit: Type.Optional(Type.String()), - gasPrice: Type.Optional(Type.String()), - data: Type.Optional(Type.String()), - value: Type.Optional(Type.String()), - chainId: Type.Integer(), - type: Type.Optional(Type.Integer()), - accessList: Type.Optional(Type.Any()), - maxFeePerGas: Type.Optional(Type.String()), - maxPriorityFeePerGas: Type.Optional(Type.String()), - ccipReadEnabled: Type.Optional(Type.Boolean()), - }), -}); - -const responseBodySchema = Type.Object({ - result: Type.String(), -}); - -export async function signTransaction(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/sign-transaction", - schema: { - summary: "Sign a transaction", - description: "Sign a transaction", - tags: ["Backend Wallet"], - operationId: "signTransaction", - body: requestBodySchema, - headers: walletHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { "x-backend-wallet-address": walletAddress } = - request.headers as Static; - - const { chainId, nonce, ...transaction } = request.body.transaction; - const chain = await getChain(chainId); - - const account = await getAccount({ - chainId, - from: getChecksumAddress(walletAddress), - }); - - if (!account.signTransaction) { - throw createCustomError( - 'This backend wallet does not support "signTransaction".', - StatusCodes.BAD_REQUEST, - "SIGN_TRANSACTION_UNIMPLEMENTED", - ); - } - - // const prepareTransactionOptions: StaticPrepareTransactionOptions - const prepareTransactionOptions = { - ...transaction, - data: transaction.data as Hex | undefined, - client: thirdwebClient, - nonce: maybeInt(nonce), - chain, - value: maybeBigInt(transaction.value), - gas: maybeBigInt(transaction.gasLimit), - gasPrice: maybeBigInt(transaction.gasPrice), - maxFeePerGas: maybeBigInt(transaction.maxFeePerGas), - maxPriorityFeePerGas: maybeBigInt(transaction.maxPriorityFeePerGas), - }; - - const preparedTransaction = prepareTransaction(prepareTransactionOptions); - const serializableTransaction = await toSerializableTransaction({ - transaction: preparedTransaction, - }); - - const signature = await account.signTransaction(serializableTransaction); - - reply.status(StatusCodes.OK).send({ - result: signature, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/sign-typed-data.ts b/src/server/routes/backend-wallet/sign-typed-data.ts deleted file mode 100644 index d668f60ed..000000000 --- a/src/server/routes/backend-wallet/sign-typed-data.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { TypedDataSigner } from "@ethersproject/abstract-signer"; -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getWallet } from "../../../shared/utils/cache/get-wallet"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { walletHeaderSchema } from "../../schemas/wallet"; - -const requestBodySchema = Type.Object({ - domain: Type.Object({}, { additionalProperties: true }), - types: Type.Object({}, { additionalProperties: true }), - value: Type.Object({}, { additionalProperties: true }), -}); - -const responseBodySchema = Type.Object({ - result: Type.String(), -}); - -export async function signTypedData(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/sign-typed-data", - schema: { - summary: "Sign an EIP-712 message", - description: 'Send an EIP-712 message ("typed data")', - tags: ["Backend Wallet"], - operationId: "signTypedData", - body: requestBodySchema, - headers: walletHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { domain, value, types } = request.body; - const { "x-backend-wallet-address": walletAddress } = - request.headers as Static; - - const wallet = await getWallet({ chainId: 1, walletAddress }); - - const signer = (await wallet.getSigner()) as unknown as TypedDataSigner; - const result = await signer._signTypedData(domain, types, value); - - reply.status(StatusCodes.OK).send({ - result: result, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/simulate-transaction.ts b/src/server/routes/backend-wallet/simulate-transaction.ts deleted file mode 100644 index 3c0e76638..000000000 --- a/src/server/routes/backend-wallet/simulate-transaction.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { randomUUID } from "node:crypto"; -import type { Address, Hex } from "thirdweb"; -import { doSimulateTransaction } from "../../../shared/utils/transaction/simulate-queued-transaction"; -import type { QueuedTransaction } from "../../../shared/utils/transaction/types"; -import { createCustomError } from "../../middleware/error"; -import { AddressSchema } from "../../schemas/address"; -import { - simulateResponseSchema, - standardResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { - walletChainParamSchema, - walletWithAAHeaderSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -const FunctionArgumentSchema = Type.Union([ - Type.String({ description: "String argument" }), - Type.Number({ description: "Numeric argument" }), - Type.Boolean({ description: "Boolean argument" }), - Type.Array(Type.Any(), { description: "Array argument" }), - Type.Object({}, { description: "Object argument" }), -]); - -const simulateRequestBodySchema = Type.Object({ - toAddress: { - ...AddressSchema, - description: "The contract address", - }, - value: Type.Optional( - Type.String({ - examples: ["0"], - description: "The amount of native currency in wei", - }), - ), - // Decoded transaction args - functionName: Type.Optional( - Type.String({ - description: "The function to call on the contract", - }), - ), - args: Type.Optional( - Type.Array(FunctionArgumentSchema, { - description: "The arguments to call for this function", - }), - ), - // Raw transaction args - data: Type.Optional( - Type.String({ - description: "Raw calldata", - }), - ), -}); - -export async function simulateTransaction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/simulate-transaction", - schema: { - summary: "Simulate a transaction", - description: "Simulate a transaction with transaction parameters", - tags: ["Backend Wallet"], - operationId: "simulateTransaction", - params: walletChainParamSchema, - body: simulateRequestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: simulateResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { toAddress, value, functionName, args, data } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - - const queuedTransaction: QueuedTransaction = { - status: "queued", - queueId: randomUUID(), - queuedAt: new Date(), - resendCount: 0, - - chainId, - from: walletAddress as Address, - to: toAddress as Address, - functionName, - functionArgs: args, - data: data as Hex | undefined, - value: value ? BigInt(value) : 0n, - transactionMode: transactionMode, - - ...(accountAddress - ? { - isUserOp: true, - accountAddress: accountAddress as Address, - target: toAddress as Address, - signerAddress: walletAddress as Address, - } - : { - isUserOp: false, - }), - }; - - const simulateError = await doSimulateTransaction(queuedTransaction); - if (simulateError) { - throw createCustomError( - simulateError, - StatusCodes.BAD_REQUEST, - "FAILED_SIMULATION", - ); - } - - reply.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/transfer.ts b/src/server/routes/backend-wallet/transfer.ts deleted file mode 100644 index 2c3c7d765..000000000 --- a/src/server/routes/backend-wallet/transfer.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - NATIVE_TOKEN_ADDRESS, - ZERO_ADDRESS, - getContract, - toWei, - type Address, -} from "thirdweb"; -import { transfer as transferERC20 } from "thirdweb/extensions/erc20"; -import { isContractDeployed, resolvePromisedValue } from "thirdweb/utils"; -import { getChain } from "../../../shared/utils/chain"; -import { normalizeAddress } from "../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { insertTransaction } from "../../../shared/utils/transaction/insert-transaction"; -import type { InsertedTransaction } from "../../../shared/utils/transaction/types"; -import { createCustomError } from "../../middleware/error"; -import { AddressSchema } from "../../schemas/address"; -import { TokenAmountStringSchema } from "../../schemas/number"; -import { - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../schemas/tx-overrides"; -import { - walletHeaderSchema, - walletWithAddressParamSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; -import { parseTransactionOverrides } from "../../utils/transaction-overrides"; - -const requestSchema = Type.Omit(walletWithAddressParamSchema, [ - "walletAddress", -]); -const requestBodySchema = Type.Object({ - to: { - ...AddressSchema, - description: "The recipient wallet address.", - }, - currencyAddress: Type.Optional({ - ...AddressSchema, - examples: [ZERO_ADDRESS], - description: - "The token address to transfer. Omit to transfer the chain's native currency (e.g. ETH on Ethereum).", - }), - amount: { - ...TokenAmountStringSchema, - description: - 'The amount in ether to transfer. Example: "0.1" to send 0.1 ETH.', - }, - ...txOverridesWithValueSchema.properties, -}); - -export async function transfer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/transfer", - schema: { - summary: "Transfer tokens", - description: - "Transfer native currency or ERC20 tokens to another wallet.", - tags: ["Backend Wallet"], - operationId: "transfer", - params: requestSchema, - body: requestBodySchema, - headers: walletHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - to, - amount, - currencyAddress: _currencyAddress = ZERO_ADDRESS, - txOverrides, - } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - const { simulateTx: shouldSimulate } = request.query; - - // Resolve inputs. - const currencyAddress = normalizeAddress(_currencyAddress); - const chainId = await getChainIdFromChain(chain); - - let insertedTransaction: InsertedTransaction; - if ( - currencyAddress === ZERO_ADDRESS || - currencyAddress === NATIVE_TOKEN_ADDRESS - ) { - insertedTransaction = { - isUserOp: false, - chainId, - from: walletAddress as Address, - to: to as Address, - data: "0x", - value: toWei(amount), - extension: "none", - functionName: "transfer", - transactionMode, - ...parseTransactionOverrides(txOverrides), - }; - } else { - const contract = getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: currencyAddress, - }); - - // Assert a valid contract. This call is cached. - // @TODO: Replace with isTransferSupported - const isValid = await isContractDeployed(contract); - if (!isValid) { - throw createCustomError( - "Invalid currency contract.", - StatusCodes.BAD_REQUEST, - "INVALID_CONTRACT", - ); - } - - const transaction = transferERC20({ contract, to, amount }); - - insertedTransaction = { - isUserOp: false, - chainId, - from: walletAddress as Address, - to: (await resolvePromisedValue(transaction.to)) as - | Address - | undefined, - data: await resolvePromisedValue(transaction.data), - value: 0n, - extension: "erc20", - functionName: "transfer", - functionArgs: [to, amount, currencyAddress], - transactionMode, - ...parseTransactionOverrides(txOverrides), - }; - } - - const queueId = await insertTransaction({ - insertedTransaction, - idempotencyKey, - shouldSimulate, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/backend-wallet/update.ts b/src/server/routes/backend-wallet/update.ts deleted file mode 100644 index 8a021084b..000000000 --- a/src/server/routes/backend-wallet/update.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateWalletDetails } from "../../../shared/db/wallets/update-wallet-details"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - walletAddress: AddressSchema, - label: Type.Optional(Type.String()), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - walletAddress: AddressSchema, - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - walletAddress: "0x....", - status: "success", - }, -}; - -export const updateBackendWallet = async (fastify: FastifyInstance) => { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/backend-wallet/update", - schema: { - summary: "Update backend wallet", - description: "Update a backend wallet.", - tags: ["Backend Wallet"], - operationId: "update", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - const { walletAddress, label } = req.body; - - await updateWalletDetails({ - address: walletAddress, - label, - }); - - reply.status(StatusCodes.OK).send({ - result: { - walletAddress, - status: "success", - }, - }); - }, - }); -}; diff --git a/src/server/routes/backend-wallet/withdraw.ts b/src/server/routes/backend-wallet/withdraw.ts deleted file mode 100644 index c5e233d23..000000000 --- a/src/server/routes/backend-wallet/withdraw.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - toSerializableTransaction, - toTokens, - type Address, - type Hex, -} from "thirdweb"; -import { getChainMetadata } from "thirdweb/chains"; -import { getWalletBalance } from "thirdweb/wallets"; -import { getAccount } from "../../../shared/utils/account"; -import { getChain } from "../../../shared/utils/chain"; -import { logger } from "../../../shared/utils/logger"; -import { getChecksumAddress } from "../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import type { PopulatedTransaction } from "../../../shared/utils/transaction/types"; -import { createCustomError } from "../../middleware/error"; -import { AddressSchema, TransactionHashSchema } from "../../schemas/address"; -import { TokenAmountStringSchema } from "../../schemas/number"; -import { - requestQuerystringSchema, - standardResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { txOverridesSchema } from "../../schemas/tx-overrides"; -import { - walletHeaderSchema, - walletWithAddressParamSchema, -} from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; -import { parseTransactionOverrides } from "../../utils/transaction-overrides"; - -const ParamsSchema = Type.Omit(walletWithAddressParamSchema, ["walletAddress"]); - -const requestBodySchema = Type.Object({ - toAddress: { - ...AddressSchema, - description: "Address to withdraw all funds to", - }, - ...txOverridesSchema.properties, -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - transactionHash: TransactionHashSchema, - amount: TokenAmountStringSchema, - }), -}); - -export async function withdraw(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/backend-wallet/:chain/withdraw", - schema: { - summary: "Withdraw funds", - description: "Withdraw all funds from this wallet to another wallet.", - tags: ["Backend Wallet"], - operationId: "withdraw", - params: ParamsSchema, - body: requestBodySchema, - headers: walletHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain: chainQuery } = request.params; - const { toAddress, txOverrides } = request.body; - const { "x-backend-wallet-address": walletAddress } = - request.headers as Static; - - const chainId = await getChainIdFromChain(chainQuery); - const chain = await getChain(chainId); - const from = getChecksumAddress(walletAddress); - - // Populate a transfer transaction with 2x gas. - const populatedTransaction = await toSerializableTransaction({ - from, - transaction: { - to: toAddress, - chain, - client: thirdwebClient, - data: "0x", - // Dummy value, replaced below. - value: 1n, - ...parseTransactionOverrides(txOverrides).overrides, - }, - }); - - // Compute the maximum amount to withdraw taking into account gas fees. - const value = await getWithdrawValue(from, populatedTransaction); - populatedTransaction.value = value; - - const account = await getAccount({ chainId, from }); - let transactionHash: Hex | undefined; - try { - const res = await account.sendTransaction(populatedTransaction); - transactionHash = res.transactionHash; - } catch (e) { - logger({ - level: "warn", - message: `Error withdrawing funds: ${e}`, - service: "server", - }); - - const metadata = await getChainMetadata(chain); - throw createCustomError( - `Insufficient ${metadata.nativeCurrency?.symbol} on ${metadata.name} in ${from}. Try again when network gas fees are lower. See: https://portal.thirdweb.com/engine/troubleshooting`, - StatusCodes.BAD_REQUEST, - "INSUFFICIENT_FUNDS", - ); - } - - reply.status(StatusCodes.OK).send({ - result: { - transactionHash, - amount: toTokens(value, 18), - }, - }); - }, - }); -} - -const getWithdrawValue = async ( - from: Address, - populatedTransaction: PopulatedTransaction, -): Promise => { - const chain = await getChain(populatedTransaction.chainId); - - // Get wallet balance. - const { value: balanceWei } = await getWalletBalance({ - address: from, - client: thirdwebClient, - chain, - }); - - // Set the withdraw value to be the amount of gas that isn't reserved to send the transaction. - const gasPrice = - populatedTransaction.maxFeePerGas ?? populatedTransaction.gasPrice; - if (!gasPrice) { - throw new Error("Unable to estimate gas price for withdraw request."); - } - - const transferCostWei = populatedTransaction.gas * gasPrice; - return balanceWei - transferCostWei; -}; diff --git a/src/server/routes/chain/balance.ts b/src/server/routes/chain/balance.ts new file mode 100644 index 000000000..7889003a0 --- /dev/null +++ b/src/server/routes/chain/balance.ts @@ -0,0 +1,99 @@ +// src/routes/onchain/balance.ts + +import { describeRoute } from "hono-openapi"; +import { resolver, validator } from "hono-openapi/zod"; +import { ResultAsync } from "neverthrow"; +import { eth_getBalance, getRpcClient } from "thirdweb"; +import * as z from "zod"; +import { serialisedBigIntSchema } from "../../../executors/types.js"; // Adjust path as needed +import { getChain } from "../../../lib/chain.js"; // Adjust path as needed +import { + accountActionErrorMapper, + engineErrToHttpException, + zErrorMapper, +} from "../../../lib/errors.js"; // Adjust path as needed +import { thirdwebClient } from "../../../lib/thirdweb-client.js"; // Adjust path as needed +import { evmAddressSchema } from "../../../lib/zod.js"; // Adjust path as needed +import { wrapResponseSchema } from "../../schemas/shared-api-schemas.js"; // Adjust path as needed +import { onchainRoutesFactory } from "./factory.js"; // Adjust path as needed + +// --- Schemas --- + +// Schema for the request body +const balanceRequestSchema = z.object({ + chainId: z.string().describe("The chain ID to query the balance on."), + address: evmAddressSchema.describe( + "The EVM address to get the native balance for.", + ), +}); + +// Schema for the successful response data +const balanceSuccessSchema = z.object({ + balance: serialisedBigIntSchema.describe( + "The native balance of the address as a stringified integer.", + ), +}); + +// Schema for the final wrapped API response +const balanceResponseSchema = wrapResponseSchema(balanceSuccessSchema); + +// --- Route Handler --- + +export const getNativeBalanceRoute = onchainRoutesFactory.createHandlers( + validator("json", balanceRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Read"], + operationId: "getNativeBalance", + summary: "Read Native Balance", + description: + "Fetches the native cryptocurrency balance (e.g., ETH, MATIC) for a given address on a specific chain.", + responses: { + 200: { + description: "OK - Balance fetched successfully.", + content: { + "application/json": { schema: resolver(balanceResponseSchema) }, + }, + }, + // Include standard error responses if your factory doesn't handle them + 400: { description: "Bad Request - Invalid input" }, + 500: { description: "Internal Server Error" }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const { chainId, address } = body; + + const chain = getChain(Number.parseInt(chainId)); // Assuming getChain handles potential errors + const overrideThirdwebClient = c.get("thirdwebClient"); + const client = overrideThirdwebClient ?? thirdwebClient; + const rpcClient = getRpcClient({ client, chain }); + + // Use ResultAsync to handle the potential promise rejection from getBalance + const balanceResult = await ResultAsync.fromPromise( + eth_getBalance(rpcClient, { address }), + accountActionErrorMapper({ + code: "get_balance_failed", + status: 500, // Or 404/400 depending on expected errors + defaultMessage: `Failed to fetch native balance for address ${address} on chain ${chainId}`, + address: address, + chainId: chainId, + }), + ); + + // Handle potential errors during the balance fetch + if (balanceResult.isErr()) { + // Convert the EngineErr to an HTTPException using the existing utility + throw engineErrToHttpException(balanceResult.error); + } + + // Extract the balance (which is a bigint) + const balanceBigInt = balanceResult.value; + + // Format the successful response + return c.json({ + result: { + balance: balanceBigInt.toString(), // Serialize bigint to string for JSON + }, + }); + }, +); diff --git a/src/server/routes/chain/contract.ts b/src/server/routes/chain/contract.ts new file mode 100644 index 000000000..1c95a6172 --- /dev/null +++ b/src/server/routes/chain/contract.ts @@ -0,0 +1,655 @@ +import type { AbiParameter } from "abitype"; +import { Abi } from "abitype/zod"; +import { describeRoute } from "hono-openapi"; +import { resolver, validator } from "hono-openapi/zod"; +import { ResultAsync } from "neverthrow"; +import { AbiFunction } from "ox"; +import { + type Address, + encode, + getContract, + type Hex, + prepareContractCall, + readContract, + resolveMethod, +} from "thirdweb"; +import { decodeAbiParameters, parseAbiParams } from "thirdweb/utils"; +import * as z from "zod"; +import { execute } from "../../../executors/execute/execute.js"; +import { + bigIntSchema, + buildExecutionRequestSchema, + EXECUTION_OPTIONS_EXAMPLE, + serialisedBigIntSchema, + transactionResponseSchema, +} from "../../../executors/types.js"; +import { getChainResult } from "../../../lib/chain.js"; +import { + accountActionErrorMapper, + type EngineErr, + engineErrToHttpException, + getDefaultErrorMessage, + isEngineErr, + zErrorMapper, +} from "../../../lib/errors.js"; +import { thirdwebClient } from "../../../lib/thirdweb-client.js"; +import { + evmAddressSchema, + exampleBaseSepoliaUsdcAddress, + exampleEvmAddress, + hexSchema, +} from "../../../lib/zod.js"; +import { getThirdwebCredentialsFromContext } from "../../middleware/thirdweb-client.js"; +import { + credentialsFromHeaders, + executionCredentialsHeadersSchema, + wrapResponseSchema, +} from "../../schemas/shared-api-schemas.js"; +import { onchainRoutesFactory } from "./factory.js"; + +// Schema for contract parameters in the URL +const transactionParamsWithoutValueSchema = z.object({ + method: z.string().describe("The function to call on the contract"), + params: z + .array(z.any()) + .describe("The parameters to pass to the function") + .openapi({ + example: [exampleEvmAddress, "0"], + }), + contractAddress: evmAddressSchema.describe("The contract address to call"), + abi: z.array(z.any()).optional().describe("The ABI of the contract"), +}); + +const transactionParamsSchema = transactionParamsWithoutValueSchema.extend({ + value: bigIntSchema + .describe("The value to send with the transaction") + .optional() + .default("0"), +}); + +const writeRequestSchema = buildExecutionRequestSchema( + z.array(transactionParamsSchema), +).openapi({ + example: { + params: [ + { + contractAddress: exampleBaseSepoliaUsdcAddress, + method: + "function approve(address spender, uint256 value) returns (bool)", + params: ["0x1234567890123456789012345678901234567890", "100"], + }, + ], + executionOptions: EXECUTION_OPTIONS_EXAMPLE, + }, +}); + +const encodeRequestSchema = z + .object({ + encodeOptions: z.object({ + chainId: z.string().openapi({ + description: "The chain id of the transaction", + }), + }), + params: z.array(transactionParamsSchema), + }) + .openapi({ + example: { + params: [ + { + contractAddress: exampleBaseSepoliaUsdcAddress, + method: + "function approve(address spender, uint256 value) returns (bool)", + params: ["0x1234567890123456789012345678901234567890", "100"], + }, + ], + encodeOptions: { + chainId: "84532", + }, + }, + }); + +// const readRequestSchema = buildExecutionRequestSchema( +// z.array(transactionParamsSchema), +// z.object({ +// multicallAddress: evmAddressSchema +// .optional() +// .describe("Optional multicall address"), +// }), +// ); + +const MULTICALL3_DEFAULT_ADDRESS = + "0xcA11bde05977b3631167028862bE2a173976CA11" as const; + +const readRequestSchema = z + .object({ + readOptions: z.object({ + multicallAddress: evmAddressSchema + .default(MULTICALL3_DEFAULT_ADDRESS) + .describe( + "Optional multicall address, defaults to the default multicall3 address for the chain", + ), + chainId: z.string().openapi({ + description: "The chain id of the transaction", + }), + from: evmAddressSchema.optional(), + }), + params: z.array(transactionParamsWithoutValueSchema), + }) + .openapi({ + example: { + params: [ + { + contractAddress: exampleBaseSepoliaUsdcAddress, + method: "function balanceOf(address account) view returns (uint256)", + params: [exampleEvmAddress], + }, + ], + readOptions: { + chainId: "84532", + }, + }, + }); + +const encodeDataSchema = z.object({ + to: evmAddressSchema, + data: hexSchema, + value: serialisedBigIntSchema, +}); + +const encodeSuccessItemSchema = z.object({ + success: z.literal(true), + result: encodeDataSchema, +}); + +const encodeErrorSchema = z + .object({ + kind: z.string(), + code: z.string(), + status: z.number(), + message: z.string().optional(), + address: evmAddressSchema.optional(), + chainId: z.string().optional(), + }) + .describe("Standardized error object"); + +const encodeErrorItemSchema = z.object({ + success: z.literal(false), + error: encodeErrorSchema, +}); + +const encodeResultItemSchema = z.union([ + encodeSuccessItemSchema, + encodeErrorItemSchema, +]); + +const encodeResponseSchema = wrapResponseSchema( + z.object({ results: z.array(encodeResultItemSchema) }), +); + +type EncodeSuccessItem = z.infer; +type EncodeErrorItem = z.infer; + +const readResultItemSchema = z.object({ + success: z.boolean(), + result: z.any().nullable(), +}); + +const readResponseSchema = wrapResponseSchema( + z.object({ results: z.array(readResultItemSchema) }), +); + +type PreparedMulticallItem = { + target: Address; + allowFailure: true; + callData: Hex; + abiFunction: AbiFunction.AbiFunction; +}; + +// --- Constants --- +const MULTICALL3_AGGREGATE3_ABI = { + /* ... ABI ... */ inputs: [ + { + components: [ + { name: "target", type: "address" }, + { name: "allowFailure", type: "bool" }, + { name: "callData", type: "bytes" }, + ], + name: "calls", + type: "tuple[]", + }, + ], + name: "aggregate3", + outputs: [ + { + components: [ + { name: "success", type: "bool" }, + { name: "returnData", type: "bytes" }, + ], + name: "returnData", + type: "tuple[]", + }, + ], + stateMutability: "payable", + type: "function", +} as const; + +// --- Reusable Batch Processing Function --- + +/** + * Processes a batch of items asynchronously, handling individual errors using neverthrow. + * + * @param items - The array of input items to process. + * @param client - The ThirdwebClient instance. + * @param chain - The resolved Chain object. + * @param processorFn - An async function that processes a single item and returns a ResultAsync. + * @returns A Promise resolving to an array containing either success results or EngineErr objects. + */ +async function processBatch< + TInput extends { contractAddress: Address; method: string }, + TSuccess, + TError, +>( + items: TInput[], + processorFn: (item: TInput) => ResultAsync, +): Promise> { + const processingPromises = items.map((item) => processorFn(item)); + + const settledResults = await Promise.all(processingPromises); + + return settledResults.map((result) => { + return result.match( + (successData) => successData, + (errorData) => errorData, + ); + }); +} + +// --- Route Handlers --- + +// 1. Encode Function Data (Batch) Handler +export const encodeFunctionDataRoute = onchainRoutesFactory.createHandlers( + validator("json", encodeRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Encode"], + operationId: "encodeFunctionData", + summary: "Encode Function Data", + description: + "Encode a contract call into transaction parameters (to, data, value).", + responses: { + 200: { + description: "OK", + content: { + "application/json": { schema: resolver(encodeResponseSchema) }, + }, + }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const { params: transactionParams, encodeOptions } = body; + const { chainId } = encodeOptions; + + const chainResult = getChainResult(chainId); + if (chainResult.isErr()) { + throw engineErrToHttpException(chainResult.error); + } + const chain = chainResult.value; + + const overrideThirdwebClient = c.get("thirdwebClient"); + const client = overrideThirdwebClient ?? thirdwebClient; + + // Define the processor function using the user's exact logic + const encodeProcessor = ( + transactionParam: z.infer, // Renamed for clarity matching snippet + ): ResultAsync => { + const { data } = Abi.safeParse(transactionParam.abi); + const contract = getContract({ + client, + chain, + address: transactionParam.contractAddress, + abi: data, + }); + + return ResultAsync.fromPromise( + // Use the function call signature from the snippet + resolveMethod(transactionParam.method)(contract), + accountActionErrorMapper({ + code: "resolve_method_failed", + // Use message from snippet if desired, or keep more specific one + defaultMessage: `Failed to resolve method ${transactionParam.method}`, + status: 400, // 400 might be better if method doesn't exist + address: transactionParam.contractAddress, + chainId: chainId, + }), + ) + .map((method) => { + const params = parseAbiParams( + method.inputs.map((i) => i.type), + transactionParam.params, + ); + const methodSignature = AbiFunction.format(method); + + return prepareContractCall({ + contract, + method: methodSignature, + params, + }); + }) + .andThen((preparedTransaction) => + ResultAsync.fromPromise( + encode(preparedTransaction), + accountActionErrorMapper({ + code: "encode_transaction_failed", + defaultMessage: "Failed to encode transaction", + status: 500, + chainId: chainId, + address: transactionParam.contractAddress, + }), + ), + ) + .map((encodedData): EncodeSuccessItem => { + // Map the successful encoded data to the final structure + return { + success: true, + result: { + to: transactionParam.contractAddress, + data: encodedData, + value: (transactionParam.value ?? 0n).toString(), + }, + }; + }) + .mapErr((engineErr) => { + return { + success: false, + error: { + ...engineErr, + message: engineErr.message ?? getDefaultErrorMessage(engineErr), + }, + }; + }); + }; + + // Process the batch using the abstraction + const results = await processBatch(transactionParams, encodeProcessor); + + return c.json({ result: { results } }); + }, +); + +// 2. Read From Contract (Batch) Handler (Remains the same, uses its own preparation logic for multicall) +export const readFromContractRoute = onchainRoutesFactory.createHandlers( + validator("json", readRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Read"], + operationId: "readContract", + summary: "Read Contract", + description: + "Call read-only contract functions or batch read using multicall.", + responses: { + 200: { + description: "OK", + content: { + "application/json": { schema: resolver(readResponseSchema) }, + }, + }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const { params: transactionParams } = body; + const { chainId, multicallAddress: customMulticallAddress } = + body.readOptions; + + const chainResult = getChainResult(chainId); + if (chainResult.isErr()) { + throw engineErrToHttpException(chainResult.error); + } + const chain = chainResult.value; + + const overrideThirdwebClient = c.get("thirdwebClient"); + const client = overrideThirdwebClient ?? thirdwebClient; + const multicallAddress = + customMulticallAddress ?? MULTICALL3_DEFAULT_ADDRESS; + + // Read route needs its own preparation logic for multicall structure + const readPrepareProcessor = ( + callParams: z.infer, + ): ResultAsync => { + const { + contractAddress, + method: methodName, + params, + abi: customAbi, + } = callParams; + const { data: parsedAbi } = Abi.safeParse(customAbi); + const contract = getContract({ + client, + chain, + address: contractAddress, + abi: parsedAbi, + }); + + return ResultAsync.fromPromise( + resolveMethod(methodName)(contract), + accountActionErrorMapper({ + code: "resolve_method_failed", + status: 400, + address: contractAddress, + chainId, + }), + ).andThen((abiFunction) => { + const parsedParams = parseAbiParams( + abiFunction.inputs.map((i) => i.type), + params, + ); + const preparedTx = prepareContractCall({ + contract, + // @ts-expect-error: sdk expected type appears to be broken + method: abiFunction, + params: parsedParams, + }); + return ResultAsync.fromPromise( + encode(preparedTx), + accountActionErrorMapper({ + code: "encode_transaction_failed", + address: contractAddress, + chainId, + }), + ).map( + (encodedData): PreparedMulticallItem => ({ + target: contractAddress, + allowFailure: true, + callData: encodedData, + abiFunction: abiFunction, + }), + ); + }); + }; + + const preparationResults = await processBatch( + transactionParams, + readPrepareProcessor, + ); + const firstError = preparationResults.find(isEngineErr); + if (firstError) { + throw engineErrToHttpException(firstError); + } + const preparedCalls = preparationResults as PreparedMulticallItem[]; + + const multicallContract = getContract({ + client, + chain, + address: multicallAddress, + }); + const multicallResult = await ResultAsync.fromPromise( + readContract({ + contract: multicallContract, + method: MULTICALL3_AGGREGATE3_ABI, + params: [preparedCalls], + }), + accountActionErrorMapper({ + code: "read_contract_failed", + status: 500, + address: multicallAddress, + chainId, + defaultMessage: "Multicall execution failed", + }), + ); + if (multicallResult.isErr()) { + throw engineErrToHttpException(multicallResult.error); + } + + const rawResults = multicallResult.value; + const decodedResults = rawResults.map((item, index) => { + const originalPreparedCall = preparedCalls[index]; + if (!originalPreparedCall) { + return { success: false, result: null }; + } + + const originalCallAbi = originalPreparedCall.abiFunction; + if (!item.success) { + return { success: false, result: null }; + } + try { + const outputs: readonly AbiParameter[] = originalCallAbi.outputs || []; + const decoded = decodeAbiParameters(outputs, item.returnData); + const finalResult = outputs.length === 1 ? decoded[0] : decoded; + return { success: true, result: finalResult }; + } catch { + return { success: false, result: null }; + } + }); + return c.json({ result: { results: decodedResults } }); + }, +); + +export const writeToContractRoute = onchainRoutesFactory.createHandlers( + validator("header", executionCredentialsHeadersSchema, zErrorMapper), + validator("json", writeRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Write"], + operationId: "writeContract", + summary: "Write Contract", + description: "Call a write function on a contract.", + responses: { + 200: { + description: "Transaction sent successfully", + content: { + "application/json": { + schema: resolver(transactionResponseSchema), + }, + }, + }, + 202: { + description: "Transaction queued successfully", + content: { + "application/json": { + schema: resolver(transactionResponseSchema), + }, + }, + }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const credentials = c.req.valid("header"); + + const { executionOptions, params: transactionParams } = body; + const { chainId } = executionOptions; + + const chainResult = getChainResult(chainId); + if (chainResult.isErr()) { + throw engineErrToHttpException(chainResult.error); + } + const chain = chainResult.value; + const overrideThirdwebClient = c.get("thirdwebClient"); + const client = overrideThirdwebClient ?? thirdwebClient; + + const transactions: { + to: Address; + data: Hex; + value: bigint; + }[] = []; + + for (const transactionParam of transactionParams) { + const { data } = Abi.safeParse(transactionParam.abi); + + const contract = getContract({ + client, + chain, + address: transactionParam.contractAddress, + abi: data, + }); + + const encodeResult = await ResultAsync.fromPromise( + resolveMethod(transactionParam.method)(contract), + accountActionErrorMapper({ + code: "resolve_method_failed", + defaultMessage: `Failed to resolve method ${transactionParam.method}`, + status: 500, + address: transactionParam.contractAddress, + chainId: chainId, + }), + ) + .map((method) => { + const params = parseAbiParams( + method.inputs.map((i) => i.type), + transactionParam.params, + ); + const methodSignature = AbiFunction.format(method); + + return prepareContractCall({ + contract, + method: methodSignature, + params, + }); + }) + .andThen((preparedTransaction) => + ResultAsync.fromPromise( + encode(preparedTransaction), + accountActionErrorMapper({ + code: "encode_transaction_failed", + defaultMessage: "Failed to encode transaction", + status: 500, + chainId: chainId, + address: transactionParam.contractAddress, + }), + ), + ) + .map((data) => { + transactions.push({ + to: transactionParam.contractAddress, + data: data, + value: transactionParam.value ?? 0n, + }); + }); + + if (encodeResult.isErr()) { + throw engineErrToHttpException(encodeResult.error); + } + } + + // Execute the transaction + const executionResult = await execute({ + client, + request: { + executionOptions, + params: transactions, + }, + credentials: { + ...credentialsFromHeaders(credentials), + ...getThirdwebCredentialsFromContext(c), + }, + }); + + if (executionResult.isErr()) { + throw engineErrToHttpException(executionResult.error); + } + + return c.json({ + result: { + transactions: executionResult.value.transactions, + }, + }); + }, +); diff --git a/src/server/routes/chain/factory.ts b/src/server/routes/chain/factory.ts new file mode 100644 index 000000000..bcaeedb0c --- /dev/null +++ b/src/server/routes/chain/factory.ts @@ -0,0 +1,11 @@ +import { createFactory } from "hono/factory"; +import type { ThirdwebClient } from "thirdweb"; + +export const onchainRoutesFactory = createFactory<{ + Variables: { + thirdwebClient?: ThirdwebClient; + thirdwebServiceKey?: string; + thirdwebClientId?: string; + thirdwebSecretKey?: string; + }; +}>(); diff --git a/src/server/routes/chain/get-all.ts b/src/server/routes/chain/get-all.ts deleted file mode 100644 index ae716658b..000000000 --- a/src/server/routes/chain/get-all.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { fetchChains } from "@thirdweb-dev/chains"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../shared/utils/cache/get-config"; -import { chainResponseSchema } from "../../schemas/chain"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(chainResponseSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - name: "Ethereum Mainnet", - chain: "ETH", - rpc: ["https://ethereum.rpc.thirdweb.com/$%7BTHIRDWEB_API_SECRET_KEY%7D"], - nativeCurrency: { - name: "Ether", - symbol: "ETH", - decimals: 18, - }, - shortName: "eth", - chainId: 1, - testnet: false, - slug: "ethereum", - }, - { - name: "Ropsten", - chain: "ETH", - rpc: ["https://ropsten.rpc.thirdweb.com/$%7BTHIRDWEB_API_SECRET_KEY%7D"], - nativeCurrency: { - name: "Ropsten Ether", - symbol: "ETH", - decimals: 18, - }, - shortName: "rop", - chainId: 3, - testnet: true, - slug: "ropsten", - }, - ], - }, -]; - -// LOGIC -export async function getAllChainData(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/chain/get-all", - schema: { - summary: "Get all chain details", - description: "Get details about all supported chains.", - tags: ["Chain"], - operationId: "listChains", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (_request, reply) => { - const allChains = (await fetchChains()) ?? []; - const config = await getConfig(); - - for (const chain of config.chainOverridesParsed) { - allChains.push({ - chainId: chain.id, - name: chain.name ?? "", - rpc: [...chain.rpc], - nativeCurrency: { - name: chain.nativeCurrency?.name ?? "Ether", - symbol: chain.nativeCurrency?.symbol ?? "ETH", - decimals: chain.nativeCurrency?.decimals ?? 18, - }, - testnet: chain.testnet ?? false, - chain: "", - shortName: "", - slug: "", - }); - } - - reply.status(StatusCodes.OK).send({ - result: allChains.map((chain) => ({ - ...chain, - rpc: [...chain.rpc], - })), - }); - }, - }); -} diff --git a/src/server/routes/chain/get.ts b/src/server/routes/chain/get.ts deleted file mode 100644 index d77f59710..000000000 --- a/src/server/routes/chain/get.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getChainMetadata } from "thirdweb/chains"; -import { getChain } from "../../../shared/utils/chain"; -import { - chainRequestQuerystringSchema, - chainResponseSchema, -} from "../../schemas/chain"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../utils/chain"; - -// OUTPUT -const responseSchema = Type.Object({ - result: chainResponseSchema, -}); - -responseSchema.examples = [ - { - result: { - name: "Polygon Amoy Testnet", - chain: "Polygon", - rpc: ["https://80002.rpc.thirdweb.com/$%7BTHIRDWEB_API_SECRET_KEY%7D"], - nativeCurrency: { - name: "MATIC", - symbol: "MATIC", - decimals: 18, - }, - shortName: "amoy", - chainId: 80002, - testnet: true, - slug: "polygon-amoy-testnet", - }, - }, -]; - -// LOGIC -export async function getChainData(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/chain/get", - schema: { - summary: "Get chain details", - description: "Get details about a chain.", - tags: ["Chain"], - operationId: "getChain", - querystring: chainRequestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.query; - - const chainId = await getChainIdFromChain(chain); - const chainV5 = await getChain(chainId); - const chainMetadata = await getChainMetadata(chainV5); - - reply.status(StatusCodes.OK).send({ - result: { - ...chainMetadata, - rpc: [...chainMetadata.rpc], - }, - }); - }, - }); -} diff --git a/src/server/routes/chain/index.ts b/src/server/routes/chain/index.ts new file mode 100644 index 000000000..71769718e --- /dev/null +++ b/src/server/routes/chain/index.ts @@ -0,0 +1,34 @@ +import { Hono } from "hono"; +import { thirdwebClientMiddleware } from "../../middleware/thirdweb-client.js"; +import { sendTransactionRoute } from "./transaction.js"; +import { + encodeFunctionDataRoute, + readFromContractRoute, + writeToContractRoute, +} from "./contract.js"; +import { getNativeBalanceRoute } from "./balance.js"; +import { + signMessageRoute, + signTransactionRoute, + signTypedDataRoute, +} from "./sign.js"; + +export const chainActionsRouter = new Hono(); + +chainActionsRouter.use(thirdwebClientMiddleware); + +// write routes +chainActionsRouter.post("/write/transaction", ...sendTransactionRoute); +chainActionsRouter.post("/write/contract", ...writeToContractRoute); + +// read routes +chainActionsRouter.post("/read/contract", ...readFromContractRoute); +chainActionsRouter.post("/read/balance", ...getNativeBalanceRoute); + +// encode routes +chainActionsRouter.post("/encode/contract", ...encodeFunctionDataRoute); + +// sign routes +chainActionsRouter.post("/sign/transaction", ...signTransactionRoute); +chainActionsRouter.post("/sign/message", ...signMessageRoute); +chainActionsRouter.post("/sign/typed-data", ...signTypedDataRoute); diff --git a/src/server/routes/chain/sign.ts b/src/server/routes/chain/sign.ts new file mode 100644 index 000000000..216e25bad --- /dev/null +++ b/src/server/routes/chain/sign.ts @@ -0,0 +1,598 @@ +import { TypedDataDomain, TypedDataParameter } from "abitype/zod"; +import { describeRoute } from "hono-openapi"; +import { resolver, validator } from "hono-openapi/zod"; +import { ok, ResultAsync, safeTry } from "neverthrow"; +import { + type Chain, + type Hex, + prepareTransaction, + type ThirdwebClient, + toSerializableTransaction, +} from "thirdweb"; +import type { Account } from "thirdweb/wallets"; +import { smartWallet } from "thirdweb/wallets"; +import * as z from "zod"; +import { + type ExecutionCredentials, + getExecutionAccountFromRequest, +} from "../../../executors/execute/execute.js"; +import { + bigIntSchema, + buildExecutionRequestSchema, + type EncodedExecutionRequest, +} from "../../../executors/types.js"; +import { getChainResult } from "../../../lib/chain.js"; +import { + accountActionErrorMapper, + type EngineErr, + engineErrToHttpException, + getDefaultErrorMessage, + type RpcErr, + zErrorMapper, +} from "../../../lib/errors.js"; +import { thirdwebClient } from "../../../lib/thirdweb-client.js"; +import { evmAddressSchema, hexSchema } from "../../../lib/zod.js"; +import { getThirdwebCredentialsFromContext } from "../../middleware/thirdweb-client.js"; +import { + credentialsFromHeaders, + executionCredentialsHeadersSchema, + wrapResponseSchema, +} from "../../schemas/shared-api-schemas.js"; +import { onchainRoutesFactory } from "./factory.js"; + +// --- Schema Definitions --- + +// 1. Sign Transaction Schemas +const transactionSignatureParamsSchema = z.object({ + to: evmAddressSchema.describe("The recipient address"), + data: hexSchema.describe("The transaction data as hex").default("0x"), + value: bigIntSchema + .describe("The value to send with the transaction") + .optional(), + nonce: z.number().int().positive().optional().describe("Transaction nonce"), + gasLimit: bigIntSchema.optional().describe("Gas limit"), + gasPrice: bigIntSchema + .optional() + .describe("Gas price (for legacy transactions)"), + maxFeePerGas: bigIntSchema + .optional() + .describe("Max fee per gas (for EIP-1559)"), + maxPriorityFeePerGas: bigIntSchema + .optional() + .describe("Max priority fee per gas (for EIP-1559)"), + accessList: z + .array( + z.object({ + address: evmAddressSchema, + storageKeys: z.array(hexSchema), + }), + ) + .optional() + .describe("Access list for EIP-2930 and later transactions"), + // type: z + // .enum(["0x00", "0x01", "0x02", "0x03", "0x05"]) + // .optional() + // .describe( + // "Transaction type (legacy, EIP-2930, EIP-1559, EIP-4844, EIP-7702)", + // ), + // EIP-4844 specific fields + maxFeePerBlobGas: bigIntSchema + .optional() + .describe("Max fee per blob gas (for EIP-4844)"), + blobVersionedHashes: z + .array(hexSchema) + .optional() + .describe("Blob versioned hashes (for EIP-4844)"), + // EIP-7702 specific fields + authorizationList: z + .array( + z.object({ + address: evmAddressSchema.describe("Authorization address"), + r: bigIntSchema.describe("r value of the signature"), + s: bigIntSchema.describe("s value of the signature"), + v: z + .union([z.number(), z.string()]) + .optional() + .describe("v value of the signature"), + yParity: z.number().describe("yParity value (0 or 1)"), + nonce: bigIntSchema.describe("Authorization nonce"), + chainId: z.number().int().positive().describe("Authorization chainId"), + }), + ) + .optional() + .describe("Authorization list (for EIP-7702)"), +}); + +const signTransactionRequestSchema = buildExecutionRequestSchema( + z.array(transactionSignatureParamsSchema), +); + +const signatureDataSchema = z.object({ + signature: hexSchema.describe("The resulting signature"), + signedData: hexSchema.optional().describe("Optional signed data"), +}); + +const signSuccessItemSchema = z.object({ + success: z.literal(true), + result: signatureDataSchema, +}); + +const signErrorSchema = z + .object({ + kind: z.string(), + code: z.string(), + status: z.number(), + message: z.string().optional(), + address: evmAddressSchema.optional(), + chainId: z.string().optional(), + }) + .describe("Standardized error object"); + +const signErrorItemSchema = z.object({ + success: z.literal(false), + error: signErrorSchema, +}); + +const signResultItemSchema = z.union([ + signSuccessItemSchema, + signErrorItemSchema, +]); + +const signResponseSchema = wrapResponseSchema( + z.object({ results: z.array(signResultItemSchema) }), +); + +type SignSuccessItem = z.infer; +type SignErrorItem = z.infer; + +// 2. Sign Message Schemas +const messageSignatureParamsSchema = z.object({ + message: z.string().describe("The message to sign"), + messageFormat: z + .enum(["text", "hex"]) + .default("text") + .describe("Format of the message (text or hex)"), +}); + +const signMessageRequestSchema = buildExecutionRequestSchema( + z.array(messageSignatureParamsSchema), +); + +// 3. Sign Typed Data Schemas +const typedDataSignatureParamsSchema = z + .object({ + domain: TypedDataDomain, + types: z.record(z.string(), z.array(TypedDataParameter)), + primaryType: z.string(), + message: z.record(z.string(), z.any()), + }) + .describe("The EIP-712 typed data structure"); + +const signTypedDataRequestSchema = buildExecutionRequestSchema( + z.array(typedDataSignatureParamsSchema), +); + +/** + * Processes a batch of items asynchronously, handling individual errors using neverthrow. + * + * @param items - The array of input items to process. + * @param processorFn - An async function that processes a single item and returns a ResultAsync. + * @returns A Promise resolving to an array containing either success results or error objects. + */ +async function processBatch( + items: TInput[], + processorFn: (item: TInput) => ResultAsync, +): Promise> { + const processingPromises = items.map((item) => processorFn(item)); + + const settledResults = await Promise.all(processingPromises); + + return settledResults.map((result) => { + return result.match( + (successData) => successData, + (errorData) => errorData, + ); + }); +} + +// Helper to get the correct signing account based on the request +function getSigningAccount({ + request, + credentials, + client, + chain, +}: { + request: EncodedExecutionRequest; + credentials: ExecutionCredentials; + client: ThirdwebClient; + chain: Chain; +}): ResultAsync { + return safeTry(async function* () { + const accountResult = yield* getExecutionAccountFromRequest({ + request, + credentials, + client, + }); + + switch (accountResult.type) { + case "EOA": { + return ok(accountResult.account); + } + case "zksync": { + return ok(accountResult.zkEoaAccount); + } + case "ERC4337": { + const { signerAccount, smartAccountDetails } = accountResult; + + // Handle the async import and connection with ResultAsync.fromPromise + // Configure the smart wallet with the details from the request + const wallet = smartWallet({ + chain, + factoryAddress: smartAccountDetails.factoryAddress, + overrides: { + entrypointAddress: smartAccountDetails.entrypointAddress, + accountAddress: smartAccountDetails.address, + accountSalt: smartAccountDetails.accountSalt ?? undefined, + }, + sponsorGas: + "sponsorGas" in request.executionOptions + ? request.executionOptions.sponsorGas + : true, + }); + + // Connect the smart wallet using the signer account + const smartAccountResult = ResultAsync.fromPromise( + wallet.connect({ + client, + personalAccount: signerAccount, + }), + accountActionErrorMapper({ + code: "smart_account_determination_failed", + defaultMessage: "Failed to connect smart account", + status: 500, + address: smartAccountDetails.address, + chainId: request.executionOptions.chainId, + }), + ); + return ok(yield* smartAccountResult); + } + } + }); +} + +// --- Route Handlers --- + +// 1. Sign Transaction (Batch) Handler +export const signTransactionRoute = onchainRoutesFactory.createHandlers( + validator("header", executionCredentialsHeadersSchema, zErrorMapper), + validator("json", signTransactionRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Sign"], + operationId: "signTransaction", + summary: "Sign Transaction", + description: "Sign transactions without sending them.", + responses: { + 200: { + description: "OK", + content: { + "application/json": { schema: resolver(signResponseSchema) }, + }, + }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const credentials = c.req.valid("header"); + const { params: transactionParams, executionOptions } = body; + const { chainId } = executionOptions; + + const overrideThirdwebClient = c.get("thirdwebClient"); + const chainResult = getChainResult(chainId); + if (chainResult.isErr()) { + throw engineErrToHttpException(chainResult.error); + } + const chain = chainResult.value; + const effectiveThirdwebClient = overrideThirdwebClient ?? thirdwebClient; + + // Get the account for signing + const accountResult = await getSigningAccount({ + request: body as EncodedExecutionRequest, + client: effectiveThirdwebClient, + chain, + credentials: { + ...credentialsFromHeaders(credentials), + ...getThirdwebCredentialsFromContext(c), + }, + }); + + if (accountResult.isErr()) { + throw engineErrToHttpException(accountResult.error); + } + const signingAccount = accountResult.value; + + if (!signingAccount.signTransaction) { + throw engineErrToHttpException({ + code: "sign_transaction_failed", + kind: "rpc", + message: + "Underlying signing account does not support transaction signing", + status: 500, + chainId: chainId, + } as RpcErr); + } + + const signTransactionMethod = + signingAccount.signTransaction.bind(signingAccount); + + const signProcessor = ( + transactionParam: z.infer, + ): ResultAsync => { + return safeTry(async function* () { + const preparedTransaction = prepareTransaction({ + chain, + client: effectiveThirdwebClient, + ...transactionParam, + }); + + const serializableTransaction = yield* ResultAsync.fromPromise( + toSerializableTransaction({ + transaction: preparedTransaction, + from: signingAccount.address, + }), + accountActionErrorMapper({ + code: "serialize_transaction_failed", + defaultMessage: "Failed to serialize transaction", + status: 400, + chainId: chainId, + }), + ); + + const signature = yield* ResultAsync.fromPromise( + signTransactionMethod(serializableTransaction), + accountActionErrorMapper({ + code: "sign_transaction_failed", + defaultMessage: "Failed to sign transaction", + status: 500, + chainId: chainId, + }), + ); + + return ok({ + success: true, + result: { + signature, + }, + } as SignSuccessItem); + }).mapErr((engineErr) => { + return { + success: false, + error: { + ...engineErr, + message: engineErr.message ?? getDefaultErrorMessage(engineErr), + }, + } as SignErrorItem; + }); + }; + + // Process the batch using the abstraction + const results = await processBatch(transactionParams, signProcessor); + + return c.json({ result: { results } }); + }, +); + +// 2. Sign Message (Batch) Handler +export const signMessageRoute = onchainRoutesFactory.createHandlers( + validator("header", executionCredentialsHeadersSchema, zErrorMapper), + validator("json", signMessageRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Sign"], + operationId: "signMessage", + summary: "Sign Message", + description: "Sign arbitrary messages.", + responses: { + 200: { + description: "OK", + content: { + "application/json": { schema: resolver(signResponseSchema) }, + }, + }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const credentials = c.req.valid("header"); + + const { params: transactionParams, executionOptions } = body; + const { chainId } = executionOptions; + + const chainResult = getChainResult(chainId); + if (chainResult.isErr()) { + throw engineErrToHttpException(chainResult.error); + } + const chain = chainResult.value; + + const overrideThirdwebClient = c.get("thirdwebClient"); + const effectiveThirdwebClient = overrideThirdwebClient ?? thirdwebClient; + + // Get the account for signing + const accountResult = await getSigningAccount({ + request: body as EncodedExecutionRequest, + client: effectiveThirdwebClient, + credentials: { + ...credentialsFromHeaders(credentials), + ...getThirdwebCredentialsFromContext(c), + }, + chain, + }); + if (accountResult.isErr()) { + throw engineErrToHttpException(accountResult.error); + } + const signingAccount = accountResult.value; + + if (!signingAccount.signMessage) { + throw engineErrToHttpException({ + code: "sign_message_failed", + kind: "rpc", + message: "Underlying signing account does not support messaage signing", + status: 500, + chainId: chainId, + } as RpcErr); + } + const signMessageMethod = signingAccount.signMessage.bind(signingAccount); + + const signMessageProcessor = ( + messageParam: z.infer, + ): ResultAsync => { + return safeTry(async function* () { + const { message, messageFormat } = messageParam; + + // Convert to the appropriate SignableMessage type based on format + const signableMessage = + messageFormat === "hex" ? { raw: message as Hex } : message; + + const signature = yield* ResultAsync.fromPromise( + signMessageMethod({ message: signableMessage, chainId: chain.id }), + accountActionErrorMapper({ + code: "sign_message_failed", + defaultMessage: "Failed to sign message", + status: 500, + chainId: chainId, + }), + ); + + return ok({ + success: true, + result: { + signature, + signedData: typeof message === "string" ? message : undefined, + }, + } as SignSuccessItem); + }).mapErr((engineErr) => { + return { + success: false, + error: { + ...engineErr, + message: engineErr.message ?? getDefaultErrorMessage(engineErr), + }, + } as SignErrorItem; + }); + }; + + // Process the batch using the abstraction + const results = await processBatch(transactionParams, signMessageProcessor); + + return c.json({ result: { results } }); + }, +); + +// 3. Sign Typed Data (Batch) Handler +export const signTypedDataRoute = onchainRoutesFactory.createHandlers( + validator("header", executionCredentialsHeadersSchema, zErrorMapper), + validator("json", signTypedDataRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Sign"], + operationId: "signTypedData", + summary: "Sign Typed Data", + description: "Sign EIP-712 typed data.", + responses: { + 200: { + description: "OK", + content: { + "application/json": { schema: resolver(signResponseSchema) }, + }, + }, + }, + }), + async (c) => { + const body = c.req.valid("json"); + const credentials = c.req.valid("header"); + + const { params: transactionParams, executionOptions } = body; + const { chainId } = executionOptions; + + const chainResult = getChainResult(chainId); + if (chainResult.isErr()) { + throw engineErrToHttpException(chainResult.error); + } + const chain = chainResult.value; + + const overrideThirdwebClient = c.get("thirdwebClient"); + const effectiveThirdwebClient = overrideThirdwebClient ?? thirdwebClient; + + // Get the account for signing + const accountResult = await getSigningAccount({ + request: body as EncodedExecutionRequest, + client: effectiveThirdwebClient, + credentials: { + ...credentialsFromHeaders(credentials), + ...getThirdwebCredentialsFromContext(c), + }, + chain, + }); + if (accountResult.isErr()) { + throw engineErrToHttpException(accountResult.error); + } + const signingAccount = accountResult.value; + + if (!signingAccount.signTypedData) { + throw engineErrToHttpException({ + code: "sign_typed_data_failed", + kind: "rpc", + message: "Underlying signing account does not support EIP712 signing", + status: 500, + chainId: chainId, + } as RpcErr); + } + + const signTypedDataMethod = + signingAccount.signTypedData.bind(signingAccount); + + const signTypedDataProcessor = ( + typedData: z.infer, + ): ResultAsync => { + return safeTry(async function* () { + const { domain, types, primaryType, message } = typedData; + + const signature = yield* ResultAsync.fromPromise( + signTypedDataMethod({ + // @ts-expect-error - SDK type does not match abitype zod schema + domain, + types, + primaryType, + message, + }), + accountActionErrorMapper({ + code: "sign_typed_data_failed", + defaultMessage: "Failed to sign typed data", + status: 500, + chainId: chainId, + }), + ); + + return ok({ + success: true, + result: { + signature, + }, + } as SignSuccessItem); + }).mapErr((engineErr) => { + return { + success: false, + error: { + ...engineErr, + message: engineErr.message ?? getDefaultErrorMessage(engineErr), + }, + } as SignErrorItem; + }); + }; + + // Process the batch using the abstraction + const results = await processBatch( + transactionParams, + signTypedDataProcessor, + ); + + return c.json({ result: { results } }); + }, +); diff --git a/src/server/routes/chain/transaction.ts b/src/server/routes/chain/transaction.ts new file mode 100644 index 000000000..10a8c00e1 --- /dev/null +++ b/src/server/routes/chain/transaction.ts @@ -0,0 +1,74 @@ +import { describeRoute } from "hono-openapi"; +import { resolver, validator } from "hono-openapi/zod"; +import { execute } from "../../../executors/execute/execute.js"; +import { + encodedExecutionRequestSchema, + transactionResponseSchema, +} from "../../../executors/types.js"; +import { engineErrToHttpException, zErrorMapper } from "../../../lib/errors.js"; +import { thirdwebClient } from "../../../lib/thirdweb-client.js"; +import { getThirdwebCredentialsFromContext } from "../../middleware/thirdweb-client.js"; +import { + credentialsFromHeaders, + executionCredentialsHeadersSchema, +} from "../../schemas/shared-api-schemas.js"; +import { onchainRoutesFactory } from "./factory.js"; + +export const sendTransactionRoute = onchainRoutesFactory.createHandlers( + validator("header", executionCredentialsHeadersSchema, zErrorMapper), + validator("json", encodedExecutionRequestSchema, zErrorMapper), + describeRoute({ + tags: ["Write"], + operationId: "sendTransaction", + summary: "Send Transaction", + description: "Send an encoded transaction or a batch of transactions", + responses: { + 200: { + description: "Transaction sent successfully", + content: { + "application/json": { + schema: resolver(transactionResponseSchema), + }, + }, + }, + 202: { + description: "Transaction queued successfully", + content: { + "application/json": { + schema: resolver(transactionResponseSchema), + }, + }, + }, + }, + }), + async (c) => { + const executionRequest = c.req.valid("json"); + const credentials = c.req.valid("header"); + + const overrideThirdwebClient = c.get("thirdwebClient"); + + if (overrideThirdwebClient) { + console.log("found override"); + console.log(overrideThirdwebClient.clientId); + } + + const executionResult = await execute({ + client: overrideThirdwebClient ?? thirdwebClient, + request: executionRequest, + credentials: { + ...credentialsFromHeaders(credentials), + ...getThirdwebCredentialsFromContext(c), + }, + }); + + if (executionResult.isErr()) { + throw engineErrToHttpException(executionResult.error); + } + + return c.json({ + result: { + transactions: executionResult.value.transactions, + }, + }); + }, +); diff --git a/src/server/routes/configuration/auth/get.ts b/src/server/routes/configuration/auth/get.ts deleted file mode 100644 index 115964dba..000000000 --- a/src/server/routes/configuration/auth/get.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - authDomain: Type.String(), - mtlsCertificate: Type.Union([Type.String(), Type.Null()]), - // Do not return mtlsPrivateKey. - }), -}); - -export async function getAuthConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/auth", - schema: { - summary: "Get auth configuration", - description: "Get auth configuration", - tags: ["Configuration"], - operationId: "getAuthConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const { authDomain, mtlsCertificate } = await getConfig(); - - res.status(StatusCodes.OK).send({ - result: { - authDomain, - mtlsCertificate, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/auth/update.ts b/src/server/routes/configuration/auth/update.ts deleted file mode 100644 index 3a1243679..000000000 --- a/src/server/routes/configuration/auth/update.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { responseBodySchema } from "./get"; -import { createCustomError } from "../../../middleware/error"; -import { encrypt } from "../../../../shared/utils/crypto"; - -export const requestBodySchema = Type.Partial( - Type.Object({ - authDomain: Type.String(), - mtlsCertificate: Type.String({ - description: - "Engine certificate used for outbound mTLS requests. Must provide the full certificate chain.", - }), - mtlsPrivateKey: Type.String({ - description: "Engine private key used for outbound mTLS requests.", - }), - }), -); - -export async function updateAuthConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/configuration/auth", - schema: { - summary: "Update auth configuration", - description: "Update auth configuration", - tags: ["Configuration"], - operationId: "updateAuthConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { authDomain, mtlsCertificate, mtlsPrivateKey } = req.body; - - if (mtlsCertificate) { - if ( - !mtlsCertificate.includes("-----BEGIN CERTIFICATE-----\n") || - !mtlsCertificate.includes("\n-----END CERTIFICATE-----") - ) { - throw createCustomError( - "Invalid mtlsCertificate.", - StatusCodes.BAD_REQUEST, - "INVALID_MTLS_CERTIFICATE", - ); - } - } - if (mtlsPrivateKey) { - if ( - !mtlsPrivateKey.startsWith("-----BEGIN PRIVATE KEY-----\n") || - !mtlsPrivateKey.endsWith("\n-----END PRIVATE KEY-----") - ) { - throw createCustomError( - "Invalid mtlsPrivateKey.", - StatusCodes.BAD_REQUEST, - "INVALID_MTLS_PRIVATE_KEY", - ); - } - } - - await updateConfiguration({ - authDomain, - mtlsCertificateEncrypted: mtlsCertificate - ? encrypt(mtlsCertificate) - : undefined, - mtlsPrivateKeyEncrypted: mtlsPrivateKey - ? encrypt(mtlsPrivateKey) - : undefined, - }); - - const config = await getConfig(false); - - res.status(StatusCodes.OK).send({ - result: { - authDomain: config.authDomain, - mtlsCertificate: config.mtlsCertificate, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/backend-wallet-balance/get.ts b/src/server/routes/configuration/backend-wallet-balance/get.ts deleted file mode 100644 index 59aa13d51..000000000 --- a/src/server/routes/configuration/backend-wallet-balance/get.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - minWalletBalance: Type.String({ - description: "Minimum wallet balance in wei", - }), - }), -}); - -export async function getBackendWalletBalanceConfiguration( - fastify: FastifyInstance, -) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/backend-wallet-balance", - schema: { - summary: "Get wallet-balance configuration", - description: "Get wallet-balance configuration", - tags: ["Configuration"], - operationId: "getBackendWalletBalanceConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(); - res.status(StatusCodes.OK).send({ - result: { - minWalletBalance: config.minWalletBalance, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/backend-wallet-balance/update.ts b/src/server/routes/configuration/backend-wallet-balance/update.ts deleted file mode 100644 index 842fef403..000000000 --- a/src/server/routes/configuration/backend-wallet-balance/update.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { WeiAmountStringSchema } from "../../../schemas/number"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Partial( - Type.Object({ - minWalletBalance: { - ...WeiAmountStringSchema, - description: "Minimum wallet balance in wei", - }, - }), -); - -export async function updateBackendWalletBalanceConfiguration( - fastify: FastifyInstance, -) { - fastify.route<{ - Body: Static; - }>({ - method: "POST", - url: "/configuration/backend-wallet-balance", - schema: { - summary: "Update backend wallet balance configuration", - description: "Update backend wallet balance configuration", - tags: ["Configuration"], - operationId: "updateBackendWalletBalanceConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - await updateConfiguration({ ...req.body }); - const config = await getConfig(false); - - res.status(StatusCodes.OK).send({ - result: { - minWalletBalance: config.minWalletBalance, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/cache/get.ts b/src/server/routes/configuration/cache/get.ts deleted file mode 100644 index 9f55c7114..000000000 --- a/src/server/routes/configuration/cache/get.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - clearCacheCronSchedule: Type.String(), - }), -}); - -export async function getCacheConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/cache", - schema: { - summary: "Get cache configuration", - description: "Get cache configuration", - tags: ["Configuration"], - operationId: "getCacheConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(); - res.status(StatusCodes.OK).send({ - result: { - clearCacheCronSchedule: config.clearCacheCronSchedule, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/cache/update.ts b/src/server/routes/configuration/cache/update.ts deleted file mode 100644 index 5ea2c035e..000000000 --- a/src/server/routes/configuration/cache/update.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { clearCacheCron } from "../../../../shared/utils/cron/clear-cache-cron"; -import { isValidCron } from "../../../../shared/utils/cron/is-valid-cron"; -import { createCustomError } from "../../../middleware/error"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Object({ - clearCacheCronSchedule: Type.String({ - description: - "Cron expression for clearing cache. It should be in the format of 'ss mm hh * * *' where ss is seconds, mm is minutes and hh is hours. Seconds should not be '*' or less than 10", - default: "*/30 * * * * *", - }), -}); - -export async function updateCacheConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - }>({ - method: "POST", - url: "/configuration/cache", - schema: { - summary: "Update cache configuration", - description: "Update cache configuration", - tags: ["Configuration"], - operationId: "updateCacheConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { clearCacheCronSchedule } = req.body; - if (isValidCron(clearCacheCronSchedule) === false) { - throw createCustomError( - "Invalid cron expression.", - StatusCodes.BAD_REQUEST, - "INVALID_CRON", - ); - } - - await updateConfiguration({ ...req.body }); - const config = await getConfig(false); - // restarting cache cron with updated cron schedule - await clearCacheCron("server"); - res.status(StatusCodes.OK).send({ - result: { - clearCacheCronSchedule: config.clearCacheCronSchedule, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/chains/get.ts b/src/server/routes/configuration/chains/get.ts deleted file mode 100644 index 9c0226bdf..000000000 --- a/src/server/routes/configuration/chains/get.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { chainResponseSchema } from "../../../schemas/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Array(chainResponseSchema), -}); - -export async function getChainsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/chains", - schema: { - summary: "Get chain overrides configuration", - description: "Get chain overrides configuration", - tags: ["Configuration"], - operationId: "getChainsConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(); - const result: Static[] = config.chainOverrides - ? JSON.parse(config.chainOverrides) - : []; - - res.status(StatusCodes.OK).send({ result }); - }, - }); -} diff --git a/src/server/routes/configuration/chains/update.ts b/src/server/routes/configuration/chains/update.ts deleted file mode 100644 index ab053a5b9..000000000 --- a/src/server/routes/configuration/chains/update.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { sdkCache } from "../../../../shared/utils/cache/get-sdk"; -import { chainResponseSchema } from "../../../schemas/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Object({ - chainOverrides: Type.Array(chainResponseSchema), -}); - -requestBodySchema.examples = [ - { - chainOverrides: [ - { - name: "Localhost", - chain: "ETH", - rpc: ["http://localhost:8545/"], - nativeCurrency: { - name: "Ether", - symbol: "ETH", - decimals: 18, - }, - chainId: 1337, - slug: "localhost", - }, - ], - }, -]; - -export async function updateChainsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/configuration/chains", - schema: { - summary: "Update chain overrides configuration", - description: "Update chain overrides configuration", - tags: ["Configuration"], - operationId: "updateChainsConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - await updateConfiguration({ - chainOverrides: JSON.stringify(req.body.chainOverrides), - }); - - const config = await getConfig(false); - const result: Static[] = config.chainOverrides - ? JSON.parse(config.chainOverrides) - : []; - - sdkCache.clear(); - res.status(StatusCodes.OK).send({ result }); - }, - }); -} diff --git a/src/server/routes/configuration/contract-subscriptions/get.ts b/src/server/routes/configuration/contract-subscriptions/get.ts deleted file mode 100644 index 624e08084..000000000 --- a/src/server/routes/configuration/contract-subscriptions/get.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { - contractSubscriptionConfigurationSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; - -const responseSchema = Type.Object({ - result: contractSubscriptionConfigurationSchema, -}); - -export async function getContractSubscriptionsConfiguration( - fastify: FastifyInstance, -) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/contract-subscriptions", - schema: { - summary: "Get Contract Subscriptions configuration", - description: "Get the configuration for Contract Subscriptions", - tags: ["Configuration"], - operationId: "getContractSubscriptionsConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(); - res.status(StatusCodes.OK).send({ - result: { - maxBlocksToIndex: config.maxBlocksToIndex, - contractSubscriptionsRequeryDelaySeconds: - config.contractSubscriptionsRequeryDelaySeconds, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/contract-subscriptions/update.ts b/src/server/routes/configuration/contract-subscriptions/update.ts deleted file mode 100644 index ee971de01..000000000 --- a/src/server/routes/configuration/contract-subscriptions/update.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { createCustomError } from "../../../middleware/error"; -import { - contractSubscriptionConfigurationSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - maxBlocksToIndex: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })), - contractSubscriptionsRequeryDelaySeconds: Type.Optional( - Type.String({ - description: `Requery after one or more delays. Use comma-separated positive integers. Example: "2,10" means requery after 2s and 10s.`, - }), - ), -}); - -const responseSchema = Type.Object({ - result: contractSubscriptionConfigurationSchema, -}); - -export async function updateContractSubscriptionsConfiguration( - fastify: FastifyInstance, -) { - fastify.route<{ - Body: Static; - }>({ - method: "POST", - url: "/configuration/contract-subscriptions", - schema: { - summary: "Update Contract Subscriptions configuration", - description: "Update the configuration for Contract Subscriptions", - tags: ["Configuration"], - operationId: "updateContractSubscriptionsConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, res) => { - const { maxBlocksToIndex, contractSubscriptionsRequeryDelaySeconds } = - req.body; - - if (!maxBlocksToIndex && !contractSubscriptionsRequeryDelaySeconds) { - throw createCustomError( - "At least one parameter is required", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - if (contractSubscriptionsRequeryDelaySeconds) { - try { - for (const delayStr of contractSubscriptionsRequeryDelaySeconds.split( - ",", - )) { - const delayInt = Number.parseInt(delayStr); - if (Number.isNaN(delayInt) || delayInt <= 0) { - throw `Invalid delay value. Use comma-separated positive integers: "2,10"`; - } - } - } catch { - throw createCustomError( - 'At least one integer "contractSubscriptionsRequeryDelaySeconds" is required', - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - } - - await updateConfiguration({ - maxBlocksToIndex, - contractSubscriptionsRetryDelaySeconds: - contractSubscriptionsRequeryDelaySeconds, - }); - const config = await getConfig(false); - - res.status(StatusCodes.OK).send({ - result: { - maxBlocksToIndex: config.maxBlocksToIndex, - contractSubscriptionsRequeryDelaySeconds: - config.contractSubscriptionsRequeryDelaySeconds, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/cors/add.ts b/src/server/routes/configuration/cors/add.ts deleted file mode 100644 index e8a0d6a3d..000000000 --- a/src/server/routes/configuration/cors/add.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { mandatoryAllowedCorsUrls } from "../../../utils/cors-urls"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Object({ - urlsToAdd: Type.Array( - Type.String({ - description: "Comma separated list of origins that will call Engine", - minLength: 1, - }), - ), -}); - -requestBodySchema.examples = [ - { - urlsToAdd: ["https://example.com/", "https://subdomain.example.com/"], - }, -]; - -export async function addUrlToCorsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/configuration/cors", - schema: { - summary: "Add a CORS URL", - description: "Add a URL to allow client-side calls to Engine", - tags: ["Configuration"], - operationId: "addUrlToCorsConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const oldConfig = await getConfig(); - - const urlsToAdd = req.body.urlsToAdd.map((url) => url.trim()); - - const requiredUrls = mandatoryAllowedCorsUrls; - - for (const url of requiredUrls) { - if (!urlsToAdd.includes(url)) { - urlsToAdd.push(url); - } - } - - await updateConfiguration({ - accessControlAllowOrigin: [ - ...new Set([ - ...urlsToAdd, - ...oldConfig.accessControlAllowOrigin.split(","), - ]), - ].join(","), - }); - - // Fetch and return the updated configuration - const config = await getConfig(false); - res.status(StatusCodes.OK).send({ - result: config.accessControlAllowOrigin.split(","), - }); - }, - }); -} diff --git a/src/server/routes/configuration/cors/get.ts b/src/server/routes/configuration/cors/get.ts deleted file mode 100644 index 0dc380626..000000000 --- a/src/server/routes/configuration/cors/get.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { mandatoryAllowedCorsUrls } from "../../../utils/cors-urls"; - -export const responseBodySchema = Type.Object({ - result: Type.Array(Type.String()), -}); - -export async function getCorsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/cors", - schema: { - summary: "Get CORS configuration", - description: "Get CORS configuration", - tags: ["Configuration"], - operationId: "getCorsConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(false); - - // Omit required domains. - const omitted = config.accessControlAllowOrigin - .split(",") - .filter((url) => !mandatoryAllowedCorsUrls.includes(url)); - - res.status(StatusCodes.OK).send({ - result: omitted, - }); - }, - }); -} diff --git a/src/server/routes/configuration/cors/remove.ts b/src/server/routes/configuration/cors/remove.ts deleted file mode 100644 index 35f3edec4..000000000 --- a/src/server/routes/configuration/cors/remove.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { createCustomError } from "../../../middleware/error"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { mandatoryAllowedCorsUrls } from "../../../utils/cors-urls"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Object({ - urlsToRemove: Type.Array( - Type.String({ - description: "Comma separated list of origins to remove", - }), - ), -}); - -requestBodySchema.examples = [ - { - urlsToRemove: ["https://example.com/", "https://subdomain.example.com/"], - }, -]; - -export async function removeUrlToCorsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "DELETE", - url: "/configuration/cors", - schema: { - summary: "Remove CORS URLs", - description: "Remove URLs from CORS configuration", - tags: ["Configuration"], - operationId: "removeUrlToCorsConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const currentConfig = await getConfig(); - - const urlsToRemove = req.body.urlsToRemove.map((url) => url.trim()); - - // Check for mandatory URLs - const containsMandatoryUrl = urlsToRemove.some((url) => - mandatoryAllowedCorsUrls.includes(url), - ); - if (containsMandatoryUrl) { - throw createCustomError( - `Cannot remove URLs: ${mandatoryAllowedCorsUrls.join(",")}`, - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - // Filter out URLs to be removed - const newAllowOriginsList = currentConfig.accessControlAllowOrigin - .split(",") - .map((url) => url.trim()) - .filter((url) => !urlsToRemove.includes(url)); - - await updateConfiguration({ - accessControlAllowOrigin: [...new Set([...newAllowOriginsList])].join( - ",", - ), - }); - - // Fetch and return the updated configuration - const newConfig = await getConfig(false); - res - .status(StatusCodes.OK) - .send({ result: newConfig.accessControlAllowOrigin.split(",") }); - }, - }); -} diff --git a/src/server/routes/configuration/cors/set.ts b/src/server/routes/configuration/cors/set.ts deleted file mode 100644 index 529a35111..000000000 --- a/src/server/routes/configuration/cors/set.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { mandatoryAllowedCorsUrls } from "../../../utils/cors-urls"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Object({ - urls: Type.Array( - Type.String({ - description: "Comma separated list of origins that will call Engine", - minLength: 1, - }), - ), -}); - -requestBodySchema.examples = [ - { - urls: ["https://example.com/", "https://subdomain.example.com/"], - }, -]; - -export async function setUrlsToCorsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "PUT", - url: "/configuration/cors", - schema: { - summary: "Set CORS URLs", - description: - "Replaces the CORS URLs to allow client-side calls to Engine", - tags: ["Configuration"], - operationId: "setUrlsToCorsConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const urls = req.body.urls.map((url) => url.trim()); - - // Add required domains and dedupe. - const dedupe = Array.from( - new Set([...urls, ...mandatoryAllowedCorsUrls]), - ); - - await updateConfiguration({ - accessControlAllowOrigin: dedupe.join(","), - }); - - // Fetch and return the updated configuration - const config = await getConfig(false); - res.status(StatusCodes.OK).send({ - result: config.accessControlAllowOrigin.split(","), - }); - }, - }); -} diff --git a/src/server/routes/configuration/ip/get.ts b/src/server/routes/configuration/ip/get.ts deleted file mode 100644 index 2e8a3a2f4..000000000 --- a/src/server/routes/configuration/ip/get.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Array(Type.String()), -}); - -export async function getIpAllowlist(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/ip-allowlist", - schema: { - summary: "Get Allowed IP Addresses", - description: "Get the list of allowed IP addresses", - tags: ["Configuration"], - operationId: "getIpAllowlist", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(false); - - res.status(StatusCodes.OK).send({ - result: config.ipAllowlist, - }); - }, - }); -} diff --git a/src/server/routes/configuration/ip/set.ts b/src/server/routes/configuration/ip/set.ts deleted file mode 100644 index f960ba615..000000000 --- a/src/server/routes/configuration/ip/set.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Object({ - ips: Type.Array( - Type.String({ - minLength: 7, - description: "IP address as a string", - }), - { - description: "Array of IP addresses to allowlist", - }, - ), -}); - -requestBodySchema.examples = [ - { - ips: ["8.8.8.8", "172.217.255.255"], - }, -]; - -export async function setIpAllowlist(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "PUT", - url: "/configuration/ip-allowlist", - schema: { - summary: "Set IP Allowlist", - description: "Replaces the IP Allowlist array to allow calls to Engine", - tags: ["Configuration"], - operationId: "setIpAllowlist", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const ips = req.body.ips.map((ip) => ip.trim()); - const dedupe = Array.from(new Set([...ips])); - - await updateConfiguration({ - ipAllowlist: dedupe, - }); - - // Fetch and return the updated configuration - const config = await getConfig(false); - res.status(StatusCodes.OK).send({ - result: config.ipAllowlist, - }); - }, - }); -} diff --git a/src/server/routes/configuration/transactions/get.ts b/src/server/routes/configuration/transactions/get.ts deleted file mode 100644 index e86533968..000000000 --- a/src/server/routes/configuration/transactions/get.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const responseBodySchema = Type.Object({ - result: Type.Object({ - minTxsToProcess: Type.Integer(), - maxTxsToProcess: Type.Integer(), - minedTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]), - maxTxsToUpdate: Type.Integer(), - retryTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]), - minEllapsedBlocksBeforeRetry: Type.Integer(), - maxFeePerGasForRetries: Type.String(), - maxPriorityFeePerGasForRetries: Type.String(), - maxRetriesPerTx: Type.Integer(), - clearCacheCronSchedule: Type.Union([Type.String(), Type.Null()]), - }), -}); - -export async function getTransactionConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/transactions", - schema: { - summary: "Get transaction processing configuration", - description: "Get transactions processing configuration", - tags: ["Configuration"], - operationId: "getTransactionConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(); - res.status(StatusCodes.OK).send({ - result: { - minTxsToProcess: config.minTxsToProcess, - maxTxsToProcess: config.maxTxsToProcess, - minedTxListenerCronSchedule: config.minedTxListenerCronSchedule, - maxTxsToUpdate: config.maxTxsToUpdate, - retryTxListenerCronSchedule: config.retryTxListenerCronSchedule, - minEllapsedBlocksBeforeRetry: config.minEllapsedBlocksBeforeRetry, - maxFeePerGasForRetries: config.maxFeePerGasForRetries, - maxPriorityFeePerGasForRetries: config.maxPriorityFeePerGasForRetries, - maxRetriesPerTx: config.maxRetriesPerTx, - clearCacheCronSchedule: config.clearCacheCronSchedule, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/transactions/update.ts b/src/server/routes/configuration/transactions/update.ts deleted file mode 100644 index 801956841..000000000 --- a/src/server/routes/configuration/transactions/update.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Partial( - Type.Object({ - maxTxsToProcess: Type.Integer({ minimum: 1, maximum: 10_000 }), - maxTxsToUpdate: Type.Integer({ minimum: 1, maximum: 10_000 }), - minedTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]), - retryTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]), - minEllapsedBlocksBeforeRetry: Type.Integer({ minimum: 1, maximum: 10_000 }), - maxFeePerGasForRetries: Type.String(), - maxRetriesPerTx: Type.Integer({ minimum: 0, maximum: 10_000 }), - }), -); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - minTxsToProcess: Type.Integer(), - maxTxsToProcess: Type.Integer(), - minedTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]), - maxTxsToUpdate: Type.Integer(), - retryTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]), - minEllapsedBlocksBeforeRetry: Type.Integer(), - maxFeePerGasForRetries: Type.String(), - maxPriorityFeePerGasForRetries: Type.String(), - maxRetriesPerTx: Type.Integer(), - }), -}); - -export async function updateTransactionConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - }>({ - method: "POST", - url: "/configuration/transactions", - schema: { - summary: "Update transaction processing configuration", - description: "Update transaction processing configuration", - tags: ["Configuration"], - operationId: "updateTransactionConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - await updateConfiguration({ ...req.body }); - const config = await getConfig(false); - res.status(StatusCodes.OK).send({ - result: { - minTxsToProcess: config.minTxsToProcess, - maxTxsToProcess: config.maxTxsToProcess, - minedTxListenerCronSchedule: config.minedTxListenerCronSchedule, - maxTxsToUpdate: config.maxTxsToUpdate, - retryTxListenerCronSchedule: config.retryTxListenerCronSchedule, - minEllapsedBlocksBeforeRetry: config.minEllapsedBlocksBeforeRetry, - maxFeePerGasForRetries: config.maxFeePerGasForRetries, - maxPriorityFeePerGasForRetries: config.maxPriorityFeePerGasForRetries, - maxRetriesPerTx: config.maxRetriesPerTx, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/wallets/get.ts b/src/server/routes/configuration/wallets/get.ts deleted file mode 100644 index b3f87ce62..000000000 --- a/src/server/routes/configuration/wallets/get.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { WalletType } from "../../../../shared/schemas/wallet"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - type: Type.Enum(WalletType), - - awsAccessKeyId: Type.Union([Type.String(), Type.Null()]), - awsRegion: Type.Union([Type.String(), Type.Null()]), - - // Omit awsSecretAccessKey - gcpApplicationProjectId: Type.Union([Type.String(), Type.Null()]), - gcpKmsLocationId: Type.Union([Type.String(), Type.Null()]), - gcpKmsKeyRingId: Type.Union([Type.String(), Type.Null()]), - gcpApplicationCredentialEmail: Type.Union([Type.String(), Type.Null()]), - // Omit gcpApplicationCredentialPrivateKey - }), -}); - -export async function getWalletsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/configuration/wallets", - schema: { - summary: "Get wallets configuration", - description: "Get wallets configuration", - tags: ["Configuration"], - operationId: "getWalletsConfiguration", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const config = await getConfig(); - - const { legacyWalletType_removeInNextBreakingChange, aws, gcp } = - config.walletConfiguration; - - res.status(StatusCodes.OK).send({ - result: { - type: legacyWalletType_removeInNextBreakingChange, - awsAccessKeyId: aws?.awsAccessKeyId ?? null, - awsRegion: aws?.defaultAwsRegion ?? null, - gcpApplicationProjectId: gcp?.defaultGcpApplicationProjectId ?? null, - gcpKmsLocationId: gcp?.defaultGcpKmsLocationId ?? null, - gcpKmsKeyRingId: gcp?.defaultGcpKmsKeyRingId ?? null, - gcpApplicationCredentialEmail: - gcp?.gcpApplicationCredentialEmail ?? null, - }, - }); - }, - }); -} diff --git a/src/server/routes/configuration/wallets/update.ts b/src/server/routes/configuration/wallets/update.ts deleted file mode 100644 index b807a9604..000000000 --- a/src/server/routes/configuration/wallets/update.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateConfiguration } from "../../../../shared/db/configuration/update-configuration"; -import { WalletType } from "../../../../shared/schemas/wallet"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { createCustomError } from "../../../middleware/error"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { responseBodySchema } from "./get"; - -const requestBodySchema = Type.Union([ - Type.Object({ - awsAccessKeyId: Type.String(), - awsSecretAccessKey: Type.String(), - awsRegion: Type.String(), - }), - Type.Object({ - gcpApplicationProjectId: Type.String(), - gcpKmsLocationId: Type.String(), - gcpKmsKeyRingId: Type.String(), - gcpApplicationCredentialEmail: Type.String(), - gcpApplicationCredentialPrivateKey: Type.String(), - }), - Type.Object({ - circleApiKey: Type.String(), - }), -]); - -requestBodySchema.examples = [ - { - type: WalletType.local, - }, - { - type: WalletType.awsKms, - awsAccessKeyId: "", - awsSecretAccessKey: "", - awsRegion: "", - }, - { - type: WalletType.gcpKms, - gcpApplicationProjectId: "", - gcpKmsLocationId: "", - gcpKmsKeyRingId: "", - gcpApplicationCredentialEmail: "", - gcpApplicationCredentialPrivateKey: - "", - }, -]; - -export async function updateWalletsConfiguration(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/configuration/wallets", - schema: { - summary: "Update wallets configuration", - description: "Update wallets configuration", - tags: ["Configuration"], - operationId: "updateWalletsConfiguration", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - if ("awsAccessKeyId" in req.body) { - if ( - !req.body.awsAccessKeyId || - !req.body.awsSecretAccessKey || - !req.body.awsRegion - ) { - throw createCustomError( - "Please specify all AWS KMS configuration.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - await updateConfiguration({ - awsAccessKeyId: req.body.awsAccessKeyId, - awsSecretAccessKey: req.body.awsSecretAccessKey, - awsRegion: req.body.awsRegion, - }); - } - - if ("gcpApplicationProjectId" in req.body) { - if ( - !req.body.gcpApplicationProjectId || - !req.body.gcpKmsLocationId || - !req.body.gcpKmsKeyRingId || - !req.body.gcpApplicationCredentialEmail || - !req.body.gcpApplicationCredentialPrivateKey - ) { - throw createCustomError( - "Please specify all GCP KMS configuration.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - await updateConfiguration({ - gcpApplicationProjectId: req.body.gcpApplicationProjectId, - gcpKmsLocationId: req.body.gcpKmsLocationId, - gcpKmsKeyRingId: req.body.gcpKmsKeyRingId, - gcpApplicationCredentialEmail: req.body.gcpApplicationCredentialEmail, - gcpApplicationCredentialPrivateKey: - req.body.gcpApplicationCredentialPrivateKey, - }); - } - - if ("circleApiKey" in req.body) { - await updateConfiguration({ - walletProviderConfigs: { - circle: { - apiKey: req.body.circleApiKey, - }, - }, - }); - } - - const config = await getConfig(false); - - const { legacyWalletType_removeInNextBreakingChange, aws, gcp } = - config.walletConfiguration; - - res.status(StatusCodes.OK).send({ - result: { - type: legacyWalletType_removeInNextBreakingChange, - awsAccessKeyId: aws?.awsAccessKeyId ?? null, - awsRegion: aws?.defaultAwsRegion ?? null, - gcpApplicationProjectId: gcp?.defaultGcpApplicationProjectId ?? null, - gcpKmsLocationId: gcp?.defaultGcpKmsLocationId ?? null, - gcpKmsKeyRingId: gcp?.defaultGcpKmsKeyRingId ?? null, - gcpApplicationCredentialEmail: - gcp?.gcpApplicationCredentialEmail ?? null, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/events/get-all-events.ts b/src/server/routes/contract/events/get-all-events.ts deleted file mode 100644 index c108cf09b..000000000 --- a/src/server/routes/contract/events/get-all-events.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - contractEventSchema, - eventsQuerystringSchema, -} from "../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { thirdwebClient } from "../../../../shared/utils/sdk"; -import { getChain } from "../../../../shared/utils/chain"; -import { getChainIdFromChain } from "../../../utils/chain"; -import { getContract, getContractEvents } from "thirdweb"; -import { - type ContractEventV5, - toContractEventV4Schema, -} from "../../../schemas/event"; -import { createCustomError } from "../../../middleware/error"; -import { prettifyError } from "../../../../shared/utils/error"; - -const requestSchema = contractParamSchema; - -const querySringSchema = Type.Optional(eventsQuerystringSchema); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(contractEventSchema), -}); - -responseSchema.example = { - result: [ - { - eventName: "Transfer", - data: { - from: "0x0000000000000000000000000000000000000000", - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - tokenId: { - type: "BigNumber", - hex: "0x01", - }, - }, - transaction: { - blockNumber: 35439713, - blockHash: - "0x0413d9c88a664f46b54cd47d66073f47114fa3b0183ca5f713d4567d345de4a1", - transactionIndex: 6, - removed: false, - address: "0xc8be6265C06aC376876b4F62670adB3c4d72EABA", - data: "0x", - topics: [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000001946267d81fb8adeeea28e6b98bcd446c8248473", - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - transactionHash: - "0x6ee82341f1e09511e9502eea45e0ca9e52dd0295a515401834d0d05a5e802da5", - logIndex: 13, - event: "Transfer", - eventSignature: "Transfer(address,address,uint256)", - }, - }, - ], -}; - -export async function getAllEvents(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/events/get-all", - schema: { - summary: "Get all events", - description: "Get a list of all blockchain events for this contract.", - tags: ["Contract-Events"], - operationId: "getAllEvents", - params: requestSchema, - querystring: querySringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { fromBlock, toBlock, order } = request.query; - - const chainId = await getChainIdFromChain(chain); - - const contract = getContract({ - client: thirdwebClient, - address: contractAddress, - chain: await getChain(chainId), - }); - - let eventsV5: ContractEventV5[]; - try { - eventsV5 = await getContractEvents({ - contract: contract, - fromBlock: - typeof fromBlock === "number" ? BigInt(fromBlock) : fromBlock, - toBlock: typeof toBlock === "number" ? BigInt(toBlock) : toBlock, - }); - } catch (e) { - throw createCustomError( - `Failed to get events: ${prettifyError(e)}`, - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - reply.status(StatusCodes.OK).send({ - result: eventsV5.map(toContractEventV4Schema).sort((a, b) => { - return order === "desc" - ? b.transaction.blockNumber - a.transaction.blockNumber - : a.transaction.blockNumber - b.transaction.blockNumber; - }), - }); - }, - }); -} diff --git a/src/server/routes/contract/events/get-contract-event-logs.ts b/src/server/routes/contract/events/get-contract-event-logs.ts deleted file mode 100644 index 84248fd68..000000000 --- a/src/server/routes/contract/events/get-contract-event-logs.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContractEventLogsByBlockAndTopics } from "../../../../shared/db/contract-event-logs/get-contract-event-logs"; -import { isContractSubscribed } from "../../../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { createCustomError } from "../../../middleware/error"; -import { AddressSchema, TransactionHashSchema } from "../../../schemas/address"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestQuerySchema = Type.Object({ - fromBlock: Type.Integer({ minimum: 0 }), - toBlock: Type.Optional(Type.Integer({ minimum: 0 })), - topics: Type.Optional(Type.Array(Type.String())), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - logs: Type.Array( - Type.Object({ - chainId: Type.Integer(), - contractAddress: AddressSchema, - blockNumber: Type.Integer(), - transactionHash: TransactionHashSchema, - topics: Type.Array(Type.String()), - data: Type.String(), - eventName: Type.Optional(Type.String()), - decodedLog: Type.Any(), - timestamp: Type.Integer(), - transactionIndex: Type.Integer(), - logIndex: Type.Integer(), - }), - ), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - logs: [ - { - chainId: 1, - contractAddress: "0x....", - blockNumber: 1, - transactionHash: "0x...", - topics: ["0x..."], - data: "0x...", - eventName: "TransferFrom", - decodedLog: { - from: { - type: "address", - value: "0x...", - }, - to: { - type: "address", - value: "0x...", - }, - value: { - type: "uint256", - value: "1000", - }, - }, - timestamp: 100, - transactionIndex: 1, - logIndex: 1, - }, - ], - status: "success", - }, -}; - -// TODO: throw this into config -const MAX_ALLOWED_QUERY_BLOCKS = 100; - -export async function getContractEventLogs(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/events/get-logs", - schema: { - summary: "Get subscribed contract event logs", - description: "Get event logs for a subscribed contract", - tags: ["Contract-Events"], - operationId: "getContractEventLogs", - params: contractParamSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { fromBlock, toBlock, topics } = request.query; - - if (toBlock && toBlock < fromBlock) { - throw createCustomError( - "toBlock cannot be less than fromBlock", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - if (toBlock && toBlock - fromBlock > MAX_ALLOWED_QUERY_BLOCKS) { - throw createCustomError( - `cannot query more than ${MAX_ALLOWED_QUERY_BLOCKS}`, - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const standardizedContractAddress = contractAddress.toLowerCase(); - - const chainId = await getChainIdFromChain(chain); - - // check if subscribed, if not tell user to subscribe - const isSubscribed = await isContractSubscribed({ - chainId, - contractAddress: standardizedContractAddress, - }); - - if (!isSubscribed) { - const subcriptionUrl = `/contract/${chain}/${contractAddress}/events/subscribe`; - throw createCustomError( - `Contract is not subscribed to! To subscribe, please use ${subcriptionUrl}`, - StatusCodes.NOT_FOUND, - "NOT_FOUND", - ); - } - - const resultLogs = await getContractEventLogsByBlockAndTopics({ - chainId, - contractAddress: standardizedContractAddress, - fromBlock, - toBlock, - topics, - }); - - const logs = resultLogs.map((log) => { - const topics: string[] = []; - for (const val of [ log.topic0, log.topic1, log.topic2, log.topic3 ]) { - if (val) { - topics.push(val); - } - } - - return { - chainId: Number.parseInt(log.chainId), - contractAddress: log.contractAddress, - blockNumber: log.blockNumber, - transactionHash: log.transactionHash, - topics, - data: log.data, - eventName: log.eventName ?? undefined, - decodedLog: log.decodedLog, - timestamp: log.timestamp.getTime(), - transactionIndex: log.transactionIndex, - logIndex: log.logIndex, - }; - }); - - reply.status(StatusCodes.OK).send({ - result: { - logs, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/events/get-event-logs-by-timestamp.ts b/src/server/routes/contract/events/get-event-logs-by-timestamp.ts deleted file mode 100644 index 5844410e9..000000000 --- a/src/server/routes/contract/events/get-event-logs-by-timestamp.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getEventLogsByBlockTimestamp } from "../../../../shared/db/contract-event-logs/get-contract-event-logs"; -import { AddressSchema } from "../../../schemas/address"; -import { eventLogSchema } from "../../../schemas/event-log"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestQuerySchema = Type.Object({ - contractAddresses: Type.Optional(Type.Array(AddressSchema)), - topics: Type.Optional(Type.Array(Type.String())), - fromBlockTimestamp: Type.Integer({ minimum: 0 }), - toBlockTimestamp: Type.Optional(Type.Integer({ minimum: 0 })), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - logs: Type.Array(eventLogSchema), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - logs: [ - { - chainId: 1, - contractAddress: "0x....", - blockNumber: 1, - transactionHash: "0x...", - topics: ["0x..."], - data: "0x...", - eventName: "TransferFrom", - decodedLog: { - from: { - type: "address", - value: "0x...", - }, - to: { - type: "address", - value: "0x...", - }, - value: { - type: "uint256", - value: "1000", - }, - }, - timestamp: 100, - transactionIndex: 1, - logIndex: 1, - }, - ], - status: "success", - }, -}; - -export async function getEventLogs(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/events/get-logs", - schema: { - summary: "Get subscribed contract event logs", - description: "Get event logs for a subscribed contract", - tags: ["Contract-Events"], - operationId: "getEventLogs", - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { - contractAddresses, - topics, - fromBlockTimestamp, - toBlockTimestamp, - } = request.query; - - const standardizedContractAddresses = contractAddresses?.map((val) => - val.toLowerCase(), - ); - - const resultLogs = await getEventLogsByBlockTimestamp({ - fromBlockTimestamp: fromBlockTimestamp, - toBlockTimestamp: toBlockTimestamp, - contractAddresses: standardizedContractAddresses, - topics: topics, - }); - - const logs = resultLogs.map((log) => { - const topics: string[] = []; - for (const val of [ log.topic0, log.topic1, log.topic2, log.topic3 ]) { - if (val) { - topics.push(val); - } - } - - return { - chainId: Number.parseInt(log.chainId), - contractAddress: log.contractAddress, - blockNumber: log.blockNumber, - transactionHash: log.transactionHash, - topics, - data: log.data, - eventName: log.eventName ?? undefined, - decodedLog: log.decodedLog, - timestamp: log.timestamp.getTime(), - transactionIndex: log.transactionIndex, - logIndex: log.logIndex, - }; - }); - - reply.status(StatusCodes.OK).send({ - result: { - logs, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/events/get-events.ts b/src/server/routes/contract/events/get-events.ts deleted file mode 100644 index f3a2d77b2..000000000 --- a/src/server/routes/contract/events/get-events.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../shared/utils/cache/get-contract"; -import { - contractEventSchema, - eventsQuerystringSchema, -} from "../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestSchema = contractParamSchema; - -const requestBodyParams = Type.Object( - { - eventName: Type.String({ examples: ["Transfer"] }), - ...eventsQuerystringSchema.properties, - filters: Type.Optional(Type.Object({})), - }, - { - description: - "Specify the from and to block numbers to get events for, defaults to all blocks", - }, -); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(contractEventSchema), -}); - -responseSchema.example = { - result: { - eventName: "ApprovalForAll", - data: { - owner: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - operator: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - approved: true, - }, - transaction: { - blockNumber: 36010321, - blockHash: - "0x2c388fe429215b6c2934746410a52a3416b7a1725cea6885eaf220f05f50a6ec", - transactionIndex: 19, - removed: false, - address: "0xc8be6265C06aC376876b4F62670adB3c4d72EABA", - data: "0x0000000000000000000000000000000000000000000000000000000000000001", - topics: [ - "0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31", - "0x000000000000000000000000e79ee09bd47f4f5381dbbacacff2040f2fbc5803", - "0x0000000000000000000000003ecdbf3b911d0e9052b64850693888b008e18373", - ], - transactionHash: - "0xa4143253005103e5203554f4e17e90a517591cd2d5e3b3dceabfbfb8fbdca5f9", - logIndex: 55, - event: "ApprovalForAll", - eventSignature: "ApprovalForAll(address,address,bool)", - }, - }, -}; - -export async function getEvents(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/events/get", - schema: { - summary: "Get events", - description: - "Get a list of specific blockchain events emitted from this contract.", - tags: ["Contract-Events"], - operationId: "getEvents", - params: requestSchema, - body: requestBodyParams, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { fromBlock, toBlock, order, eventName, filters } = request.body; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = await contract.events.getEvents(eventName, { - fromBlock, - toBlock, - order, - filters, - }); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/events/paginate-event-logs.ts b/src/server/routes/contract/events/paginate-event-logs.ts deleted file mode 100644 index cc566aee5..000000000 --- a/src/server/routes/contract/events/paginate-event-logs.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfiguration } from "../../../../shared/db/configuration/get-configuration"; -import { getEventLogsByCursor } from "../../../../shared/db/contract-event-logs/get-contract-event-logs"; -import { AddressSchema } from "../../../schemas/address"; -import { eventLogSchema, toEventLogSchema } from "../../../schemas/event-log"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const requestQuerySchema = Type.Object({ - cursor: Type.Optional(Type.String()), - pageSize: Type.Optional(Type.Integer({ minimum: 1 })), - topics: Type.Optional(Type.Array(Type.String())), - contractAddresses: Type.Optional(Type.Array(AddressSchema)), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - cursor: Type.Optional(Type.String()), - logs: Type.Array(eventLogSchema), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - cursor: "abcd-xyz", - logs: [ - { - chainId: 1, - contractAddress: "0x....", - blockNumber: 1, - transactionHash: "0x...", - topics: ["0x..."], - data: "0x...", - eventName: "TransferFrom", - decodedLog: { - from: { - type: "address", - value: "0x...", - }, - to: { - type: "address", - value: "0x...", - }, - value: { - type: "uint256", - value: "1000", - }, - }, - timestamp: 100, - transactionIndex: 1, - logIndex: 1, - }, - ], - status: "success", - }, -}; - -export async function pageEventLogs(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/events/paginate-logs", - schema: { - summary: "Get contract paginated event logs for subscribed contract", - description: "Get contract paginated event logs for subscribed contract", - tags: ["Contract-Events"], - operationId: "pageEventLogs", - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { cursor, pageSize, topics, contractAddresses } = request.query; - - const standardizedContractAddresses = contractAddresses?.map((val) => - val.toLowerCase(), - ); - - // add lag behind to account for clock skew, concurrent writes, etc - const config = await getConfiguration(); - const maxCreatedAt = new Date( - Date.now() - config.cursorDelaySeconds * 1000, - ); - - const { cursor: newCursor, logs } = await getEventLogsByCursor({ - cursor, - limit: pageSize, - topics, - contractAddresses: standardizedContractAddresses, - maxCreatedAt, - }); - - reply.status(StatusCodes.OK).send({ - result: { - cursor: newCursor, - logs: logs.map(toEventLogSchema), - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/account-factory/index.ts b/src/server/routes/contract/extensions/account-factory/index.ts deleted file mode 100644 index 5934ba12a..000000000 --- a/src/server/routes/contract/extensions/account-factory/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { getAllAccounts } from "./read/get-all-accounts"; -import { getAssociatedAccounts } from "./read/get-associated-accounts"; -import { isAccountDeployed } from "./read/is-account-deployed"; -import { predictAccountAddress } from "./read/predict-account-address"; -import { createAccount } from "./write/create-account"; - -export const accountFactoryRoutes = async (fastify: FastifyInstance) => { - // GET - await fastify.register(getAllAccounts); - await fastify.register(getAssociatedAccounts); - await fastify.register(isAccountDeployed); - await fastify.register(predictAccountAddress); - - // POST - await fastify.register(createAccount); -}; diff --git a/src/server/routes/contract/extensions/account-factory/read/get-all-accounts.ts b/src/server/routes/contract/extensions/account-factory/read/get-all-accounts.ts deleted file mode 100644 index b445ee240..000000000 --- a/src/server/routes/contract/extensions/account-factory/read/get-all-accounts.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const responseBodySchema = Type.Object({ - result: Type.Array(Type.String(), { - description: "The account addresses of all the accounts in this factory", - }), -}); - -export const getAllAccounts = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/account-factory/get-all-accounts", - schema: { - summary: "Get all smart accounts", - description: "Get all the smart accounts for this account factory.", - tags: ["Account Factory"], - operationId: "getAllAccounts", - params: contractParamSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - }); - const accountAddresses = await contract.accountFactory.getAllAccounts(); - - reply.status(StatusCodes.OK).send({ - result: accountAddresses, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account-factory/read/get-associated-accounts.ts b/src/server/routes/contract/extensions/account-factory/read/get-associated-accounts.ts deleted file mode 100644 index 31380e7d9..000000000 --- a/src/server/routes/contract/extensions/account-factory/read/get-associated-accounts.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const responseBodySchema = Type.Object({ - result: Type.Array(Type.String(), { - description: - "The account addresses of all the accounts with a specific signer in this factory", - }), -}); - -const QuerySchema = Type.Object({ - signerAddress: { - ...AddressSchema, - description: "The address of the signer to get associated accounts from", - }, -}); - -export const getAssociatedAccounts = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/account-factory/get-associated-accounts", - schema: { - summary: "Get associated smart accounts", - description: - "Get all the smart accounts for this account factory associated with the specific admin wallet.", - tags: ["Account Factory"], - operationId: "getAssociatedAccounts", - params: contractParamSchema, - querystring: QuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { signerAddress } = request.query; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - }); - const accountAddresses = - await contract.accountFactory.getAssociatedAccounts(signerAddress); - - reply.status(StatusCodes.OK).send({ - result: accountAddresses, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account-factory/read/is-account-deployed.ts b/src/server/routes/contract/extensions/account-factory/read/is-account-deployed.ts deleted file mode 100644 index 1588f95a6..000000000 --- a/src/server/routes/contract/extensions/account-factory/read/is-account-deployed.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const responseBodySchema = Type.Object({ - result: Type.Boolean({ - description: "Whether or not the account has been deployed", - }), -}); - -const QuerySchema = Type.Object({ - adminAddress: { - ...AddressSchema, - description: - "The address of the admin to check if the account address is deployed", - }, - extraData: Type.Optional( - Type.String({ - description: "Extra data to use in predicting the account address", - }), - ), -}); - -export const isAccountDeployed = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/account-factory/is-account-deployed", - schema: { - summary: "Check if deployed", - description: - "Check if a smart account has been deployed to the blockchain.", - tags: ["Account Factory"], - operationId: "isAccountDeployed", - params: contractParamSchema, - querystring: QuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { adminAddress, extraData } = request.query; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - }); - const isDeployed = await contract.accountFactory.isAccountDeployed( - adminAddress, - extraData, - ); - - reply.status(StatusCodes.OK).send({ - result: isDeployed, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account-factory/read/predict-account-address.ts b/src/server/routes/contract/extensions/account-factory/read/predict-account-address.ts deleted file mode 100644 index 546932cd8..000000000 --- a/src/server/routes/contract/extensions/account-factory/read/predict-account-address.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { predictAddress } from "thirdweb/wallets/smart"; -import { getContractV5 } from "../../../../../../shared/utils/cache/get-contractv5"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const responseBodySchema = Type.Object({ - result: Type.String({ - description: "New account counter-factual address.", - }), -}); - -const QuerySchema = Type.Object({ - adminAddress: { - ...AddressSchema, - description: "The address of the admin to predict the account address for", - }, - extraData: Type.Optional( - Type.String({ - description: - "Extra data (account salt) to add to use in predicting the account address", - }), - ), -}); - -export const predictAccountAddress = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/account-factory/predict-account-address", - schema: { - summary: "Predict smart account address", - description: "Get the counterfactual address of a smart account.", - tags: ["Account Factory"], - operationId: "predictAccountAddress", - params: contractParamSchema, - querystring: QuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { adminAddress, extraData } = request.query; - const chainId = await getChainIdFromChain(chain); - const factoryContract = await getContractV5({ - chainId, - contractAddress, - }); - - const accountAddress = await predictAddress({ - factoryContract, - adminAddress, - accountSalt: extraData, - }); - - reply.status(StatusCodes.OK).send({ - result: accountAddress, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account-factory/write/create-account.ts b/src/server/routes/contract/extensions/account-factory/write/create-account.ts deleted file mode 100644 index a5e82e808..000000000 --- a/src/server/routes/contract/extensions/account-factory/write/create-account.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { createAccount as factoryCreateAccount } from "thirdweb/extensions/erc4337"; -import { isHex, stringToHex } from "thirdweb/utils"; -import { predictAddress } from "thirdweb/wallets/smart"; -import { getContractV5 } from "../../../../../../shared/utils/cache/get-contractv5"; -import { redis } from "../../../../../../shared/utils/redis/redis"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { prebuiltDeployResponseSchema } from "../../../../../schemas/prebuilts"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestBodySchema = Type.Object({ - adminAddress: { - ...AddressSchema, - description: "The admin address to create an account for", - }, - extraData: Type.Optional( - Type.String({ - description: "Extra data to add to use in creating the account address", - }), - ), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - adminAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - }, -]; - -export const createAccount = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/account-factory/create-account", - schema: { - summary: "Create smart account", - description: "Create a smart account for this account factory.", - tags: ["Account Factory"], - operationId: "createAccount", - params: contractParamSchema, - headers: walletWithAAHeaderSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: prebuiltDeployResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { adminAddress, extraData, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const factoryContract = await getContractV5({ - chainId, - contractAddress, - }); - - const deployedAddress = await predictAddress({ - factoryContract, - adminAddress, - accountSalt: extraData, - }); - - // if extraData is not a hex string, convert it to a hex string - // this is the same transformation that is done in the SDK - // for predictAddress and createAndSignUserOp - // but needed here because we're calling the raw autogenerated abi function - const accountSaltHex = - extraData && isHex(extraData) - ? extraData - : stringToHex(extraData ?? ""); - - const transaction = factoryCreateAccount({ - contract: factoryContract, - admin: adminAddress, - data: accountSaltHex, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - transactionMode, - }); - - // Note: This is a temporary solution to cache the deployed address's factory for 7 days. - // This is needed due to a potential race condition of submitting a transaction immediately after creating an account that is not yet mined onchain - await redis.set( - `account-factory:${deployedAddress.toLowerCase()}`, - contractAddress, - "EX", - 7 * 24 * 60 * 60, - ); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - deployedAddress, - }, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/index.ts b/src/server/routes/contract/extensions/account/index.ts deleted file mode 100644 index c50ac0855..000000000 --- a/src/server/routes/contract/extensions/account/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { getAllAdmins } from "./read/get-all-admins"; -import { getAllSessions } from "./read/get-all-sessions"; -import { grantAdmin } from "./write/grant-admin"; -import { grantSession } from "./write/grant-session"; -import { revokeAdmin } from "./write/revoke-admin"; -import { revokeSession } from "./write/revoke-session"; -import { updateSession } from "./write/update-session"; - -export const accountRoutes = async (fastify: FastifyInstance) => { - // GET - await fastify.register(getAllAdmins); - await fastify.register(getAllSessions); - - // POST - await fastify.register(grantAdmin); - await fastify.register(revokeAdmin); - await fastify.register(grantSession); - await fastify.register(revokeSession); - await fastify.register(updateSession); -}; diff --git a/src/server/routes/contract/extensions/account/read/get-all-admins.ts b/src/server/routes/contract/extensions/account/read/get-all-admins.ts deleted file mode 100644 index 4bfe3f3b0..000000000 --- a/src/server/routes/contract/extensions/account/read/get-all-admins.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const responseBodySchema = Type.Object({ - result: Type.Array(Type.String(), { - description: "The address of the admins on this account", - }), -}); - -export const getAllAdmins = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/account/admins/get-all", - schema: { - summary: "Get all admins", - description: "Get all admins for a smart account.", - tags: ["Account"], - operationId: "getAllAdmins", - params: contractParamSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - }); - const accountAddresses = await contract.account.getAllAdmins(); - - reply.status(StatusCodes.OK).send({ - result: accountAddresses, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/read/get-all-sessions.ts b/src/server/routes/contract/extensions/account/read/get-all-sessions.ts deleted file mode 100644 index 4da9384ff..000000000 --- a/src/server/routes/contract/extensions/account/read/get-all-sessions.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { sessionSchema } from "../../../../../schemas/account"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const responseBodySchema = Type.Object({ - result: Type.Array(sessionSchema), -}); - -export const getAllSessions = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/account/sessions/get-all", - schema: { - summary: "Get all session keys", - description: "Get all session keys for a smart account.", - tags: ["Account"], - operationId: "getAllSessions", - params: contractParamSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - }); - const sessions = await contract.account.getAllSigners(); - - reply.status(StatusCodes.OK).send({ - result: sessions.map((session) => ({ - signerAddress: session.signer, - startDate: session.permissions.startDate.toISOString(), - expirationDate: session.permissions.expirationDate.toISOString(), - nativeTokenLimitPerTransaction: - session.permissions.nativeTokenLimitPerTransaction.toString(), - approvedCallTargets: session.permissions.approvedCallTargets, - })), - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/write/grant-admin.ts b/src/server/routes/contract/extensions/account/write/grant-admin.ts deleted file mode 100644 index 38efdb3d7..000000000 --- a/src/server/routes/contract/extensions/account/write/grant-admin.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestBodySchema = Type.Object({ - signerAddress: { - ...AddressSchema, - description: "Address to grant admin permissions to", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - signerAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - }, -]; - -export const grantAdmin = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/account/admins/grant", - schema: { - summary: "Grant admin", - description: "Grant a smart account's admin permission.", - tags: ["Account"], - operationId: "grantAccountAdmin", - headers: walletWithAAHeaderSchema, - params: contractParamSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { signerAddress, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-idempotency-key": idempotencyKey, - "x-account-address": accountAddress, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = - await contract.account.grantAdminPermissions.prepare(signerAddress); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "account", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/write/grant-session.ts b/src/server/routes/contract/extensions/account/write/grant-session.ts deleted file mode 100644 index 90f5a1153..000000000 --- a/src/server/routes/contract/extensions/account/write/grant-session.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { sessionSchema } from "../../../../../schemas/account"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestBodySchema = Type.Object({ - ...sessionSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - signerAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - startDate: "2021-01-01T00:00:00.000Z", - expirationDate: "2022-01-01T00:10:00.000Z", - nativeTokenLimitPerTransaction: "1000000000000000000", - approvedCallTargets: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }, -]; - -export const grantSession = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/account/sessions/create", - schema: { - summary: "Create session key", - description: "Create a session key for a smart account.", - tags: ["Account"], - operationId: "grantAccountSession", - params: contractParamSchema, - headers: walletWithAAHeaderSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { signerAddress, txOverrides, ...permissions } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-idempotency-key": idempotencyKey, - "x-account-address": accountAddress, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = await contract.account.grantPermissions.prepare( - signerAddress, - { - startDate: new Date(permissions.startDate), - expirationDate: new Date(permissions.expirationDate), - approvedCallTargets: permissions.approvedCallTargets, - nativeTokenLimitPerTransaction: - permissions.nativeTokenLimitPerTransaction, - }, - ); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "account", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/write/revoke-admin.ts b/src/server/routes/contract/extensions/account/write/revoke-admin.ts deleted file mode 100644 index 1fec31058..000000000 --- a/src/server/routes/contract/extensions/account/write/revoke-admin.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestBodySchema = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Address to revoke admin permissions from", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - walletAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - }, -]; - -export const revokeAdmin = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - Body: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/account/admins/revoke", - schema: { - summary: "Revoke admin", - description: "Revoke a smart account's admin permission.", - tags: ["Account"], - operationId: "revokeAccountAdmin", - headers: walletWithAAHeaderSchema, - params: contractParamSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { walletAddress, txOverrides } = request.body; - const { - "x-backend-wallet-address": backendWalletAddress, - "x-idempotency-key": idempotencyKey, - "x-account-address": accountAddress, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - walletAddress: backendWalletAddress, - accountAddress, - }); - - const tx = - await contract.account.revokeAdminPermissions.prepare(walletAddress); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "account", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/write/revoke-session.ts b/src/server/routes/contract/extensions/account/write/revoke-session.ts deleted file mode 100644 index 82727db79..000000000 --- a/src/server/routes/contract/extensions/account/write/revoke-session.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestBodySchema = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Address to revoke session from", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - walletAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - }, -]; - -export const revokeSession = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/account/sessions/revoke", - schema: { - summary: "Revoke session key", - description: "Revoke a session key for a smart account.", - tags: ["Account"], - operationId: "revokeAccountSession", - params: contractParamSchema, - headers: walletWithAAHeaderSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { walletAddress, txOverrides } = request.body; - const { - "x-backend-wallet-address": backendWalletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - walletAddress: backendWalletAddress, - accountAddress, - }); - const tx = await contract.account.revokeAccess.prepare(walletAddress); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "account", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/account/write/update-session.ts b/src/server/routes/contract/extensions/account/write/update-session.ts deleted file mode 100644 index 418c6d6d3..000000000 --- a/src/server/routes/contract/extensions/account/write/update-session.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestBodySchema = Type.Object({ - signerAddress: AddressSchema, - approvedCallTargets: Type.Array(AddressSchema), - startDate: Type.Optional(Type.String()), - expirationDate: Type.Optional(Type.String()), - nativeTokenLimitPerTransaction: Type.Optional(Type.String()), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - signerAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - approvedCallTargets: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }, -]; - -export const updateSession = async (fastify: FastifyInstance) => { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/account/sessions/update", - schema: { - summary: "Update session key", - description: "Update a session key for a smart account.", - tags: ["Account"], - operationId: "updateAccountSession", - params: contractParamSchema, - headers: walletWithAAHeaderSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { signerAddress, txOverrides, ...permissions } = request.body; - const { simulateTx } = request.query; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = await contract.account.updatePermissions.prepare( - signerAddress, - { - startDate: permissions.startDate - ? new Date(permissions.startDate) - : undefined, - expirationDate: permissions.expirationDate - ? new Date(permissions.expirationDate) - : undefined, - approvedCallTargets: permissions.approvedCallTargets, - nativeTokenLimitPerTransaction: - permissions.nativeTokenLimitPerTransaction, - }, - ); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "account", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -}; diff --git a/src/server/routes/contract/extensions/erc1155/index.ts b/src/server/routes/contract/extensions/erc1155/index.ts deleted file mode 100644 index 16b23032e..000000000 --- a/src/server/routes/contract/extensions/erc1155/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { erc1155BalanceOf } from "./read/balance-of"; -import { erc1155CanClaim } from "./read/can-claim"; -import { erc1155Get } from "./read/get"; -import { erc1155GetActiveClaimConditions } from "./read/get-active-claim-conditions"; -import { erc1155GetAll } from "./read/get-all"; -import { erc1155GetAllClaimConditions } from "./read/get-all-claim-conditions"; -import { erc1155GetClaimIneligibilityReasons } from "./read/get-claim-ineligibility-reasons"; -import { erc1155GetClaimerProofs } from "./read/get-claimer-proofs"; -import { erc1155GetOwned } from "./read/get-owned"; -import { erc1155IsApproved } from "./read/is-approved"; -import { erc1155SignatureGenerate } from "./read/signature-generate"; -import { erc1155TotalCount } from "./read/total-count"; -import { erc1155TotalSupply } from "./read/total-supply"; -import { erc1155airdrop } from "./write/airdrop"; -import { erc1155burn } from "./write/burn"; -import { erc1155burnBatch } from "./write/burn-batch"; -import { erc1155claimTo } from "./write/claim-to"; -import { erc1155lazyMint } from "./write/lazy-mint"; -import { erc1155mintAdditionalSupplyTo } from "./write/mint-additional-supply-to"; -import { erc1155mintBatchTo } from "./write/mint-batch-to"; -import { erc1155mintTo } from "./write/mint-to"; -import { erc1155SetApprovalForAll } from "./write/set-approval-for-all"; -import { erc1155SetBatchClaimConditions } from "./write/set-batch-claim-conditions"; -import { erc1155SetClaimCondition } from "./write/set-claim-conditions"; -import { erc1155SignatureMint } from "./write/signature-mint"; -import { erc1155transfer } from "./write/transfer"; -import { erc1155transferFrom } from "./write/transfer-from"; -import { erc1155UpdateClaimConditions } from "./write/update-claim-conditions"; -import { erc1155UpdateTokenMetadata } from "./write/update-token-metadata"; - -export const erc1155Routes = async (fastify: FastifyInstance) => { - // GET - await fastify.register(erc1155Get); - await fastify.register(erc1155GetAll); - await fastify.register(erc1155GetOwned); - await fastify.register(erc1155BalanceOf); - await fastify.register(erc1155IsApproved); - await fastify.register(erc1155TotalCount); - await fastify.register(erc1155TotalSupply); - await fastify.register(erc1155SignatureGenerate); - await fastify.register(erc1155CanClaim); - await fastify.register(erc1155GetActiveClaimConditions); - await fastify.register(erc1155GetAllClaimConditions); - await fastify.register(erc1155GetClaimerProofs); - await fastify.register(erc1155GetClaimIneligibilityReasons); - - // POST - await fastify.register(erc1155airdrop); - await fastify.register(erc1155burn); - await fastify.register(erc1155burnBatch); - await fastify.register(erc1155claimTo); - await fastify.register(erc1155lazyMint); - await fastify.register(erc1155mintAdditionalSupplyTo); - await fastify.register(erc1155mintBatchTo); - await fastify.register(erc1155mintTo); - await fastify.register(erc1155SetApprovalForAll); - await fastify.register(erc1155transfer); - await fastify.register(erc1155transferFrom); - await fastify.register(erc1155SignatureMint); - await fastify.register(erc1155SetClaimCondition); - await fastify.register(erc1155SetBatchClaimConditions); - await fastify.register(erc1155UpdateClaimConditions); - await fastify.register(erc1155UpdateTokenMetadata); -}; diff --git a/src/server/routes/contract/extensions/erc1155/read/balance-of.ts b/src/server/routes/contract/extensions/erc1155/read/balance-of.ts deleted file mode 100644 index 82ce95c12..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/balance-of.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const querystringSchema = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Address of the wallet to check NFT balance", - }, - tokenId: Type.String({ - description: "The tokenId of the NFT to check balance of", - examples: ["0"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -responseSchema.examples = [ - { - result: "1", - }, -]; - -// LOGIC -export async function erc1155BalanceOf(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/balance-of", - schema: { - summary: "Get balance", - description: - "Get the balance of a specific wallet address for this ERC-1155 contract.", - tags: ["ERC1155"], - operationId: "erc1155-balanceOf", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { walletAddress, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.balanceOf( - walletAddress, - tokenId, - ); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/can-claim.ts b/src/server/routes/contract/extensions/erc1155/read/can-claim.ts deleted file mode 100644 index 459990ad4..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/can-claim.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - quantity: Type.String({ - description: "The amount of tokens to claim.", - }), - tokenId: Type.String({ - description: "The token ID of the NFT you want to claim.", - }), - addressToCheck: Type.Optional( - Type.String({ - description: - "The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc.", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Boolean(), -}); - -// LOGIC -export async function erc1155CanClaim(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/can-claim", - schema: { - summary: "Check if tokens are available for claiming", - description: - "Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim.", - tags: ["ERC1155"], - operationId: "erc1155-canClaim", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { quantity, tokenId, addressToCheck } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.claimConditions.canClaim( - quantity, - tokenId, - addressToCheck, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get-active-claim-conditions.ts b/src/server/routes/contract/extensions/erc1155/read/get-active-claim-conditions.ts deleted file mode 100644 index bb83ab1e6..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get-active-claim-conditions.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { claimConditionOutputSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: "The token ID of the NFT you want to claim.", - }), - withAllowList: Type.Optional( - Type.Boolean({ - description: - "Provide a boolean value to include the allowlist in the response.", - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: claimConditionOutputSchema, -}); - -// LOGIC -export async function erc1155GetActiveClaimConditions( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/get-active", - schema: { - summary: "Get currently active claim phase for a specific token ID.", - description: - "Retrieve the currently active claim phase for a specific token ID, if any.", - tags: ["ERC1155"], - operationId: "erc1155-getActiveClaimConditions", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { tokenId, withAllowList } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.claimConditions.getActive( - tokenId, - { - withAllowList, - }, - ); - reply.status(StatusCodes.OK).send({ - result: { - ...returnData, - price: returnData.price.toString(), - waitInSeconds: returnData.waitInSeconds.toString(), - currencyMetadata: { - ...returnData.currencyMetadata, - value: returnData.currencyMetadata.value.toString(), - }, - startTime: returnData.startTime.toISOString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get-all-claim-conditions.ts b/src/server/routes/contract/extensions/erc1155/read/get-all-claim-conditions.ts deleted file mode 100644 index 845e6d21c..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get-all-claim-conditions.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { claimConditionOutputSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: - "The token ID of the NFT you want to get the claim conditions for.", - }), - withAllowList: Type.Optional( - Type.Boolean({ - description: - "Provide a boolean value to include the allowlist in the response.", - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(claimConditionOutputSchema), -}); - -// LOGIC -export async function erc1155GetAllClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/get-all", - schema: { - summary: "Get all the claim phases configured for a specific token ID.", - description: - "Get all the claim phases configured for a specific token ID.", - tags: ["ERC1155"], - operationId: "erc1155-getAllClaimConditions", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { tokenId, withAllowList } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.claimConditions.getAll( - tokenId, - { - withAllowList, - }, - ); - - const sanitizedReturnData = returnData.map((item) => { - return { - ...item, - price: item.price.toString(), - waitInSeconds: item.waitInSeconds.toString(), - currencyMetadata: { - ...item.currencyMetadata, - value: item.currencyMetadata.value.toString(), - }, - startTime: item.startTime.toISOString(), - }; - }); - - reply.status(StatusCodes.OK).send({ - result: sanitizedReturnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get-all.ts b/src/server/routes/contract/extensions/erc1155/read/get-all.ts deleted file mode 100644 index b3deb9017..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get-all.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftSchema } from "../../../../../schemas/nft"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc1155ContractParamSchema; -const querystringSchema = Type.Object({ - start: Type.Optional( - Type.Integer({ - description: "The start token ID for paginated results. Defaults to 0.", - minimum: 0, - }), - ), - count: Type.Optional( - Type.Integer({ - description: "The page count for paginated results. Defaults to 100.", - minimum: 1, - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(nftSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - metadata: { - id: "0", - uri: "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - name: "My Edition NFT", - description: "My Edition NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - type: "ERC1155", - supply: "100", - quantityOwned: "100", - }, - ], - }, -]; - -// LOGIC -export async function erc1155GetAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/get-all", - schema: { - summary: "Get all details", - description: "Get details for all tokens in an ERC-1155 contract.", - tags: ["ERC1155"], - operationId: "erc1155-getAll", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.erc1155.getAll({ - start, - count, - }); - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get-claim-ineligibility-reasons.ts b/src/server/routes/contract/extensions/erc1155/read/get-claim-ineligibility-reasons.ts deleted file mode 100644 index af758f40a..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get-claim-ineligibility-reasons.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { ClaimEligibility } from "@thirdweb-dev/sdk"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { NumberStringSchema } from "../../../../../schemas/number"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: - "The token ID of the NFT you want to check if the wallet address can claim.", - }), - quantity: { - ...NumberStringSchema, - description: "The amount of tokens to claim.", - }, - addressToCheck: Type.Optional({ - ...AddressSchema, - description: "The wallet address to check if it can claim tokens.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(Type.Union([Type.String(), Type.Enum(ClaimEligibility)])), -}); - -// LOGIC -export async function erc1155GetClaimIneligibilityReasons( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/get-claim-ineligibility-reasons", - schema: { - summary: "Get claim ineligibility reasons", - description: - "Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any.", - tags: ["ERC1155"], - operationId: "erc1155-getClaimIneligibilityReasons", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { quantity, tokenId, addressToCheck } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = - await contract.erc1155.claimConditions.getClaimIneligibilityReasons( - tokenId, - quantity, - addressToCheck, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get-claimer-proofs.ts b/src/server/routes/contract/extensions/erc1155/read/get-claimer-proofs.ts deleted file mode 100644 index d1cd466ce..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get-claimer-proofs.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { claimerProofSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: - "The token ID of the NFT you want to get the claimer proofs for.", - }), - walletAddress: { - ...AddressSchema, - description: "The wallet address to get the merkle proofs for.", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: claimerProofSchema, -}); - -// LOGIC -export async function erc1155GetClaimerProofs(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/get-claimer-proofs", - schema: { - summary: "Get claimer proofs", - description: - "Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address.", - tags: ["ERC1155"], - operationId: "erc1155-getClaimerProofs", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { tokenId, walletAddress } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = - await contract.erc1155.claimConditions.getClaimerProofs( - tokenId, - walletAddress, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get-owned.ts b/src/server/routes/contract/extensions/erc1155/read/get-owned.ts deleted file mode 100644 index ab056da46..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get-owned.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { nftSchema } from "../../../../../schemas/nft"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc1155ContractParamSchema; -const querystringSchema = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Address of the wallet to get NFTs for", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(nftSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - metadata: { - id: "0", - uri: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - owner: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - type: "ERC1155", - supply: - "600000150000000000000000000000000000000000009000000000000000000000712", - quantityOwned: "9000000000000000000000000", - }, - ], - }, -]; - -// LOGIC -export async function erc1155GetOwned(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/get-owned", - schema: { - summary: "Get owned tokens", - description: - "Get all tokens in an ERC-1155 contract owned by a specific wallet.", - tags: ["ERC1155"], - operationId: "erc1155-getOwned", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { walletAddress } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.erc1155.getOwned(walletAddress); - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/get.ts b/src/server/routes/contract/extensions/erc1155/read/get.ts deleted file mode 100644 index 2f5b7cb9c..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/get.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftSchema } from "../../../../../schemas/nft"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc1155ContractParamSchema; - -// QUERY -const querystringSchema = Type.Object({ - tokenId: Type.String({ - description: "The tokenId of the NFT to retrieve", - examples: ["0"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: nftSchema, -}); - -responseSchema.examples = [ - { - result: { - metadata: { - id: "0", - uri: "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - name: "My Edition NFT", - description: "My Edition NFT description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - type: "ERC1155", - supply: "100", - quantityOwned: "100", - }, - }, -]; - -// LOGIC -export async function erc1155Get(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/get", - schema: { - summary: "Get details", - description: "Get the details for a token in an ERC-1155 contract.", - tags: ["ERC1155"], - operationId: "erc1155-get", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.erc1155.get(tokenId); - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/is-approved.ts b/src/server/routes/contract/extensions/erc1155/read/is-approved.ts deleted file mode 100644 index 495bd8dc3..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/is-approved.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const querystringSchema = Type.Object({ - ownerWallet: Type.String({ - description: "Address of the wallet who owns the NFT", - examples: ["0x3EcDBF3B911d0e9052b64850693888b008e18373"], - }), - operator: Type.String({ - description: "Address of the operator to check approval on", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.Boolean()), -}); - -responseSchema.examples = [ - { - result: true, - }, -]; - -// LOGIC -export async function erc1155IsApproved(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/is-approved", - schema: { - summary: "Check if approved transfers", - description: - "Check if the specific wallet has approved transfers from a specific operator wallet.", - tags: ["ERC1155"], - operationId: "erc1155-isApproved", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { ownerWallet, operator } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.isApproved( - ownerWallet, - operator, - ); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/signature-generate.ts b/src/server/routes/contract/extensions/erc1155/read/signature-generate.ts deleted file mode 100644 index ab2c14ebd..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/signature-generate.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract, type Address, type Hex } from "thirdweb"; -import type { NFTInput } from "thirdweb/dist/types/utils/nft/parseNft"; -import { generateMintSignature } from "thirdweb/extensions/erc1155"; -import { getAccount } from "../../../../../../shared/utils/account"; -import { getContract as getContractV4 } from "../../../../../../shared/utils/cache/get-contract"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { maybeBigInt } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { createCustomError } from "../../../../../middleware/error"; -import { thirdwebSdkVersionSchema } from "../../../../../schemas/http-headers/thirdweb-sdk-version"; -import { - nftInputSchema, - signature1155InputSchema, - signature1155OutputSchema, - type ercNFTResponseType, -} from "../../../../../schemas/nft"; -import { - TokenAmountStringSchema, - WeiAmountStringSchema, -} from "../../../../../schemas/number"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { checkAndReturnNFTSignaturePayload } from "../../../../../utils/validator"; - -// v4 sdk -const requestBodySchemaV4 = signature1155InputSchema; -const responseSchemaV4 = Type.Object({ - payload: signature1155OutputSchema, - signature: Type.String(), -}); - -// v5 sdk -const requestBodySchemaV5 = Type.Intersect([ - Type.Object({ - contractType: Type.Optional( - Type.Union([ - Type.Literal("TokenERC1155"), - Type.Literal("SignatureMintERC1155"), - ]), - ), - to: Type.String(), - quantity: Type.String(), - royaltyRecipient: Type.Optional(Type.String()), - royaltyBps: Type.Optional(Type.Integer({ minimum: 0, maximum: 10_000 })), - primarySaleRecipient: Type.Optional(Type.String()), - pricePerToken: Type.Optional(TokenAmountStringSchema), - pricePerTokenWei: Type.Optional(WeiAmountStringSchema), - currency: Type.Optional(Type.String()), - validityStartTimestamp: Type.Integer({ minimum: 0 }), - validityEndTimestamp: Type.Optional(Type.Integer({ minimum: 0 })), - uid: Type.Optional(Type.String()), - }), - Type.Union([ - Type.Object({ metadata: Type.Union([nftInputSchema, Type.String()]) }), - Type.Object({ tokenId: Type.String() }), - ]), -]); -const responseSchemaV5 = Type.Object({ - payload: Type.Object({ - to: Type.String(), - royaltyRecipient: Type.String(), - royaltyBps: Type.String(), - primarySaleRecipient: Type.String(), - tokenId: Type.String(), - uri: Type.String(), - quantity: Type.String(), - pricePerToken: Type.String(), - currency: Type.String(), - validityStartTimestamp: Type.Integer(), - validityEndTimestamp: Type.Integer(), - uid: Type.String(), - }), - signature: Type.String(), -}); - -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Union([ - requestBodySchemaV4, - requestBodySchemaV5, -]); -const responseSchema = Type.Object({ - result: Type.Union([responseSchemaV4, responseSchemaV5]), -}); - -responseSchema.example = { - result: "1", -}; - -// LOGIC -export async function erc1155SignatureGenerate(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/signature/generate", - schema: { - summary: "Generate signature", - description: - "Generate a signature granting access for another wallet to mint tokens from this ERC-1155 contract. This method is typically called by the token contract owner.", - tags: ["ERC1155"], - operationId: "erc1155-signatureGenerate", - params: requestSchema, - body: requestBodySchema, - headers: { - ...walletWithAAHeaderSchema.properties, - ...thirdwebSdkVersionSchema.properties, - }, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - } = request.headers as Static; - const { "x-thirdweb-sdk-version": sdkVersion } = - request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - - // Use v5 SDK if "x-thirdweb-sdk-version" header is set. - if (sdkVersion === "5") { - const args = request.body as Static; - const { - contractType, - to, - quantity, - royaltyRecipient, - royaltyBps, - primarySaleRecipient, - pricePerToken, - pricePerTokenWei, - currency, - validityStartTimestamp, - validityEndTimestamp, - uid, - } = args; - - let nftInput: { metadata: NFTInput | string } | { tokenId: bigint }; - if ("metadata" in args) { - nftInput = { metadata: args.metadata }; - } else if ("tokenId" in args) { - nftInput = { tokenId: BigInt(args.tokenId) }; - } else { - throw createCustomError( - `Missing "metadata" or "tokenId".`, - StatusCodes.BAD_REQUEST, - "MISSING_PARAMETERS", - ); - } - - const contract = getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - const account = await getAccount({ - chainId, - from: walletAddress as Address, - accountAddress: accountAddress as Address, - }); - - const { payload, signature } = await generateMintSignature({ - contract, - account, - contractType, - mintRequest: { - to, - quantity: BigInt(quantity), - royaltyRecipient, - royaltyBps, - primarySaleRecipient, - pricePerToken, - pricePerTokenWei: maybeBigInt(pricePerTokenWei), - currency, - validityStartTimestamp: new Date(validityStartTimestamp * 1000), - validityEndTimestamp: validityEndTimestamp - ? new Date(validityEndTimestamp * 1000) - : undefined, - uid: uid as Hex | undefined, - ...nftInput, - }, - }); - - return reply.status(StatusCodes.OK).send({ - result: { - payload: { - ...payload, - royaltyBps: payload.royaltyBps.toString(), - tokenId: payload.tokenId.toString(), - quantity: payload.quantity.toString(), - pricePerToken: payload.pricePerToken.toString(), - validityStartTimestamp: Number(payload.validityStartTimestamp), - validityEndTimestamp: Number(payload.validityEndTimestamp), - }, - signature, - }, - }); - } - - // Use v4 SDK. - const { - to, - currencyAddress, - metadata, - mintEndTime, - mintStartTime, - price = "0", - primarySaleRecipient, - quantity, - royaltyBps, - royaltyRecipient, - uid, - } = request.body as Static; - - const contract = await getContractV4({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const payload = checkAndReturnNFTSignaturePayload< - Static, - ercNFTResponseType - >({ - to, - currencyAddress, - metadata, - mintEndTime, - mintStartTime, - price, - primarySaleRecipient, - quantity, - royaltyBps, - royaltyRecipient, - uid, - }); - - const signedPayload = await contract.erc1155.signature.generate(payload); - reply.status(StatusCodes.OK).send({ - result: { - ...signedPayload, - payload: { - ...signedPayload.payload, - quantity: signedPayload.payload.quantity.toString(), - royaltyBps: signedPayload.payload.royaltyBps.toString(), - mintStartTime: signedPayload.payload.mintStartTime.toNumber(), - mintEndTime: signedPayload.payload.mintEndTime.toNumber(), - tokenId: signedPayload.payload.tokenId.toString(), - }, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/total-count.ts b/src/server/routes/contract/extensions/erc1155/read/total-count.ts deleted file mode 100644 index 8855ea0dd..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/total-count.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc1155ContractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -responseSchema.example = { - result: "1", -}; - -// LOGIC -export async function erc1155TotalCount(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/total-count", - schema: { - summary: "Get total supply", - description: - "Get the total supply in circulation for this ERC-1155 contract.", - tags: ["ERC1155"], - operationId: "erc1155-totalCount", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.totalCount(); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/read/total-supply.ts b/src/server/routes/contract/extensions/erc1155/read/total-supply.ts deleted file mode 100644 index c38c68e0d..000000000 --- a/src/server/routes/contract/extensions/erc1155/read/total-supply.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc1155ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc1155ContractParamSchema; -const querystringSchema = Type.Object({ - tokenId: Type.String({ - description: "The tokenId of the NFT to retrieve", - examples: ["0"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -responseSchema.example = [ - { - result: "100000000", - }, -]; - -// LOGIC -export async function erc1155TotalSupply(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc1155/total-supply", - schema: { - summary: "Get total supply", - description: - "Get the total supply in circulation for this ERC-1155 contract.", - tags: ["ERC1155"], - operationId: "erc1155-totalSupply", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc1155.totalSupply(tokenId); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/airdrop.ts b/src/server/routes/contract/extensions/erc1155/write/airdrop.ts deleted file mode 100644 index 47ba5e7f6..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/airdrop.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.String({ - description: "Token ID of the NFT to airdrop", - }), - addresses: Type.Array( - Type.Object({ - address: AddressSchema, - quantity: Type.String({ - default: "1", - }), - }), - { - description: "Addresses and quantities to airdrop to", - }, - ), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - tokenId: "0", - addresses: [ - { - address: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - quantity: "1", - }, - { - address: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - quantity: "1", - }, - ], - }, -]; - -export async function erc1155airdrop(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/airdrop", - schema: { - summary: "Airdrop tokens", - description: "Airdrop ERC-1155 tokens to specific wallets.", - tags: ["ERC1155"], - operationId: "erc1155-airdrop", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenId, addresses, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = await contract.erc1155.airdrop.prepare(tokenId, addresses); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/burn-batch.ts b/src/server/routes/contract/extensions/erc1155/write/burn-batch.ts deleted file mode 100644 index e24ae64c3..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/burn-batch.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - tokenIds: Type.Array( - Type.String({ - description: "The token IDs to burn", - }), - ), - amounts: Type.Array( - Type.String({ - description: "The amounts of tokens to burn", - }), - ), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - tokenIds: ["0", "1"], - amounts: ["1", "1"], - }, -]; - -// OUTPUT - -export async function erc1155burnBatch(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/burn-batch", - schema: { - summary: "Burn tokens (batch)", - description: "Burn a batch of ERC-1155 tokens in the caller wallet.", - tags: ["ERC1155"], - operationId: "erc1155-burnBatch", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenIds, amounts, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.burnBatch.prepare(tokenIds, amounts); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/burn.ts b/src/server/routes/contract/extensions/erc1155/write/burn.ts deleted file mode 100644 index 10ffd4688..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/burn.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.String({ - description: "The token ID to burn", - }), - amount: Type.String({ - description: "The amount of tokens to burn", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - tokenId: "0", - amount: "1", - }, -]; - -export async function erc1155burn(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/burn", - schema: { - summary: "Burn token", - description: "Burn ERC-1155 tokens in the caller wallet.", - tags: ["ERC1155"], - operationId: "erc1155-burn", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenId, amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.burn.prepare(tokenId, amount); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/claim-to.ts b/src/server/routes/contract/extensions/erc1155/write/claim-to.ts deleted file mode 100644 index fce1fd82f..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/claim-to.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { claimTo } from "thirdweb/extensions/erc1155"; -import { getContractV5 } from "../../../../../../shared/utils/cache/get-contractv5"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to claim the NFT to", - }, - tokenId: Type.String({ - description: "Token ID of the NFT to claim", - }), - quantity: Type.String({ - description: "Quantity of NFTs to mint", - }), - singlePhaseDrop: Type.Optional( - Type.Boolean({ - description: "Whether the drop is a single phase drop", - }), - ), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "0", - quantity: "1", - }, -]; - -export async function erc1155claimTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/claim-to", - schema: { - summary: "Claim tokens to wallet", - description: "Claim ERC-1155 tokens to a specific wallet.", - tags: ["ERC1155"], - operationId: "erc1155-claimTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, tokenId, quantity, singlePhaseDrop, txOverrides } = - request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContractV5({ - chainId, - contractAddress, - }); - - const transaction = claimTo({ - contract, - from: fromAddress as Address, - to: receiver, - quantity: BigInt(quantity), - tokenId: BigInt(tokenId), - singlePhaseDrop, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/lazy-mint.ts b/src/server/routes/contract/extensions/erc1155/write/lazy-mint.ts deleted file mode 100644 index 04fc4b6b0..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/lazy-mint.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftOrInputSchema } from "../../../../../schemas/nft"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - metadatas: Type.Array(nftOrInputSchema), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - metadatas: [ - { - name: "My NFT #1", - description: "My NFT #1 description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - { - name: "My NFT #2", - description: "My NFT #2 description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - ], - }, -]; - -export async function erc1155lazyMint(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/lazy-mint", - schema: { - summary: "Lazy mint", - description: "Lazy mint ERC-1155 tokens to be claimed in the future.", - tags: ["ERC1155"], - operationId: "erc1155-lazyMint", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { metadatas, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.lazyMint.prepare(metadatas); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/mint-additional-supply-to.ts b/src/server/routes/contract/extensions/erc1155/write/mint-additional-supply-to.ts deleted file mode 100644 index a63f73c79..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/mint-additional-supply-to.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to mint the NFT to", - }, - tokenId: Type.String({ - description: "Token ID to mint additional supply to", - }), - additionalSupply: Type.String({ - description: "The amount of supply to mint", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "1", - additionalSupply: "10", - }, -]; - -export async function erc1155mintAdditionalSupplyTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/mint-additional-supply-to", - schema: { - summary: "Mint additional supply", - description: - "Mint additional supply of ERC-1155 tokens to a specific wallet.", - tags: ["ERC1155"], - operationId: "erc1155-mintAdditionalSupplyTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, additionalSupply, tokenId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.mintAdditionalSupplyTo.prepare( - receiver, - tokenId, - additionalSupply, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/mint-batch-to.ts b/src/server/routes/contract/extensions/erc1155/write/mint-batch-to.ts deleted file mode 100644 index 595ea6311..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/mint-batch-to.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { nftAndSupplySchema } from "../../../../../schemas/nft"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to mint the NFT to", - }, - metadataWithSupply: Type.Array(nftAndSupplySchema), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - metadataWithSupply: [ - { - metadata: { - name: "My NFT #1", - description: "My NFT #1 description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - supply: "10", - }, - { - metadata: { - name: "My NFT #2", - description: "My NFT #2 description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - supply: "5", - }, - ], - }, -]; - -// OUTPUT - -export async function erc1155mintBatchTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/mint-batch-to", - schema: { - summary: "Mint tokens (batch)", - description: - "Mint ERC-1155 tokens to multiple wallets in one transaction.", - tags: ["ERC1155"], - operationId: "erc1155-mintBatchTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, metadataWithSupply, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.mintBatchTo.prepare( - receiver, - metadataWithSupply, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/mint-to.ts b/src/server/routes/contract/extensions/erc1155/write/mint-to.ts deleted file mode 100644 index 6508c87f6..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/mint-to.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { mintTo } from "thirdweb/extensions/erc1155"; -import type { NFTInput } from "thirdweb/utils"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { nftAndSupplySchema } from "../../../../../schemas/nft"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to mint the NFT to", - }, - metadataWithSupply: nftAndSupplySchema, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - metadataWithSupply: { - metadata: { - name: "My NFT", - description: "My NFT description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - supply: "100", - }, - }, -]; - -// OUTPUT - -export async function erc1155mintTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/mint-to", - schema: { - summary: "Mint tokens", - description: "Mint ERC-1155 tokens to a specific wallet.", - tags: ["ERC1155"], - operationId: "erc1155-mintTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain: _chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, metadataWithSupply, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(_chain); - const chain = await getChain(chainId); - - const contract = getContract({ - chain, - client: thirdwebClient, - address: contractAddress, - }); - - // Backward compatibility: Transform the request body's v4 shape to v5. - const { metadata, supply } = metadataWithSupply; - const nft: NFTInput | string = - typeof metadata === "string" - ? metadata - : { - name: metadata.name?.toString() ?? undefined, - description: metadata.description ?? undefined, - image: metadata.image ?? undefined, - animation_url: metadata.animation_url ?? undefined, - external_url: metadata.external_url ?? undefined, - background_color: metadata.background_color ?? undefined, - properties: metadata.properties ?? undefined, - attributes: metadata.attributes ?? undefined, - }; - const transaction = mintTo({ - contract, - to: receiver, - nft, - supply: BigInt(supply), - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - extension: "erc1155", - functionName: "mintTo", - shouldSimulate: simulateTx, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/set-approval-for-all.ts b/src/server/routes/contract/extensions/erc1155/write/set-approval-for-all.ts deleted file mode 100644 index 5891a9dd1..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/set-approval-for-all.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - operator: Type.String({ - description: "Address of the operator to give approval to", - }), - approved: Type.Boolean({ - description: "whether to approve or revoke approval", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - operator: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - approved: "true", - }, -]; - -// OUTPUT - -export async function erc1155SetApprovalForAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/set-approval-for-all", - schema: { - summary: "Set approval for all", - description: - "Approve or remove operator as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller.", - tags: ["ERC1155"], - operationId: "erc1155-setApprovalForAll", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { operator, approved, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.setApprovalForAll.prepare( - operator, - approved, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/set-batch-claim-conditions.ts b/src/server/routes/contract/extensions/erc1155/write/set-batch-claim-conditions.ts deleted file mode 100644 index 4e432eae3..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/set-batch-claim-conditions.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type setBatchSantiziedClaimConditionsRequestSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - claimConditionsForToken: Type.Array( - Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: "ID of the token to set the claim conditions for", - }), - claimConditions: Type.Array(claimConditionInputSchema), - }), - ), - resetClaimEligibilityForAll: Type.Optional(Type.Boolean()), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc1155SetBatchClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/set-batch", - schema: { - summary: "Overwrite the claim conditions for a specific token ID..", - description: - "Allows you to set claim conditions for multiple token IDs in a single transaction.", - tags: ["ERC1155"], - operationId: "erc1155-claimConditionsUpdate", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { - claimConditionsForToken, - resetClaimEligibilityForAll, - txOverrides, - } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInputs: Static< - typeof setBatchSantiziedClaimConditionsRequestSchema - > = { - claimConditionsForToken: claimConditionsForToken.map((item) => { - return { - tokenId: item.tokenId, - claimConditions: item.claimConditions.map((condition) => { - return { - ...condition, - startTime: condition.startTime - ? isUnixEpochTimestamp( - Number.parseInt(condition.startTime.toString()), - ) - ? new Date( - Number.parseInt(condition.startTime.toString()) * 1000, - ) - : new Date(condition.startTime) - : undefined, - }; - }), - }; - }), - resetClaimEligibilityForAll, - }; - const tx = await contract.erc1155.claimConditions.setBatch.prepare( - sanitizedClaimConditionInputs.claimConditionsForToken, - resetClaimEligibilityForAll, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/set-claim-conditions.ts b/src/server/routes/contract/extensions/erc1155/write/set-claim-conditions.ts deleted file mode 100644 index 9b30d33ee..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/set-claim-conditions.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type sanitizedClaimConditionInputSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: "ID of the token to set the claim conditions for", - }), - claimConditionInputs: Type.Array(claimConditionInputSchema), - resetClaimEligibilityForAll: Type.Optional(Type.Boolean()), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc1155SetClaimCondition(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/set", - schema: { - summary: "Overwrite the claim conditions for a specific token ID..", - description: - "Overwrite the claim conditions for a specific token ID. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - tags: ["ERC1155"], - operationId: "erc1155-setClaimConditions", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { - tokenId, - claimConditionInputs, - resetClaimEligibilityForAll, - txOverrides, - } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInputs: Static< - typeof sanitizedClaimConditionInputSchema - >[] = claimConditionInputs.map((item) => { - return { - ...item, - startTime: item.startTime - ? isUnixEpochTimestamp(Number.parseInt(item.startTime.toString())) - ? new Date(Number.parseInt(item.startTime.toString()) * 1000) - : new Date(item.startTime) - : undefined, - }; - }); - - const tx = await contract.erc1155.claimConditions.set.prepare( - tokenId, - sanitizedClaimConditionInputs, - resetClaimEligibilityForAll, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/signature-mint.ts b/src/server/routes/contract/extensions/erc1155/write/signature-mint.ts deleted file mode 100644 index 05c50724a..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/signature-mint.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { SignedPayload1155 } from "@thirdweb-dev/sdk"; -import { BigNumber } from "ethers"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { signature1155OutputSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - payload: signature1155OutputSchema, - signature: Type.String(), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - payload: {}, - signature: "", - }, -]; - -export async function erc1155SignatureMint(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/signature/mint", - schema: { - summary: "Signature mint", - description: "Mint ERC-1155 tokens from a generated signature.", - tags: ["ERC1155"], - operationId: "erc1155-signatureMint", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { payload, signature, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const signedPayload: SignedPayload1155 = { - payload: { - ...payload, - royaltyBps: BigNumber.from(payload.royaltyBps), - quantity: BigNumber.from(payload.quantity), - mintStartTime: BigNumber.from(payload.mintStartTime), - mintEndTime: BigNumber.from(payload.mintEndTime), - tokenId: BigNumber.from(payload.tokenId), - }, - signature, - }; - const tx = await contract.erc1155.signature.mint.prepare(signedPayload); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/transfer-from.ts b/src/server/routes/contract/extensions/erc1155/write/transfer-from.ts deleted file mode 100644 index 67e046a02..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/transfer-from.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract, type Hex } from "thirdweb"; -import { safeTransferFrom } from "thirdweb/extensions/erc1155"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { getChecksumAddress } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema, HexSchema } from "../../../../../schemas/address"; -import { NumberStringSchema } from "../../../../../schemas/number"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - from: { - ...AddressSchema, - description: "The sender address.", - }, - to: { - ...AddressSchema, - description: "The recipient address.", - }, - tokenId: { - ...NumberStringSchema, - description: "The token ID to transfer.", - }, - amount: { - ...NumberStringSchema, - description: "The amount of tokens to transfer.", - }, - data: Type.Optional(HexSchema), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - from: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - to: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "0", - amount: "1", - }, -]; - -// OUTPUT - -export async function erc1155transferFrom(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/transfer-from", - schema: { - summary: "Transfer token from wallet", - description: - "Transfer an ERC-1155 token from the connected wallet to another wallet. Requires allowance.", - tags: ["ERC1155"], - operationId: "erc1155-transferFrom", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { from, to, tokenId, amount, data, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - - const transaction = safeTransferFrom({ - contract, - from: getChecksumAddress(from), - to: getChecksumAddress(to), - tokenId: BigInt(tokenId), - value: BigInt(amount), - data: (data as Hex | undefined) ?? "0x", - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: getChecksumAddress(walletAddress), - toAddress: getChecksumAddress(contractAddress), - accountAddress: getChecksumAddress(accountAddress), - accountFactoryAddress: getChecksumAddress(accountFactoryAddress), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - functionName: "safeTransferFrom", - extension: "erc1155", - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/transfer.ts b/src/server/routes/contract/extensions/erc1155/write/transfer.ts deleted file mode 100644 index 4c1732175..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/transfer.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract, type Hex } from "thirdweb"; -import { safeTransferFrom } from "thirdweb/extensions/erc1155"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { getChecksumAddress } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema, HexSchema } from "../../../../../schemas/address"; -import { NumberStringSchema } from "../../../../../schemas/number"; -import { - erc1155ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc1155ContractParamSchema; -const requestBodySchema = Type.Object({ - to: { - ...AddressSchema, - description: "The recipient address.", - }, - tokenId: Type.String({ - ...NumberStringSchema, - description: "The token ID to transfer.", - }), - amount: Type.String({ - ...NumberStringSchema, - description: "The amount of tokens to transfer.", - }), - data: Type.Optional(HexSchema), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - to: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "0", - amount: "1", - }, -]; - -export async function erc1155transfer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/transfer", - schema: { - summary: "Transfer token", - description: "Transfer an ERC-1155 token from the caller wallet.", - tags: ["ERC1155"], - operationId: "erc1155-transfer", - params: requestSchema, - headers: walletWithAAHeaderSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { to, tokenId, amount, data, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - - const transaction = safeTransferFrom({ - contract, - from: getChecksumAddress(walletAddress), - to: getChecksumAddress(to), - tokenId: BigInt(tokenId), - value: BigInt(amount), - data: (data as Hex | undefined) ?? "0x", - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: getChecksumAddress(walletAddress), - toAddress: getChecksumAddress(contractAddress), - accountAddress: getChecksumAddress(accountAddress), - accountFactoryAddress: getChecksumAddress(accountFactoryAddress), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - functionName: "safeTransferFrom", - extension: "erc1155", - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/update-claim-conditions.ts b/src/server/routes/contract/extensions/erc1155/write/update-claim-conditions.ts deleted file mode 100644 index c0ba8f104..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/update-claim-conditions.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type sanitizedClaimConditionInputSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: "Token ID to update claim phase for", - }), - claimConditionInput: claimConditionInputSchema, - index: Type.Integer({ - description: "Index of the claim condition to update", - minimum: 0, - }), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc1155UpdateClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/claim-conditions/update", - schema: { - summary: "Update a single claim phase.", - description: - "Update a single claim phase on a specific token ID, by providing the index of the claim phase and the new phase configuration.", - tags: ["ERC1155"], - operationId: "erc1155-updateClaimConditions", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenId, claimConditionInput, index, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInput: Static< - typeof sanitizedClaimConditionInputSchema - > = { - ...claimConditionInput, - startTime: claimConditionInput.startTime - ? isUnixEpochTimestamp( - Number.parseInt(claimConditionInput.startTime.toString()), - ) - ? new Date( - Number.parseInt(claimConditionInput.startTime.toString()) * - 1000, - ) - : new Date(claimConditionInput.startTime) - : undefined, - }; - const tx = await contract.erc1155.claimConditions.update.prepare( - tokenId, - index, - sanitizedClaimConditionInput, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc1155/write/update-token-metadata.ts b/src/server/routes/contract/extensions/erc1155/write/update-token-metadata.ts deleted file mode 100644 index bcc6fbef1..000000000 --- a/src/server/routes/contract/extensions/erc1155/write/update-token-metadata.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftMetadataInputSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.String({ - description: "Token ID to update metadata", - }), - metadata: nftMetadataInputSchema, - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc1155UpdateTokenMetadata(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc1155/token/update", - schema: { - summary: "Update token metadata", - description: "Update the metadata for an ERC1155 token.", - tags: ["ERC1155"], - operationId: "erc1155-updateTokenMetadata", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenId, metadata, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc1155.updateMetadata.prepare( - tokenId, - metadata, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc1155", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/index.ts b/src/server/routes/contract/extensions/erc20/index.ts deleted file mode 100644 index c0cc43892..000000000 --- a/src/server/routes/contract/extensions/erc20/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { erc20AllowanceOf } from "./read/allowance-of"; -import { erc20BalanceOf } from "./read/balance-of"; -import { erc20CanClaim } from "./read/can-claim"; -import { erc20GetMetadata } from "./read/get"; -import { erc20GetActiveClaimConditions } from "./read/get-active-claim-conditions"; -import { erc20GetAllClaimConditions } from "./read/get-all-claim-conditions"; -import { erc20GetClaimIneligibilityReasons } from "./read/get-claim-ineligibility-reasons"; -import { erc20GetClaimerProofs } from "./read/get-claimer-proofs"; -import { erc20SignatureGenerate } from "./read/signature-generate"; -import { erc20TotalSupply } from "./read/total-supply"; -import { erc20burn } from "./write/burn"; -import { erc20burnFrom } from "./write/burn-from"; -import { erc20claimTo } from "./write/claim-to"; -import { erc20mintBatchTo } from "./write/mint-batch-to"; -import { erc20mintTo } from "./write/mint-to"; -import { erc20SetAlowance } from "./write/set-allowance"; -import { erc20SetClaimConditions } from "./write/set-claim-conditions"; -import { erc20SignatureMint } from "./write/signature-mint"; -import { erc20Transfer } from "./write/transfer"; -import { erc20TransferFrom } from "./write/transfer-from"; -import { erc20UpdateClaimConditions } from "./write/update-claim-conditions"; - -export const erc20Routes = async (fastify: FastifyInstance) => { - // GET - await fastify.register(erc20AllowanceOf); - await fastify.register(erc20BalanceOf); - await fastify.register(erc20GetMetadata); - await fastify.register(erc20TotalSupply); - await fastify.register(erc20SignatureGenerate); - await fastify.register(erc20CanClaim); - await fastify.register(erc20GetActiveClaimConditions); - await fastify.register(erc20GetAllClaimConditions); - await fastify.register(erc20GetClaimIneligibilityReasons); - await fastify.register(erc20GetClaimerProofs); - - //POST - await fastify.register(erc20SetAlowance); - await fastify.register(erc20Transfer); - await fastify.register(erc20TransferFrom); - await fastify.register(erc20burn); - await fastify.register(erc20burnFrom); - await fastify.register(erc20claimTo); - await fastify.register(erc20mintBatchTo); - await fastify.register(erc20mintTo); - await fastify.register(erc20SignatureMint); - await fastify.register(erc20SetClaimConditions); - await fastify.register(erc20UpdateClaimConditions); -}; diff --git a/src/server/routes/contract/extensions/erc20/read/allowance-of.ts b/src/server/routes/contract/extensions/erc20/read/allowance-of.ts deleted file mode 100644 index 3020eecee..000000000 --- a/src/server/routes/contract/extensions/erc20/read/allowance-of.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { erc20MetadataSchema } from "../../../../../schemas/erc20"; -import { - erc20ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const querystringSchema = Type.Object({ - ownerWallet: Type.String({ - description: "Address of the wallet who owns the funds", - examples: ["0x3EcDBF3B911d0e9052b64850693888b008e18373"], - }), - spenderWallet: Type.String({ - description: "Address of the wallet to check token allowance", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: erc20MetadataSchema, -}); - -responseSchema.example = { - result: { - name: "ERC20", - symbol: "", - decimals: "18", - value: "0", - displayValue: "0.0", - }, -}; - -// LOGIC -export async function erc20AllowanceOf(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/allowance-of", - schema: { - summary: "Get token allowance", - description: - "Get the allowance of a specific wallet for an ERC-20 contract.", - tags: ["ERC20"], - operationId: "erc20-allowanceOf", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { spenderWallet, ownerWallet } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.allowanceOf( - ownerWallet ? ownerWallet : "", - spenderWallet ? spenderWallet : "", - ); - reply.status(StatusCodes.OK).send({ - result: { - name: returnData.name, - symbol: returnData.symbol, - decimals: returnData.decimals.toString(), - displayValue: returnData.displayValue, - value: returnData.value.toString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/balance-of.ts b/src/server/routes/contract/extensions/erc20/read/balance-of.ts deleted file mode 100644 index e0350946d..000000000 --- a/src/server/routes/contract/extensions/erc20/read/balance-of.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { erc20MetadataSchema } from "../../../../../schemas/erc20"; -import { - erc20ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const querystringSchema = Type.Object({ - wallet_address: { - ...AddressSchema, - description: "Address of the wallet to check token balance", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: erc20MetadataSchema, -}); - -responseSchema.example = [ - { - result: { - name: "ERC20", - symbol: "", - decimals: "18", - value: "7799999999615999974", - displayValue: "7.799999999615999974", - }, - }, -]; - -// LOGIC -export async function erc20BalanceOf(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/balance-of", - schema: { - summary: "Get token balance", - description: - "Get the balance of a specific wallet address for this ERC-20 contract.", - tags: ["ERC20"], - operationId: "erc20-balanceOf", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { wallet_address } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.balanceOf(wallet_address); - reply.status(StatusCodes.OK).send({ - result: { - name: returnData.name, - symbol: returnData.symbol, - decimals: returnData.decimals.toString(), - displayValue: returnData.displayValue, - value: returnData.value.toString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/can-claim.ts b/src/server/routes/contract/extensions/erc20/read/can-claim.ts deleted file mode 100644 index 413b24cca..000000000 --- a/src/server/routes/contract/extensions/erc20/read/can-claim.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - quantity: Type.String({ - description: "The amount of tokens to claim.", - }), - addressToCheck: Type.Optional( - Type.String({ - description: - "The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc.", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Boolean(), -}); - -// LOGIC -export async function erc20CanClaim(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/can-claim", - schema: { - summary: "Check if tokens are available for claiming", - description: - "Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim.", - tags: ["ERC20"], - operationId: "erc20-canClaim", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { quantity, addressToCheck } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.claimConditions.canClaim( - quantity, - addressToCheck, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/get-active-claim-conditions.ts b/src/server/routes/contract/extensions/erc20/read/get-active-claim-conditions.ts deleted file mode 100644 index 97c1b1ea3..000000000 --- a/src/server/routes/contract/extensions/erc20/read/get-active-claim-conditions.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { claimConditionOutputSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - withAllowList: Type.Optional( - Type.Boolean({ - description: - "Provide a boolean value to include the allowlist in the response.", - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: claimConditionOutputSchema, -}); - -// LOGIC -export async function erc20GetActiveClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/get-active", - schema: { - summary: "Retrieve the currently active claim phase, if any.", - description: "Retrieve the currently active claim phase, if any.", - tags: ["ERC20"], - operationId: "erc20-getActiveClaimConditions", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { withAllowList } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.claimConditions.getActive({ - withAllowList, - }); - reply.status(StatusCodes.OK).send({ - result: { - ...returnData, - price: returnData.price.toString(), - waitInSeconds: returnData.waitInSeconds.toString(), - currencyMetadata: { - ...returnData.currencyMetadata, - value: returnData.currencyMetadata.value.toString(), - }, - startTime: returnData.startTime.toISOString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/get-all-claim-conditions.ts b/src/server/routes/contract/extensions/erc20/read/get-all-claim-conditions.ts deleted file mode 100644 index f6bf68f94..000000000 --- a/src/server/routes/contract/extensions/erc20/read/get-all-claim-conditions.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { claimConditionOutputSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - withAllowList: Type.Optional( - Type.Boolean({ - description: - "Provide a boolean value to include the allowlist in the response.", - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(claimConditionOutputSchema), -}); - -// LOGIC -export async function erc20GetAllClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/get-all", - schema: { - summary: "Get all the claim phases configured.", - description: "Get all the claim phases configured on the drop contract.", - tags: ["ERC20"], - operationId: "erc20-getAllClaimConditions", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { withAllowList } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.claimConditions.getAll({ - withAllowList, - }); - - const sanitizedReturnData = returnData.map((item) => { - return { - ...item, - price: item.price.toString(), - waitInSeconds: item.waitInSeconds.toString(), - currencyMetadata: { - ...item.currencyMetadata, - value: item.currencyMetadata.value.toString(), - }, - startTime: item.startTime.toISOString(), - }; - }); - - reply.status(StatusCodes.OK).send({ - result: sanitizedReturnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/get-claim-ineligibility-reasons.ts b/src/server/routes/contract/extensions/erc20/read/get-claim-ineligibility-reasons.ts deleted file mode 100644 index 40629cbba..000000000 --- a/src/server/routes/contract/extensions/erc20/read/get-claim-ineligibility-reasons.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { ClaimEligibility } from "@thirdweb-dev/sdk"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - quantity: Type.String({ - description: "The amount of tokens to claim.", - }), - addressToCheck: Type.Optional( - Type.String({ - description: "The wallet address to check if it can claim tokens.", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(Type.Union([Type.String(), Type.Enum(ClaimEligibility)])), -}); - -// LOGIC -export async function erc20GetClaimIneligibilityReasons( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/get-claim-ineligibility-reasons", - schema: { - summary: "Get claim ineligibility reasons", - description: - "Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any.", - tags: ["ERC20"], - operationId: "erc20-claimConditionsGetClaimIneligibilityReasons", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { quantity, addressToCheck } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = - await contract.erc20.claimConditions.getClaimIneligibilityReasons( - quantity, - addressToCheck, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/get-claimer-proofs.ts b/src/server/routes/contract/extensions/erc20/read/get-claimer-proofs.ts deleted file mode 100644 index d68a11cb4..000000000 --- a/src/server/routes/contract/extensions/erc20/read/get-claimer-proofs.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { claimerProofSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "The wallet address to get the merkle proofs for.", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: claimerProofSchema, -}); - -// LOGIC -export async function erc20GetClaimerProofs(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/get-claimer-proofs", - schema: { - summary: "Get claimer proofs", - description: - "Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address.", - tags: ["ERC20"], - operationId: "erc20-claimConditionsGetClaimerProofs", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { walletAddress } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = - await contract.erc20.claimConditions.getClaimerProofs(walletAddress); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/get.ts b/src/server/routes/contract/extensions/erc20/read/get.ts deleted file mode 100644 index dbd3b933b..000000000 --- a/src/server/routes/contract/extensions/erc20/read/get.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc20ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc20ContractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Object({ - name: Type.String(), - symbol: Type.String(), - decimals: Type.String(), - }), -}); - -responseSchema.example = { - result: { - name: "ERC20", - symbol: "", - decimals: "18", - }, -}; - -// LOGIC -export async function erc20GetMetadata(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/get", - schema: { - summary: "Get token details", - description: "Get details for this ERC-20 contract.", - tags: ["ERC20"], - operationId: "erc20-get", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.get(); - reply.status(StatusCodes.OK).send({ - result: { - symbol: returnData.symbol, - name: returnData.name, - decimals: returnData.decimals.toString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/signature-generate.ts b/src/server/routes/contract/extensions/erc20/read/signature-generate.ts deleted file mode 100644 index 352e0738a..000000000 --- a/src/server/routes/contract/extensions/erc20/read/signature-generate.ts +++ /dev/null @@ -1,231 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract, type Address, type Hex } from "thirdweb"; -import { generateMintSignature } from "thirdweb/extensions/erc20"; -import { getAccount } from "../../../../../../shared/utils/account"; -import { getContract as getContractV4 } from "../../../../../../shared/utils/cache/get-contract"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { maybeBigInt } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { createCustomError } from "../../../../../middleware/error"; -import { - signature20InputSchema, - signature20OutputSchema, - type erc20ResponseType, -} from "../../../../../schemas/erc20"; -import { thirdwebSdkVersionSchema } from "../../../../../schemas/http-headers/thirdweb-sdk-version"; -import { - erc20ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { checkAndReturnERC20SignaturePayload } from "../../../../../utils/validator"; - -// v4 sdk -const requestBodySchemaV4 = signature20InputSchema; -const responseSchemaV4 = Type.Object({ - payload: signature20OutputSchema, - signature: Type.String(), -}); - -// v5 sdk -const requestBodySchemaV5 = Type.Intersect([ - Type.Object({ - to: Type.String(), - primarySaleRecipient: Type.Optional(Type.String()), - price: Type.Optional(Type.String()), - priceInWei: Type.Optional(Type.String()), - currency: Type.Optional(Type.String()), - validityStartTimestamp: Type.Integer({ minimum: 0 }), - validityEndTimestamp: Type.Optional(Type.Integer({ minimum: 0 })), - uid: Type.Optional(Type.String()), - }), - Type.Union([ - Type.Object({ quantity: Type.String() }), - Type.Object({ quantityWei: Type.String() }), - ]), -]); -const responseSchemaV5 = Type.Object({ - payload: Type.Object({ - to: Type.String(), - primarySaleRecipient: Type.String(), - quantity: Type.String(), - price: Type.String(), - currency: Type.String(), - validityStartTimestamp: Type.Integer(), - validityEndTimestamp: Type.Integer(), - uid: Type.String(), - }), - signature: Type.String(), -}); - -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Union([ - requestBodySchemaV4, - requestBodySchemaV5, -]); -const responseSchema = Type.Object({ - result: Type.Union([responseSchemaV4, responseSchemaV5]), -}); - -responseSchema.example = { - result: "1", -}; - -// LOGIC -export async function erc20SignatureGenerate(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/signature/generate", - schema: { - summary: "Generate signature", - description: - "Generate a signature granting access for another wallet to mint tokens from this ERC-20 contract. This method is typically called by the token contract owner.", - tags: ["ERC20"], - operationId: "erc20-signatureGenerate", - params: requestSchema, - body: requestBodySchema, - headers: { - ...walletWithAAHeaderSchema.properties, - ...thirdwebSdkVersionSchema.properties, - }, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - } = request.headers as Static; - const { "x-thirdweb-sdk-version": sdkVersion } = - request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - - // Use v5 SDK if "x-thirdweb-sdk-version" header is set. - if (sdkVersion === "5") { - const args = request.body as Static; - const { - to, - primarySaleRecipient, - price, - priceInWei, - currency, - validityStartTimestamp, - validityEndTimestamp, - uid, - } = args; - - let quantityInput: { quantity: string } | { quantityWei: bigint }; - if ("quantity" in args) { - quantityInput = { quantity: args.quantity }; - } else if ("quantityWei" in args) { - quantityInput = { quantityWei: BigInt(args.quantityWei) }; - } else { - throw createCustomError( - `Missing "quantity" or "quantityWei".`, - StatusCodes.BAD_REQUEST, - "MISSING_PARAMETERS", - ); - } - - const contract = getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - const account = await getAccount({ - chainId, - from: walletAddress as Address, - accountAddress: accountAddress as Address, - }); - - const { payload, signature } = await generateMintSignature({ - contract, - account, - mintRequest: { - to, - primarySaleRecipient, - price, - priceInWei: maybeBigInt(priceInWei), - currency: currency as Address | undefined, - validityStartTimestamp: new Date(validityStartTimestamp * 1000), - validityEndTimestamp: validityEndTimestamp - ? new Date(validityEndTimestamp * 1000) - : undefined, - uid: uid as Hex | undefined, - ...quantityInput, - }, - }); - - return reply.status(StatusCodes.OK).send({ - result: { - payload: { - ...payload, - quantity: payload.quantity.toString(), - price: payload.price.toString(), - validityStartTimestamp: Number(payload.validityStartTimestamp), - validityEndTimestamp: Number(payload.validityEndTimestamp), - }, - signature, - }, - }); - } - - // Use v4 SDK. - const { - to, - currencyAddress, - mintEndTime, - mintStartTime, - price = "0", - primarySaleRecipient, - quantity, - uid, - } = request.body as Static; - - const contract = await getContractV4({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const payload = checkAndReturnERC20SignaturePayload< - Static, - erc20ResponseType - >({ - to, - currencyAddress, - mintEndTime, - mintStartTime, - price, - primarySaleRecipient, - quantity, - uid, - }); - const signedPayload = await contract.erc20.signature.generate(payload); - - reply.status(StatusCodes.OK).send({ - result: { - ...signedPayload, - payload: { - ...signedPayload.payload, - quantity: signedPayload.payload.quantity.toString(), - mintStartTime: signedPayload.payload.mintStartTime.toNumber(), - mintEndTime: signedPayload.payload.mintEndTime.toNumber(), - }, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/read/total-supply.ts b/src/server/routes/contract/extensions/erc20/read/total-supply.ts deleted file mode 100644 index cefccf0c6..000000000 --- a/src/server/routes/contract/extensions/erc20/read/total-supply.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { erc20MetadataSchema } from "../../../../../schemas/erc20"; -import { - erc20ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = erc20ContractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: erc20MetadataSchema, -}); - -responseSchema.example = [ - { - result: { - name: "Mumba20", - symbol: "", - decimals: "18", - value: "10000000000000000000", - displayValue: "10.0", - }, - }, -]; - -// LOGIC -export async function erc20TotalSupply(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc20/total-supply", - schema: { - summary: "Get total supply", - description: - "Get the total supply in circulation for this ERC-20 contract.", - tags: ["ERC20"], - operationId: "erc20-totalSupply", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc20.totalSupply(); - reply.status(StatusCodes.OK).send({ - result: { - value: returnData.value.toString(), - symbol: returnData.symbol, - name: returnData.name, - decimals: returnData.decimals.toString(), - displayValue: returnData.displayValue, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/burn-from.ts b/src/server/routes/contract/extensions/erc20/write/burn-from.ts deleted file mode 100644 index cb9ff17ca..000000000 --- a/src/server/routes/contract/extensions/erc20/write/burn-from.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - holderAddress: { - ...AddressSchema, - description: "Address of the wallet sending the tokens", - }, - amount: Type.String({ - description: "The amount of this token you want to burn", - }), - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - holderAddress: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - amount: "0.1", - }, -]; - -export async function erc20burnFrom(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/burn-from", - schema: { - summary: "Burn token from wallet", - description: - "Burn ERC-20 tokens in a specific wallet. Requires allowance.", - tags: ["ERC20"], - operationId: "erc20-burnFrom", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { holderAddress, amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc20.burnFrom.prepare(holderAddress, amount); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/burn.ts b/src/server/routes/contract/extensions/erc20/write/burn.ts deleted file mode 100644 index 086f7fc5f..000000000 --- a/src/server/routes/contract/extensions/erc20/write/burn.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - amount: Type.String({ - description: "The amount of tokens you want to burn", - }), - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - amount: "0.1", - }, -]; - -export async function erc20burn(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/burn", - schema: { - summary: "Burn token", - description: "Burn ERC-20 tokens in the caller wallet.", - tags: ["ERC20"], - operationId: "erc20-burn", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc20.burn.prepare(amount); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/claim-to.ts b/src/server/routes/contract/extensions/erc20/write/claim-to.ts deleted file mode 100644 index 45c405f30..000000000 --- a/src/server/routes/contract/extensions/erc20/write/claim-to.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { claimTo } from "thirdweb/extensions/erc20"; -import { getContractV5 } from "../../../../../../shared/utils/cache/get-contractv5"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - recipient: Type.String({ - description: "The wallet address to receive the claimed tokens.", - }), - amount: Type.String({ - description: "The amount of tokens to claim.", - }), - singlePhaseDrop: Type.Optional( - Type.Boolean({ - description: "Whether the drop is a single phase drop", - }), - ), - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - recipient: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - amount: "0.1", - }, -]; - -export async function erc20claimTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/claim-to", - schema: { - summary: "Claim tokens to wallet", - description: "Claim ERC-20 tokens to a specific wallet.", - tags: ["ERC20"], - operationId: "erc20-claimTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { recipient, amount, singlePhaseDrop, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContractV5({ - chainId, - contractAddress, - }); - const transaction = claimTo({ - contract, - from: fromAddress as Address, - to: recipient, - quantity: amount, - singlePhaseDrop, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/mint-batch-to.ts b/src/server/routes/contract/extensions/erc20/write/mint-batch-to.ts deleted file mode 100644 index 81b008ca0..000000000 --- a/src/server/routes/contract/extensions/erc20/write/mint-batch-to.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - data: Type.Array( - Type.Object({ - toAddress: { - ...AddressSchema, - description: "The address to mint tokens to", - }, - amount: Type.String({ - description: "The number of tokens to mint to the specific address.", - }), - }), - ), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - data: [ - { - toAddress: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - amount: "0.1", - }, - { - toAddress: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - amount: "0.1", - }, - ], - }, -]; - -export async function erc20mintBatchTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/mint-batch-to", - schema: { - summary: "Mint tokens (batch)", - description: "Mint ERC-20 tokens to multiple wallets in one transaction.", - tags: ["ERC20"], - operationId: "erc20-mintBatchTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { data, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc20.mintBatchTo.prepare(data); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/mint-to.ts b/src/server/routes/contract/extensions/erc20/write/mint-to.ts deleted file mode 100644 index 3135dc727..000000000 --- a/src/server/routes/contract/extensions/erc20/write/mint-to.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { mintTo } from "thirdweb/extensions/erc20"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - toAddress: { - ...AddressSchema, - description: "Address of the wallet to mint tokens to", - }, - amount: Type.String({ - description: "The amount of tokens you want to send", - }), - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - toAddress: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - amount: "0.1", - }, -]; - -export async function erc20mintTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/mint-to", - schema: { - summary: "Mint tokens", - description: "Mint ERC-20 tokens to a specific wallet.", - tags: ["ERC20"], - operationId: "erc20-mintTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain: _chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { toAddress, amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(_chain); - const chain = await getChain(chainId); - - const contract = getContract({ - chain, - client: thirdwebClient, - address: contractAddress, - }); - const transaction = mintTo({ - contract, - to: toAddress, - amount, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - extension: "erc20", - functionName: "mintTo", - shouldSimulate: simulateTx, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/set-allowance.ts b/src/server/routes/contract/extensions/erc20/write/set-allowance.ts deleted file mode 100644 index 0977941a7..000000000 --- a/src/server/routes/contract/extensions/erc20/write/set-allowance.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - spenderAddress: { - ...AddressSchema, - description: "Address of the wallet to allow transfers from", - }, - amount: Type.String({ - description: "The number of tokens to give as allowance", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - spenderAddress: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - amount: "100", - }, -]; - -export async function erc20SetAlowance(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/set-allowance", - schema: { - summary: "Set allowance", - description: - "Grant a specific wallet address to transfer ERC-20 tokens from the caller wallet.", - tags: ["ERC20"], - operationId: "erc20-setAllowance", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { spenderAddress, amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc20.setAllowance.prepare( - spenderAddress, - amount, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/set-claim-conditions.ts b/src/server/routes/contract/extensions/erc20/write/set-claim-conditions.ts deleted file mode 100644 index ed1b88b70..000000000 --- a/src/server/routes/contract/extensions/erc20/write/set-claim-conditions.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type sanitizedClaimConditionInputSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - claimConditionInputs: Type.Array(claimConditionInputSchema), - resetClaimEligibilityForAll: Type.Optional(Type.Boolean()), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc20SetClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/set", - schema: { - summary: "Overwrite the claim conditions for the drop.", - description: - "Overwrite the claim conditions for the drop. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - tags: ["ERC20"], - operationId: "erc20-setClaimConditions", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { claimConditionInputs, resetClaimEligibilityForAll, txOverrides } = - request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInputs: Static< - typeof sanitizedClaimConditionInputSchema - >[] = claimConditionInputs.map((item) => { - return { - ...item, - startTime: item.startTime - ? isUnixEpochTimestamp(Number.parseInt(item.startTime.toString())) - ? new Date(Number.parseInt(item.startTime.toString()) * 1000) - : new Date(item.startTime) - : undefined, - }; - }); - const tx = await contract.erc20.claimConditions.set.prepare( - sanitizedClaimConditionInputs, - resetClaimEligibilityForAll, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/signature-mint.ts b/src/server/routes/contract/extensions/erc20/write/signature-mint.ts deleted file mode 100644 index 1601ec311..000000000 --- a/src/server/routes/contract/extensions/erc20/write/signature-mint.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { SignedPayload20 } from "@thirdweb-dev/sdk"; -import { BigNumber } from "ethers"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { signature20OutputSchema } from "../../../../../schemas/erc20"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - payload: signature20OutputSchema, - signature: Type.String(), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - payload: {}, - signature: "", - }, -]; - -export async function erc20SignatureMint(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/signature/mint", - schema: { - summary: "Signature mint", - description: "Mint ERC-20 tokens from a generated signature.", - tags: ["ERC20"], - operationId: "erc20-signatureMint", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { payload, signature, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const signedPayload: SignedPayload20 = { - payload: { - ...payload, - quantity: BigNumber.from(payload.quantity).toString(), - mintStartTime: BigNumber.from(payload.mintStartTime), - mintEndTime: BigNumber.from(payload.mintEndTime), - }, - signature, - }; - const tx = await contract.erc20.signature.mint.prepare(signedPayload); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/transfer-from.ts b/src/server/routes/contract/extensions/erc20/write/transfer-from.ts deleted file mode 100644 index a96c54b83..000000000 --- a/src/server/routes/contract/extensions/erc20/write/transfer-from.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { transferFrom } from "thirdweb/extensions/erc20"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { getChecksumAddress } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { TokenAmountStringSchema } from "../../../../../schemas/number"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - fromAddress: { - ...AddressSchema, - description: "The sender address.", - }, - toAddress: { - ...AddressSchema, - description: "The recipient address.", - }, - amount: { - ...TokenAmountStringSchema, - description: "The amount of tokens to transfer.", - }, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - fromAddress: "0x....", - toAddress: "0x...", - amount: "0.1", - }, -]; - -// OUTPUTS - -export async function erc20TransferFrom(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/transfer-from", - schema: { - summary: "Transfer tokens from wallet", - description: - "Transfer ERC-20 tokens from the connected wallet to another wallet. Requires allowance.", - tags: ["ERC20"], - operationId: "erc20-transferFrom", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { fromAddress, toAddress, amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - - const transaction = transferFrom({ - contract, - from: getChecksumAddress(fromAddress), - to: getChecksumAddress(toAddress), - amount, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: getChecksumAddress(walletAddress), - toAddress: getChecksumAddress(contractAddress), - accountAddress: getChecksumAddress(accountAddress), - accountFactoryAddress: getChecksumAddress(accountFactoryAddress), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - functionName: "transferFrom", - extension: "erc20", - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/transfer.ts b/src/server/routes/contract/extensions/erc20/write/transfer.ts deleted file mode 100644 index 3c7b62ec7..000000000 --- a/src/server/routes/contract/extensions/erc20/write/transfer.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { transfer } from "thirdweb/extensions/erc20"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { getChecksumAddress } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { TokenAmountStringSchema } from "../../../../../schemas/number"; -import { - erc20ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestSchema = erc20ContractParamSchema; -const requestBodySchema = Type.Object({ - toAddress: { - ...AddressSchema, - description: "The recipient address.", - }, - amount: Type.String({ - ...TokenAmountStringSchema, - description: "The amount of tokens to transfer.", - }), - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - toAddress: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - amount: "0.1", - }, -]; - -export async function erc20Transfer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/transfer", - schema: { - summary: "Transfer tokens", - description: - "Transfer ERC-20 tokens from the caller wallet to a specific wallet.", - tags: ["ERC20"], - operationId: "erc20-transfer", - body: requestBodySchema, - params: requestSchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { toAddress, amount, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - - const transaction = transfer({ - contract, - to: getChecksumAddress(toAddress), - amount, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: getChecksumAddress(walletAddress), - toAddress: getChecksumAddress(contractAddress), - accountAddress: getChecksumAddress(accountAddress), - accountFactoryAddress: getChecksumAddress(accountFactoryAddress), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - functionName: "transfer", - extension: "erc20", - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc20/write/update-claim-conditions.ts b/src/server/routes/contract/extensions/erc20/write/update-claim-conditions.ts deleted file mode 100644 index 77f778d2f..000000000 --- a/src/server/routes/contract/extensions/erc20/write/update-claim-conditions.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type sanitizedClaimConditionInputSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - claimConditionInput: claimConditionInputSchema, - index: Type.Integer({ - description: "Index of the claim condition to update", - minimum: 0, - }), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc20UpdateClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc20/claim-conditions/update", - schema: { - summary: "Update a single claim phase.", - description: - "Update a single claim phase, by providing the index of the claim phase and the new phase configuration. The index is the position of the phase in the list of phases you have made, starting from zero. e.g. if you have two phases, the first phase has an index of 0 and the second phase has an index of 1. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - tags: ["ERC20"], - operationId: "erc20-updateClaimConditions", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { claimConditionInput, index, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInput: Static< - typeof sanitizedClaimConditionInputSchema - > = { - ...claimConditionInput, - startTime: claimConditionInput.startTime - ? isUnixEpochTimestamp( - Number.parseInt(claimConditionInput.startTime.toString()), - ) - ? new Date( - Number.parseInt(claimConditionInput.startTime.toString()) * - 1000, - ) - : new Date(claimConditionInput.startTime) - : undefined, - }; - const tx = await contract.erc20.claimConditions.update.prepare( - index, - sanitizedClaimConditionInput, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc20", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/index.ts b/src/server/routes/contract/extensions/erc721/index.ts deleted file mode 100644 index 3b8d75107..000000000 --- a/src/server/routes/contract/extensions/erc721/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { erc721BalanceOf } from "./read/balance-of"; -import { erc721CanClaim } from "./read/can-claim"; -import { erc721Get } from "./read/get"; -import { erc721GetActiveClaimConditions } from "./read/get-active-claim-conditions"; -import { erc721GetAll } from "./read/get-all"; -import { erc721GetAllClaimConditions } from "./read/get-all-claim-conditions"; -import { erc721GetClaimIneligibilityReasons } from "./read/get-claim-ineligibility-reasons"; -import { erc721GetClaimerProofs } from "./read/get-claimer-proofs"; -import { erc721GetOwned } from "./read/get-owned"; -import { erc721IsApproved } from "./read/is-approved"; -import { erc721SignatureGenerate } from "./read/signature-generate"; -import { erc721SignaturePrepare } from "./read/signature-prepare"; -import { erc721TotalClaimedSupply } from "./read/total-claimed-supply"; -import { erc721TotalCount } from "./read/total-count"; -import { erc721TotalUnclaimedSupply } from "./read/total-unclaimed-supply"; -import { erc721burn } from "./write/burn"; -import { erc721claimTo } from "./write/claim-to"; -import { erc721lazyMint } from "./write/lazy-mint"; -import { erc721mintBatchTo } from "./write/mint-batch-to"; -import { erc721mintTo } from "./write/mint-to"; -import { erc721SetApprovalForAll } from "./write/set-approval-for-all"; -import { erc721SetApprovalForToken } from "./write/set-approval-for-token"; -import { erc721SetClaimConditions } from "./write/set-claim-conditions"; -import { erc721SignatureMint } from "./write/signature-mint"; -import { erc721transfer } from "./write/transfer"; -import { erc721transferFrom } from "./write/transfer-from"; -import { erc721UpdateClaimConditions } from "./write/update-claim-conditions"; -import { erc721UpdateTokenMetadata } from "./write/update-token-metadata"; - -export const erc721Routes = async (fastify: FastifyInstance) => { - // GET - await fastify.register(erc721Get); - await fastify.register(erc721GetAll); - await fastify.register(erc721GetOwned); - await fastify.register(erc721BalanceOf); - await fastify.register(erc721IsApproved); - await fastify.register(erc721TotalCount); - await fastify.register(erc721TotalClaimedSupply); - await fastify.register(erc721TotalUnclaimedSupply); - await fastify.register(erc721CanClaim); - await fastify.register(erc721GetActiveClaimConditions); - await fastify.register(erc721GetAllClaimConditions); - await fastify.register(erc721GetClaimIneligibilityReasons); - await fastify.register(erc721GetClaimerProofs); - - // POST - await fastify.register(erc721SetApprovalForAll); - await fastify.register(erc721SetApprovalForToken); - await fastify.register(erc721transfer); - await fastify.register(erc721transferFrom); - await fastify.register(erc721mintTo); - await fastify.register(erc721mintBatchTo); - await fastify.register(erc721burn); - await fastify.register(erc721lazyMint); - await fastify.register(erc721claimTo); - await fastify.register(erc721SignatureGenerate); - await fastify.register(erc721SignatureMint); - await fastify.register(erc721SetClaimConditions); - await fastify.register(erc721UpdateClaimConditions); - await fastify.register(erc721SignaturePrepare); - await fastify.register(erc721UpdateTokenMetadata); -}; diff --git a/src/server/routes/contract/extensions/erc721/read/balance-of.ts b/src/server/routes/contract/extensions/erc721/read/balance-of.ts deleted file mode 100644 index 33333c5af..000000000 --- a/src/server/routes/contract/extensions/erc721/read/balance-of.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - erc721ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = erc721ContractParamSchema; -const querystringSchema = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Address of the wallet to check NFT balance", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -responseSchema.example = { - result: "1", -}; - -// LOGIC -export async function erc721BalanceOf(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/balance-of", - schema: { - summary: "Get token balance", - description: - "Get the balance of a specific wallet address for this ERC-721 contract.", - tags: ["ERC721"], - operationId: "erc721-balanceOf", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { walletAddress } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.balanceOf(walletAddress); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/can-claim.ts b/src/server/routes/contract/extensions/erc721/read/can-claim.ts deleted file mode 100644 index 3ea49992c..000000000 --- a/src/server/routes/contract/extensions/erc721/read/can-claim.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - quantity: Type.String({ - description: "The amount of tokens to claim.", - }), - addressToCheck: Type.Optional( - Type.String({ - description: - "The wallet address to check if it can claim tokens. This considers all aspects of the active claim phase, including allowlists, previous claims, etc.", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Boolean(), -}); - -// LOGIC -export async function erc721CanClaim(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/can-claim", - schema: { - summary: "Check if tokens are available for claiming", - description: - "Check if tokens are currently available for claiming, optionally specifying if a specific wallet address can claim.", - tags: ["ERC721"], - operationId: "erc721-canClaim", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { quantity, addressToCheck } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.claimConditions.canClaim( - quantity, - addressToCheck, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get-active-claim-conditions.ts b/src/server/routes/contract/extensions/erc721/read/get-active-claim-conditions.ts deleted file mode 100644 index 91a7879ec..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get-active-claim-conditions.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { claimConditionOutputSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - withAllowList: Type.Optional( - Type.Boolean({ - description: - "Provide a boolean value to include the allowlist in the response.", - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: claimConditionOutputSchema, -}); - -// LOGIC -export async function erc721GetActiveClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/get-active", - schema: { - summary: "Retrieve the currently active claim phase, if any.", - description: "Retrieve the currently active claim phase, if any.", - tags: ["ERC721"], - operationId: "erc721-getActiveClaimConditions", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { withAllowList } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.claimConditions.getActive({ - withAllowList, - }); - reply.status(StatusCodes.OK).send({ - result: { - ...returnData, - price: returnData.price.toString(), - waitInSeconds: returnData.waitInSeconds.toString(), - currencyMetadata: { - ...returnData.currencyMetadata, - value: returnData.currencyMetadata.value.toString(), - }, - startTime: returnData.startTime.toISOString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get-all-claim-conditions.ts b/src/server/routes/contract/extensions/erc721/read/get-all-claim-conditions.ts deleted file mode 100644 index e0ffab452..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get-all-claim-conditions.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { claimConditionOutputSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - withAllowList: Type.Optional( - Type.Boolean({ - description: - "Provide a boolean value to include the allowlist in the response.", - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(claimConditionOutputSchema), -}); - -// LOGIC -export async function erc721GetAllClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/get-all", - schema: { - summary: "Get all the claim phases configured for the drop.", - description: "Get all the claim phases configured for the drop.", - tags: ["ERC721"], - operationId: "erc721-getAllClaimConditions", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { withAllowList } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.claimConditions.getAll({ - withAllowList, - }); - - const sanitizedReturnData = returnData.map((item) => { - return { - ...item, - price: item.price.toString(), - waitInSeconds: item.waitInSeconds.toString(), - currencyMetadata: { - ...item.currencyMetadata, - value: item.currencyMetadata.value.toString(), - }, - startTime: item.startTime.toISOString(), - }; - }); - - reply.status(StatusCodes.OK).send({ - result: sanitizedReturnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get-all.ts b/src/server/routes/contract/extensions/erc721/read/get-all.ts deleted file mode 100644 index d83515470..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get-all.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const querystringSchema = Type.Object({ - start: Type.Optional( - Type.Integer({ - description: "The start token id for paginated results. Defaults to 0.", - minimum: 0, - }), - ), - count: Type.Optional( - Type.Integer({ - description: "The page count for paginated results. Defaults to 100.", - minimum: 1, - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(nftSchema), -}); - -responseSchema.example = { - result: [ - { - metadata: { - id: "2", - uri: "ipfs://QmWDdRcLqVMzFeawADAPr2EFCzdqCzx373VpWK3Kfx25GJ/0", - name: "My NFT", - description: "My NFT description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - type: "ERC721", - supply: "1", - }, - ], -}; - -// LOGIC -export async function erc721GetAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/get-all", - schema: { - summary: "Get all details", - description: "Get details for all tokens in an ERC-721 contract.", - tags: ["ERC721"], - operationId: "erc721-getAll", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.erc721.getAll({ - start, - count, - }); - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get-claim-ineligibility-reasons.ts b/src/server/routes/contract/extensions/erc721/read/get-claim-ineligibility-reasons.ts deleted file mode 100644 index 8c3d3efb8..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get-claim-ineligibility-reasons.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { ClaimEligibility } from "@thirdweb-dev/sdk"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - quantity: Type.String({ - description: "The amount of tokens to claim.", - }), - addressToCheck: Type.Optional( - Type.String({ - description: "The wallet address to check if it can claim tokens.", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), - ), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(Type.Union([Type.String(), Type.Enum(ClaimEligibility)])), -}); - -// LOGIC -export async function erc721GetClaimIneligibilityReasons( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/get-claim-ineligibility-reasons", - schema: { - summary: "Get claim ineligibility reasons", - description: - "Get an array of reasons why a specific wallet address is not eligible to claim tokens, if any.", - tags: ["ERC721"], - operationId: "erc721-getClaimIneligibilityReasons", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { quantity, addressToCheck } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = - await contract.erc721.claimConditions.getClaimIneligibilityReasons( - quantity, - addressToCheck, - ); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get-claimer-proofs.ts b/src/server/routes/contract/extensions/erc721/read/get-claimer-proofs.ts deleted file mode 100644 index 315a79e65..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get-claimer-proofs.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { claimerProofSchema } from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestQueryString = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "The wallet address to get the merkle proofs for.", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: claimerProofSchema, -}); - -// LOGIC -export async function erc721GetClaimerProofs(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/get-claimer-proofs", - schema: { - summary: "Get claimer proofs", - description: - "Returns allowlist information and merkle proofs for a given wallet address. Returns null if no proof is found for the given wallet address.", - tags: ["ERC721"], - operationId: "erc721-getClaimerProofs", - params: requestSchema, - querystring: requestQueryString, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { walletAddress } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = - await contract.erc721.claimConditions.getClaimerProofs(walletAddress); - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get-owned.ts b/src/server/routes/contract/extensions/erc721/read/get-owned.ts deleted file mode 100644 index 6b577e263..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get-owned.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { nftSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const querystringSchema = Type.Object({ - walletAddress: { - ...AddressSchema, - description: "Address of the wallet to get NFTs for", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(nftSchema), -}); - -responseSchema.example = [ - { - result: [ - { - metadata: { - id: "2", - uri: "ipfs://QmWDdRcLqVMzFeawADAPr2EFCzdqCzx373VpWK3Kfx25GJ/0", - name: "My NFT", - description: "My NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - type: "ERC721", - supply: "1", - }, - ], - }, -]; - -// LOGIC -export async function erc721GetOwned(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/get-owned", - schema: { - summary: "Get owned tokens", - description: - "Get all tokens in an ERC-721 contract owned by a specific wallet.", - tags: ["ERC721"], - operationId: "erc721-getOwned", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { walletAddress } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - // Check if the wallet has any tokens before querying getOwned - const balance = await contract.erc721.balanceOf(walletAddress); - if (balance.eq(0)) { - reply.status(StatusCodes.OK).send({ - result: [], - }); - return; - } - const result = await contract.erc721.getOwned(walletAddress); - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/get.ts b/src/server/routes/contract/extensions/erc721/read/get.ts deleted file mode 100644 index 1a58d5e7d..000000000 --- a/src/server/routes/contract/extensions/erc721/read/get.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const querystringSchema = Type.Object({ - tokenId: Type.String({ - description: "The tokenId of the NFT to retrieve", - examples: ["0"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: nftSchema, -}); - -responseSchema.example = [ - { - result: { - metadata: { - id: "2", - uri: "ipfs://QmWDdRcLqVMzFeawADAPr2EFCzdqCzx373VpWK3Kfx25GJ/0", - name: "My NFT", - description: "My NFT description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - type: "ERC721", - supply: "1", - }, - }, -]; - -// LOGIC -export async function erc721Get(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/get", - schema: { - summary: "Get details", - description: "Get the details for a token in an ERC-721 contract.", - tags: ["ERC721"], - operationId: "erc721-get", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.erc721.get(tokenId); - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/is-approved.ts b/src/server/routes/contract/extensions/erc721/read/is-approved.ts deleted file mode 100644 index 5afcdfa36..000000000 --- a/src/server/routes/contract/extensions/erc721/read/is-approved.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const querystringSchema = Type.Object({ - ownerWallet: Type.String({ - description: "Address of the wallet who owns the NFT", - examples: ["0x3EcDBF3B911d0e9052b64850693888b008e18373"], - }), - operator: Type.String({ - description: "Address of the operator to check approval on", - examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.Boolean()), -}); - -responseSchema.example = { - result: false, -}; - -// LOGIC -export async function erc721IsApproved(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/is-approved", - schema: { - summary: "Check if approved transfers", - description: - "Check if the specific wallet has approved transfers from a specific operator wallet.", - tags: ["ERC721"], - operationId: "erc721-isApproved", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { ownerWallet, operator } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.isApproved( - ownerWallet, - operator, - ); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/signature-generate.ts b/src/server/routes/contract/extensions/erc721/read/signature-generate.ts deleted file mode 100644 index 1540bb756..000000000 --- a/src/server/routes/contract/extensions/erc721/read/signature-generate.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract, type Address, type Hex } from "thirdweb"; -import { generateMintSignature } from "thirdweb/extensions/erc721"; -import { getAccount } from "../../../../../../shared/utils/account"; -import { getContract as getContractV4 } from "../../../../../../shared/utils/cache/get-contract"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { maybeBigInt } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { thirdwebSdkVersionSchema } from "../../../../../schemas/http-headers/thirdweb-sdk-version"; -import { - signature721InputSchema, - signature721OutputSchema, - type ercNFTResponseType, -} from "../../../../../schemas/nft"; -import { - signature721InputSchemaV5, - signature721OutputSchemaV5, -} from "../../../../../schemas/nft/v5"; -import { - erc721ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { checkAndReturnNFTSignaturePayload } from "../../../../../utils/validator"; - -// v4 sdk -const requestBodySchemaV4 = signature721InputSchema; -const responseSchemaV4 = Type.Object({ - payload: signature721OutputSchema, - signature: Type.String(), -}); - -// v5 sdk -const requestBodySchemaV5 = signature721InputSchemaV5; -const responseSchemaV5 = Type.Object({ - payload: signature721OutputSchemaV5, - signature: Type.String(), -}); - -const requestSchema = erc721ContractParamSchema; -const requestBodySchema = Type.Union([ - requestBodySchemaV4, - requestBodySchemaV5, -]); -const responseSchema = Type.Object({ - result: Type.Union([responseSchemaV4, responseSchemaV5]), -}); - -responseSchema.example = { - result: { - payload: { - uri: "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - royaltyRecipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - quantity: "1", - royaltyBps: "0", - primarySaleRecipient: "0x0000000000000000000000000000000000000000", - uid: "0x3862386334363135326230303461303939626136653361643131343836373563", - metadata: { - name: "test token", - description: "test token", - }, - currencyAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - price: "0", - mintStartTime: 1686169938, - mintEndTime: 2001529938, - }, - signature: - "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b", - }, -}; - -// LOGIC -export async function erc721SignatureGenerate(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/signature/generate", - schema: { - summary: "Generate signature", - description: - "Generate a signature granting access for another wallet to mint tokens from this ERC-721 contract. This method is typically called by the token contract owner.", - tags: ["ERC721"], - operationId: "erc721-signatureGenerate", - params: requestSchema, - body: requestBodySchema, - headers: { - ...walletWithAAHeaderSchema.properties, - ...thirdwebSdkVersionSchema.properties, - }, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - } = request.headers as Static; - const { "x-thirdweb-sdk-version": sdkVersion } = - request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - - // Use v5 SDK if "x-thirdweb-sdk-version" header is set. - if (sdkVersion === "5") { - const args = request.body as Static; - const { - to, - metadata, - royaltyRecipient, - royaltyBps, - primarySaleRecipient, - price, - priceInWei, - currency, - validityStartTimestamp, - validityEndTimestamp, - uid, - } = args; - - const contract = getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - const account = await getAccount({ - chainId, - from: walletAddress as Address, - accountAddress: accountAddress as Address, - }); - - const { payload, signature } = await generateMintSignature({ - contract, - account, - mintRequest: { - to, - metadata, - royaltyRecipient, - royaltyBps, - primarySaleRecipient, - price, - priceInWei: maybeBigInt(priceInWei), - currency: currency as Address | undefined, - validityStartTimestamp: validityStartTimestamp - ? new Date(validityStartTimestamp * 1000) - : undefined, - validityEndTimestamp: validityEndTimestamp - ? new Date(validityEndTimestamp * 1000) - : undefined, - uid: uid as Hex | undefined, - }, - }); - - return reply.status(StatusCodes.OK).send({ - result: { - payload: { - ...payload, - royaltyBps: payload.royaltyBps.toString(), - price: payload.price.toString(), - validityStartTimestamp: Number(payload.validityStartTimestamp), - validityEndTimestamp: Number(payload.validityEndTimestamp), - }, - signature, - }, - }); - } - - // Use v4 SDK. - const { - to, - currencyAddress, - metadata, - mintEndTime, - mintStartTime, - price = "0", - primarySaleRecipient, - quantity, - royaltyBps, - royaltyRecipient, - uid, - } = request.body as Static; - - const contract = await getContractV4({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const payload = checkAndReturnNFTSignaturePayload< - Static, - ercNFTResponseType - >({ - to, - currencyAddress, - metadata, - mintEndTime, - mintStartTime, - price, - primarySaleRecipient, - quantity, - royaltyBps, - royaltyRecipient, - uid, - }); - - const signedPayload = await contract.erc721.signature.generate(payload); - - reply.status(StatusCodes.OK).send({ - result: { - ...signedPayload, - payload: { - ...signedPayload.payload, - quantity: signedPayload.payload.quantity.toString(), - royaltyBps: signedPayload.payload.royaltyBps.toString(), - mintStartTime: signedPayload.payload.mintStartTime.toNumber(), - mintEndTime: signedPayload.payload.mintEndTime.toNumber(), - }, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/signature-prepare.ts b/src/server/routes/contract/extensions/erc721/read/signature-prepare.ts deleted file mode 100644 index 6cde4c604..000000000 --- a/src/server/routes/contract/extensions/erc721/read/signature-prepare.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { MintRequest721 } from "@thirdweb-dev/sdk"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { createHash, getRandomValues } from "node:crypto"; -import { - ZERO_ADDRESS, - getContract, - isHex, - uint8ArrayToHex, - type Hex, -} from "thirdweb"; -import { - primarySaleRecipient as getDefaultPrimarySaleRecipient, - getDefaultRoyaltyInfo, -} from "thirdweb/extensions/common"; -import { decimals } from "thirdweb/extensions/erc20"; -import { upload } from "thirdweb/storage"; -import { checksumAddress } from "thirdweb/utils"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { prettifyError } from "../../../../../../shared/utils/error"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { createCustomError } from "../../../../../middleware/error"; -import { - signature721InputSchemaV5, - signature721OutputSchemaV5, -} from "../../../../../schemas/nft/v5"; -import { - erc721ContractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestSchema = erc721ContractParamSchema; -const requestBodySchema = signature721InputSchemaV5; - -const responseSchema = Type.Object({ - result: Type.Object({ - mintPayload: signature721OutputSchemaV5, - typedDataPayload: Type.Object( - { - domain: Type.Object( - { - name: Type.String(), - version: Type.String(), - chainId: Type.Integer(), - verifyingContract: Type.String(), - }, - { - description: - "Specifies the contextual information used to prevent signature reuse across different contexts.", - }, - ), - types: Type.Object( - { - EIP712Domain: Type.Array( - Type.Object({ - name: Type.String(), - type: Type.String(), - }), - ), - MintRequest: Type.Array( - Type.Object({ - name: Type.String(), - type: Type.String(), - }), - ), - }, - { - description: - "Defines the structure of the data types used in the message.", - }, - ), - message: { - ...signature721OutputSchemaV5, - description: "The structured data to be signed.", - }, - primaryType: Type.Literal("MintRequest", { - description: - "The main type of the data in the message corresponding to a defined type in the `types` field.", - }), - }, - { - description: - "The payload to sign with a wallet's `signTypedData` method.", - }, - ), - }), -}); - -responseSchema.example = { - result: { - mintPayload: { - uri: "ipfs://...", - currency: "0x0000000000000000000000000000000000000000", - uid: "0x3862386334363135326230303461303939626136653361643131343836373563", - to: "0x...", - royaltyRecipient: "0x...", - primarySaleRecipient: "0x...", - }, - typedDataPayload: { - domain: { - name: "TokenERC721", - version: "1", - chainId: 84532, - verifyingContract: "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4", - }, - types: { - MintRequest: [ - { - name: "to", - type: "address", - }, - { - name: "royaltyRecipient", - type: "address", - }, - { - name: "royaltyBps", - type: "uint256", - }, - { - name: "primarySaleRecipient", - type: "address", - }, - { - name: "uri", - type: "string", - }, - { - name: "price", - type: "uint256", - }, - { - name: "currency", - type: "address", - }, - { - name: "validityStartTimestamp", - type: "uint128", - }, - { - name: "validityEndTimestamp", - type: "uint128", - }, - { - name: "uid", - type: "bytes32", - }, - ], - }, - message: { - uri: "ipfs://test", - currency: "0x0000000000000000000000000000000000000000", - uid: "0xmyuid", - to: "0x4Ff9aa707AE1eAeb40E581DF2cf4e14AffcC553d", - royaltyRecipient: "0x4Ff9aa707AE1eAeb40E581DF2cf4e14AffcC553d", - primarySaleRecipient: "0x4Ff9aa707AE1eAeb40E581DF2cf4e14AffcC553d", - }, - primaryType: "MintRequest", - }, - }, -}; - -export async function erc721SignaturePrepare(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/signature/prepare", - schema: { - summary: "Prepare signature", - description: "Prepares a payload for a wallet to generate a signature.", - tags: ["ERC721"], - operationId: "erc721-signaturePrepare", - params: requestSchema, - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain: chainSlug, contractAddress } = request.params; - const { - metadata, - to, - price, - priceInWei, - currency, - validityStartTimestamp, - validityEndTimestamp, - uid, - } = request.body; - - const chainId = await getChainIdFromChain(chainSlug); - const chain = await getChain(chainId); - const contract = await getContract({ - client: thirdwebClient, - chain, - address: contractAddress, - }); - - let royaltyRecipient = request.body.royaltyRecipient; - let royaltyBps = request.body.royaltyBps; - if (!royaltyRecipient || !royaltyBps) { - try { - const [defaultRoyaltyRecipient, defaultRoyaltyBps] = - await getDefaultRoyaltyInfo({ - contract, - }); - - royaltyRecipient = royaltyRecipient ?? defaultRoyaltyRecipient; - royaltyBps = royaltyBps ?? defaultRoyaltyBps; - } catch (e) { - throw createCustomError( - `Could not get default royalty info: ${prettifyError(e)}`, - StatusCodes.BAD_REQUEST, - "DEFAULT_ROYALTY_INFO", - ); - } - } - - let primarySaleRecipient = request.body.primarySaleRecipient; - if (!primarySaleRecipient) { - try { - primarySaleRecipient = await getDefaultPrimarySaleRecipient({ - contract, - }); - } catch (e) { - throw createCustomError( - `Could not get default primary sale recipient: ${prettifyError(e)}`, - StatusCodes.BAD_REQUEST, - "DEFAULT_PRIMARY_SALE_RECIPIENT", - ); - } - } - - const parsedCurrency = currency || ZERO_ADDRESS; - - let parsedPrice = 0n; - if (priceInWei) { - parsedPrice = BigInt(priceInWei); - } else if (price) { - let _decimals = 18; - if ( - !( - parsedCurrency === ZERO_ADDRESS || - parsedCurrency === "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" - ) - ) { - const contract = getContract({ - chain, - client: thirdwebClient, - address: parsedCurrency, - }); - _decimals = await decimals({ contract }); - } - parsedPrice = BigInt(Number.parseFloat(price) * 10 ** _decimals); - } - - let parsedUri = ""; - if (metadata) { - parsedUri = - typeof metadata === "string" - ? metadata - : await upload({ - client: thirdwebClient, - files: [metadata], - }); - } - - let parsedUid: Hex; - if (uid) { - if (isHex(uid)) { - // 0x + 32-byte hex - if (uid.length !== 66) { - throw createCustomError( - '"uid" must be a valid 32-byte hex string.', - StatusCodes.BAD_REQUEST, - "INVALID_UID", - ); - } - parsedUid = uid; - } else { - parsedUid = `0x${createHash("sha256").update(uid).digest("hex")}`; - } - } else { - parsedUid = uint8ArrayToHex(getRandomValues(new Uint8Array(32))); - } - - const mintPayload: Static = { - uri: parsedUri, - uid: parsedUid, - currency: parsedCurrency, - price: parsedPrice.toString(), - to: checksumAddress(to), - royaltyRecipient, - royaltyBps: royaltyBps.toString(), - primarySaleRecipient, - validityStartTimestamp: - validityStartTimestamp ?? toSeconds(new Date(0)), - validityEndTimestamp: - validityEndTimestamp ?? toSeconds(tenYearsFromNow()), - }; - - reply.status(StatusCodes.OK).send({ - result: { - mintPayload: mintPayload, - typedDataPayload: { - domain: { - name: "TokenERC721", - version: "1", - chainId: contract.chain.id, - verifyingContract: contract.address, - }, - types: { - // signTypedData on some wallets fail without this type. - EIP712Domain: [ - { name: "name", type: "string" }, - { name: "version", type: "string" }, - { name: "chainId", type: "uint256" }, - { name: "verifyingContract", type: "address" }, - ], - MintRequest: MintRequest721, - }, - message: mintPayload, - primaryType: "MintRequest", - }, - }, - }); - }, - }); -} - -const tenYearsFromNow = () => - new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 10); - -const toSeconds = (date: Date) => { - return Math.floor(date.getTime() / 1000); -}; diff --git a/src/server/routes/contract/extensions/erc721/read/total-claimed-supply.ts b/src/server/routes/contract/extensions/erc721/read/total-claimed-supply.ts deleted file mode 100644 index 720fcc5e3..000000000 --- a/src/server/routes/contract/extensions/erc721/read/total-claimed-supply.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -// LOGIC -export async function erc721TotalClaimedSupply(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/total-claimed-supply", - schema: { - summary: "Get claimed supply", - description: "Get the claimed supply for this ERC-721 contract.", - tags: ["ERC721"], - operationId: "erc721-totalClaimedSupply", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.totalClaimedSupply(); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/total-count.ts b/src/server/routes/contract/extensions/erc721/read/total-count.ts deleted file mode 100644 index 2c4f0a6a0..000000000 --- a/src/server/routes/contract/extensions/erc721/read/total-count.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -responseSchema.example = [ - { - result: "1", - }, -]; - -// LOGIC -export async function erc721TotalCount(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/total-count", - schema: { - summary: "Get total supply", - description: - "Get the total supply in circulation for this ERC-721 contract.", - tags: ["ERC721"], - operationId: "erc721-totalCount", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.totalCount(); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/read/total-unclaimed-supply.ts b/src/server/routes/contract/extensions/erc721/read/total-unclaimed-supply.ts deleted file mode 100644 index d4fec394c..000000000 --- a/src/server/routes/contract/extensions/erc721/read/total-unclaimed-supply.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(Type.String()), -}); - -// LOGIC -export async function erc721TotalUnclaimedSupply(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/erc721/total-unclaimed-supply", - schema: { - summary: "Get unclaimed supply", - description: "Get the unclaimed supply for this ERC-721 contract.", - tags: ["ERC721"], - operationId: "erc721-totalUnclaimedSupply", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const returnData = await contract.erc721.totalUnclaimedSupply(); - reply.status(StatusCodes.OK).send({ - result: returnData.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/burn.ts b/src/server/routes/contract/extensions/erc721/write/burn.ts deleted file mode 100644 index 878ec7a42..000000000 --- a/src/server/routes/contract/extensions/erc721/write/burn.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.String({ - description: "The token ID to burn", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - tokenId: "0", - }, -]; - -export async function erc721burn(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/burn", - schema: { - summary: "Burn token", - description: "Burn ERC-721 tokens in the caller wallet.", - tags: ["ERC721"], - operationId: "erc721-burn", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc721.burn.prepare(tokenId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/claim-to.ts b/src/server/routes/contract/extensions/erc721/write/claim-to.ts deleted file mode 100644 index 9616b6d44..000000000 --- a/src/server/routes/contract/extensions/erc721/write/claim-to.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { claimTo } from "thirdweb/extensions/erc721"; -import { getContractV5 } from "../../../../../../shared/utils/cache/get-contractv5"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to claim the NFT to", - }, - quantity: Type.String({ - description: "Quantity of NFTs to mint", - }), - singlePhaseDrop: Type.Optional( - Type.Boolean({ - description: "Whether the drop is a single phase drop", - }), - ), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - quantity: "1", - }, -]; - -export async function erc721claimTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/claim-to", - schema: { - summary: "Claim tokens to wallet", - description: "Claim ERC-721 tokens to a specific wallet.", - tags: ["ERC721"], - operationId: "erc721-claimTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, quantity, singlePhaseDrop, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContractV5({ - chainId, - contractAddress, - }); - const transaction = claimTo({ - contract, - from: fromAddress as Address, - to: receiver, - quantity: BigInt(quantity), - singlePhaseDrop, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/lazy-mint.ts b/src/server/routes/contract/extensions/erc721/write/lazy-mint.ts deleted file mode 100644 index 64001b0f6..000000000 --- a/src/server/routes/contract/extensions/erc721/write/lazy-mint.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftOrInputSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - metadatas: Type.Array(nftOrInputSchema), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - metadatas: [ - { - name: "My NFT #1", - description: "My NFT #1 description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - { - name: "My NFT #2", - description: "My NFT #2 description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - ], - }, -]; - -export async function erc721lazyMint(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/lazy-mint", - schema: { - summary: "Lazy mint", - description: "Lazy mint ERC-721 tokens to be claimed in the future.", - tags: ["ERC721"], - operationId: "erc721-lazyMint", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { metadatas, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc721.lazyMint.prepare(metadatas); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/mint-batch-to.ts b/src/server/routes/contract/extensions/erc721/write/mint-batch-to.ts deleted file mode 100644 index 862a51d4e..000000000 --- a/src/server/routes/contract/extensions/erc721/write/mint-batch-to.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../schemas/address"; -import { nftOrInputSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to mint the NFT to", - }, - metadatas: Type.Array(nftOrInputSchema), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - metadata: [ - { - name: "My NFT #1", - description: "My NFT #1 description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - { - name: "My NFT #2", - description: "My NFT #2 description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - ], - }, -]; - -export async function erc721mintBatchTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/mint-batch-to", - schema: { - summary: "Mint tokens (batch)", - description: - "Mint ERC-721 tokens to multiple wallets in one transaction.", - tags: ["ERC721"], - operationId: "erc721-mintBatchTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, metadatas, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc721.mintBatchTo.prepare(receiver, metadatas); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/mint-to.ts b/src/server/routes/contract/extensions/erc721/write/mint-to.ts deleted file mode 100644 index 0385d0bc5..000000000 --- a/src/server/routes/contract/extensions/erc721/write/mint-to.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { mintTo } from "thirdweb/extensions/erc721"; -import type { NFTInput } from "thirdweb/utils"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { nftOrInputSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - receiver: { - ...AddressSchema, - description: "Address of the wallet to mint the NFT to", - }, - metadata: nftOrInputSchema, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - receiver: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - metadata: { - name: "My NFT", - description: "My NFT description", - image: "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - }, -]; - -export async function erc721mintTo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/mint-to", - schema: { - summary: "Mint tokens", - description: "Mint ERC-721 tokens to a specific wallet.", - tags: ["ERC721"], - operationId: "erc721-mintTo", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain: _chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { receiver, metadata, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(_chain); - const chain = await getChain(chainId); - - const contract = getContract({ - chain, - client: thirdwebClient, - address: contractAddress, - }); - - // Backward compatibility: Transform the request body's v4 shape to v5. - const nft: NFTInput | string = - typeof metadata === "string" - ? metadata - : { - name: metadata.name?.toString() ?? undefined, - description: metadata.description ?? undefined, - image: metadata.image ?? undefined, - animation_url: metadata.animation_url ?? undefined, - external_url: metadata.external_url ?? undefined, - background_color: metadata.background_color ?? undefined, - properties: metadata.properties ?? undefined, - attributes: metadata.attributes ?? undefined, - }; - const transaction = mintTo({ - contract, - to: receiver, - nft, - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - extension: "erc721", - functionName: "mintTo", - shouldSimulate: simulateTx, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/set-approval-for-all.ts b/src/server/routes/contract/extensions/erc721/write/set-approval-for-all.ts deleted file mode 100644 index 52d69a119..000000000 --- a/src/server/routes/contract/extensions/erc721/write/set-approval-for-all.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - operator: Type.String({ - description: "Address of the operator to give approval to", - }), - approved: Type.Boolean({ - description: "whether to approve or revoke approval", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - operator: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - approved: "true", - }, -]; - -export async function erc721SetApprovalForAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/set-approval-for-all", - schema: { - summary: "Set approval for all", - description: - "Approve or remove operator as an operator for the caller. Operators can call transferFrom or safeTransferFrom for any token owned by the caller.", - tags: ["ERC721"], - operationId: "erc721-setApprovalForAll", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { operator, approved, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc721.setApprovalForAll.prepare( - operator, - approved, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/set-approval-for-token.ts b/src/server/routes/contract/extensions/erc721/write/set-approval-for-token.ts deleted file mode 100644 index d7a61e5a6..000000000 --- a/src/server/routes/contract/extensions/erc721/write/set-approval-for-token.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - operator: Type.String({ - description: "Address of the operator to give approval to", - }), - tokenId: Type.String({ - description: "the tokenId to give approval for", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - operator: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "0", - }, -]; - -export async function erc721SetApprovalForToken(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/set-approval-for-token", - schema: { - summary: "Set approval for token", - description: - "Approve an operator for the NFT owner. Operators can call transferFrom or safeTransferFrom for the specific token.", - tags: ["ERC721"], - operationId: "erc721-setApprovalForToken", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { operator, tokenId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc721.setApprovalForToken.prepare( - operator, - tokenId, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/set-claim-conditions.ts b/src/server/routes/contract/extensions/erc721/write/set-claim-conditions.ts deleted file mode 100644 index bb108b29a..000000000 --- a/src/server/routes/contract/extensions/erc721/write/set-claim-conditions.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type sanitizedClaimConditionInputSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - claimConditionInputs: Type.Array(claimConditionInputSchema), - resetClaimEligibilityForAll: Type.Optional(Type.Boolean()), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc721SetClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/set", - schema: { - summary: "Overwrite the claim conditions for the drop.", - description: - "Overwrite the claim conditions for the drop. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - tags: ["ERC721"], - operationId: "erc721-setClaimConditions", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { claimConditionInputs, resetClaimEligibilityForAll, txOverrides } = - request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInputs: Static< - typeof sanitizedClaimConditionInputSchema - >[] = claimConditionInputs.map((item) => { - return { - ...item, - startTime: item.startTime - ? isUnixEpochTimestamp(Number.parseInt(item.startTime.toString())) - ? new Date(Number.parseInt(item.startTime.toString()) * 1000) - : new Date(item.startTime) - : undefined, - }; - }); - const tx = await contract.erc721.claimConditions.set.prepare( - sanitizedClaimConditionInputs, - resetClaimEligibilityForAll, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/signature-mint.ts b/src/server/routes/contract/extensions/erc721/write/signature-mint.ts deleted file mode 100644 index 4cd0afddd..000000000 --- a/src/server/routes/contract/extensions/erc721/write/signature-mint.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { SignedPayload721WithQuantitySignature } from "@thirdweb-dev/sdk"; -import { BigNumber } from "ethers"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address, Hex } from "thirdweb"; -import { mintWithSignature } from "thirdweb/extensions/erc721"; -import { resolvePromisedValue } from "thirdweb/utils"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { getContractV5 } from "../../../../../../shared/utils/cache/get-contractv5"; -import { insertTransaction } from "../../../../../../shared/utils/transaction/insert-transaction"; -import type { thirdwebSdkVersionSchema } from "../../../../../schemas/http-headers/thirdweb-sdk-version"; -import { signature721OutputSchema } from "../../../../../schemas/nft"; -import { signature721OutputSchemaV5 } from "../../../../../schemas/nft/v5"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { parseTransactionOverrides } from "../../../../../utils/transaction-overrides"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - payload: Type.Union([signature721OutputSchema, signature721OutputSchemaV5]), - signature: Type.String(), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - payload: { - uri: "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - royaltyRecipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - quantity: "1", - royaltyBps: "0", - primarySaleRecipient: "0x0000000000000000000000000000000000000000", - uid: "0x3862386334363135326230303461303939626136653361643131343836373563", - metadata: { - name: "test tokenII", - description: "test token", - }, - currencyAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - price: "0", - mintStartTime: 1686169938, - mintEndTime: 2001529938, - }, - signature: - "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b", - }, -]; - -export async function erc721SignatureMint(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/signature/mint", - schema: { - summary: "Signature mint", - description: "Mint ERC-721 tokens from a generated signature.", - tags: ["ERC721"], - operationId: "erc721-signatureMint", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { payload, signature, txOverrides } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - const { "x-thirdweb-sdk-version": sdkVersion } = - request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - - let queueId: string; - if (sdkVersion === "5") { - const payloadV5 = payload as Static; - const contract = await getContractV5({ - chainId, - contractAddress, - }); - const transaction = mintWithSignature({ - contract, - payload: { - uri: payloadV5.uri, - to: payloadV5.to, - price: BigInt(payloadV5.price), - currency: payloadV5.currency, - primarySaleRecipient: payloadV5.primarySaleRecipient, - royaltyRecipient: payloadV5.royaltyRecipient, - royaltyBps: BigInt(payloadV5.royaltyBps), - validityStartTimestamp: BigInt(payloadV5.validityStartTimestamp), - validityEndTimestamp: BigInt(payloadV5.validityEndTimestamp), - uid: payloadV5.uid as Hex, - }, - signature: signature as Hex, - }); - - const insertedTransaction = { - chainId, - from: fromAddress as Address, - to: contractAddress as Address | undefined, - data: (await resolvePromisedValue(transaction.data)) as Hex, - ...parseTransactionOverrides(txOverrides), - }; - - if (accountAddress) { - queueId = await insertTransaction({ - insertedTransaction: { - ...insertedTransaction, - isUserOp: true, - accountAddress: accountAddress as Address, - signerAddress: fromAddress as Address, - target: contractAddress as Address | undefined, - transactionMode: undefined, - }, - shouldSimulate: simulateTx, - idempotencyKey, - }); - } else { - queueId = await insertTransaction({ - insertedTransaction: { - ...insertedTransaction, - isUserOp: false, - transactionMode, - }, - shouldSimulate: simulateTx, - idempotencyKey, - }); - } - } else { - const payloadV4 = payload as Static; - const contract = await getContract({ - chainId, - contractAddress, - walletAddress: fromAddress, - accountAddress, - }); - const signedPayload: SignedPayload721WithQuantitySignature = { - payload: { - ...payloadV4, - price: payloadV4.price ?? "0", - royaltyBps: BigNumber.from(payloadV4.royaltyBps), - quantity: BigNumber.from(payloadV4.quantity), - mintStartTime: BigNumber.from(payloadV4.mintStartTime), - mintEndTime: BigNumber.from(payloadV4.mintEndTime), - }, - signature, - }; - const tx = await contract.erc721.signature.mint.prepare(signedPayload); - - queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - }); - } - - reply.status(StatusCodes.OK).send({ - result: { queueId }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/transfer-from.ts b/src/server/routes/contract/extensions/erc721/write/transfer-from.ts deleted file mode 100644 index 2bbba5479..000000000 --- a/src/server/routes/contract/extensions/erc721/write/transfer-from.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { transferFrom } from "thirdweb/extensions/erc721"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { getChecksumAddress } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { NumberStringSchema } from "../../../../../schemas/number"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - from: { - ...AddressSchema, - description: "The sender address.", - }, - to: { - ...AddressSchema, - description: "The recipient address.", - }, - tokenId: { - ...NumberStringSchema, - description: "The token ID to transfer.", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - from: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - to: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "0", - }, -]; - -export async function erc721transferFrom(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/transfer-from", - schema: { - summary: "Transfer token from wallet", - description: - "Transfer an ERC-721 token from the connected wallet to another wallet. Requires allowance.", - tags: ["ERC721"], - operationId: "erc721-transferFrom", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { from, to, tokenId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - - const transaction = transferFrom({ - contract, - from: getChecksumAddress(from), - to: getChecksumAddress(to), - tokenId: BigInt(tokenId), - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: getChecksumAddress(walletAddress), - toAddress: getChecksumAddress(contractAddress), - accountAddress: getChecksumAddress(accountAddress), - accountFactoryAddress: getChecksumAddress(accountFactoryAddress), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - functionName: "transferFrom", - extension: "erc721", - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/transfer.ts b/src/server/routes/contract/extensions/erc721/write/transfer.ts deleted file mode 100644 index e2a0127c9..000000000 --- a/src/server/routes/contract/extensions/erc721/write/transfer.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { transferFrom } from "thirdweb/extensions/erc721"; -import { getChain } from "../../../../../../shared/utils/chain"; -import { getChecksumAddress } from "../../../../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../../../../shared/utils/sdk"; -import { queueTransaction } from "../../../../../../shared/utils/transaction/queue-transation"; -import { AddressSchema } from "../../../../../schemas/address"; -import { NumberStringSchema } from "../../../../../schemas/number"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - to: { - ...AddressSchema, - description: "The recipient address.", - }, - tokenId: { - ...NumberStringSchema, - description: "The token ID to transfer.", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - to: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - tokenId: "0", - }, -]; - -export async function erc721transfer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/transfer", - schema: { - summary: "Transfer token", - description: "Transfer an ERC-721 token from the caller wallet.", - tags: ["ERC721"], - operationId: "erc721-transfer", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { to, tokenId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - - const transaction = transferFrom({ - contract, - from: getChecksumAddress(walletAddress), - to: getChecksumAddress(to), - tokenId: BigInt(tokenId), - }); - - const queueId = await queueTransaction({ - transaction, - fromAddress: getChecksumAddress(walletAddress), - toAddress: getChecksumAddress(contractAddress), - accountAddress: getChecksumAddress(accountAddress), - accountFactoryAddress: getChecksumAddress(accountFactoryAddress), - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate: simulateTx, - functionName: "transferFrom", - extension: "erc721", - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/update-claim-conditions.ts b/src/server/routes/contract/extensions/erc721/write/update-claim-conditions.ts deleted file mode 100644 index 913091e9a..000000000 --- a/src/server/routes/contract/extensions/erc721/write/update-claim-conditions.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { - claimConditionInputSchema, - type sanitizedClaimConditionInputSchema, -} from "../../../../../schemas/claim-conditions"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; -import { isUnixEpochTimestamp } from "../../../../../utils/validator"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - claimConditionInput: claimConditionInputSchema, - index: Type.Integer({ - description: "Index of the claim condition to update", - minimum: 0, - }), - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc721UpdateClaimConditions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/claim-conditions/update", - schema: { - summary: "Update a single claim phase.", - description: - "Update a single claim phase, by providing the index of the claim phase and the new phase configuration. The index is the position of the phase in the list of phases you have made, starting from zero. e.g. if you have two phases, the first phase has an index of 0 and the second phase has an index of 1. All properties of a phase are optional, with the default being a free, open, unlimited claim, in the native currency, starting immediately.", - tags: ["ERC721"], - operationId: "erc721-updateClaimConditions", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { claimConditionInput, index, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - // Since Swagger doesn't allow for Date objects, we need to convert the - // startTime property to a Date object before passing it to the contract. - const sanitizedClaimConditionInput: Static< - typeof sanitizedClaimConditionInputSchema - > = { - ...claimConditionInput, - startTime: claimConditionInput.startTime - ? isUnixEpochTimestamp( - Number.parseInt(claimConditionInput.startTime.toString()), - ) - ? new Date( - Number.parseInt(claimConditionInput.startTime.toString()) * - 1000, - ) - : new Date(claimConditionInput.startTime) - : undefined, - }; - - const tx = await contract.erc721.claimConditions.update.prepare( - index, - sanitizedClaimConditionInput, - ); - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/erc721/write/update-token-metadata.ts b/src/server/routes/contract/extensions/erc721/write/update-token-metadata.ts deleted file mode 100644 index fd8aec9da..000000000 --- a/src/server/routes/contract/extensions/erc721/write/update-token-metadata.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../shared/utils/cache/get-contract"; -import { nftMetadataInputSchema } from "../../../../../schemas/nft"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../utils/chain"; - -// INPUT -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - tokenId: Type.String({ - description: "Token ID to update metadata", - }), - metadata: nftMetadataInputSchema, - ...txOverridesWithValueSchema.properties, -}); - -// LOGIC -export async function erc721UpdateTokenMetadata(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/erc721/token/update", - schema: { - summary: "Update token metadata", - description: "Update the metadata for an ERC721 token.", - tags: ["ERC721"], - operationId: "erc721-updateTokenMetadata", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { tokenId, metadata, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.erc721.updateMetadata.prepare( - tokenId, - metadata, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "erc721", - idempotencyKey, - txOverrides, - transactionMode, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-all-valid.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-all-valid.ts deleted file mode 100644 index a9c0e87f1..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-all-valid.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { directListingV3OutputSchema } from "../../../../../../schemas/marketplace-v3/direct-listing"; -import { - marketplaceFilterSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatDirectListingV3Result } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Omit(marketplaceFilterSchema, ["offeror"]); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(directListingV3OutputSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - currencyContractAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - quantity: "1", - pricePerToken: "10000000000", - isReservedListing: false, - id: "0", - currencyValuePerToken: { - name: "MATIC", - symbol: "MATIC", - decimals: 18, - value: "10000000000", - displayValue: "0.00000001", - }, - asset: { - id: "0", - uri: "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - status: 1, - startTimeInSeconds: 1686006043, - endTimeInSeconds: 1686610889, - }, - ], - }, -]; - -// LOGIC -export async function directListingsGetAllValid(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/direct-listings/get-all-valid", - schema: { - summary: "Get all valid listings", - description: - "Get all the valid direct listings for this marketplace contract. A valid listing is where the listing is active, and the creator still owns & has approved Marketplace to transfer the listed NFTs.", - tags: ["Marketplace-DirectListings"], - operationId: "getAllValidDirectListings", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count, seller, tokenContract, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.directListings.getAllValid({ - start, - count, - tokenContract, - tokenId, - seller, - }); - - const finalResult = result.map((data) => { - return formatDirectListingV3Result(data); - }); - reply.status(StatusCodes.OK).send({ - result: finalResult, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-all.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-all.ts deleted file mode 100644 index 098a1c0b1..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-all.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { directListingV3OutputSchema } from "../../../../../../schemas/marketplace-v3/direct-listing"; -import { - marketplaceFilterSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatDirectListingV3Result } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Omit(marketplaceFilterSchema, ["offeror"]); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(directListingV3OutputSchema), -}); - -responseSchema.example = [ - { - result: [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - currencyContractAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - quantity: "1", - pricePerToken: "10000000000", - isReservedListing: false, - id: "0", - currencyValuePerToken: { - name: "MATIC", - symbol: "MATIC", - decimals: 18, - value: "10000000000", - displayValue: "0.00000001", - }, - asset: { - id: "0", - uri: "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - status: 1, - startTimeInSeconds: 1686006043, - endTimeInSeconds: 1686610889, - }, - ], - }, -]; - -// LOGIC -export async function directListingsGetAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/direct-listings/get-all", - schema: { - summary: "Get all listings", - description: "Get all direct listings for this marketplace contract.", - tags: ["Marketplace-DirectListings"], - operationId: "getAllDirectListings", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count, seller, tokenContract, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.directListings.getAll({ - start, - count, - tokenContract, - tokenId, - seller, - }); - - const finalResult = result.map((data) => { - return formatDirectListingV3Result(data); - }); - reply.status(StatusCodes.OK).send({ - result: finalResult, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-listing.ts deleted file mode 100644 index dcf842531..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-listing.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { directListingV3OutputSchema } from "../../../../../../schemas/marketplace-v3/direct-listing"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatDirectListingV3Result } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The id of the listing to retrieve.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: directListingV3OutputSchema, -}); - -responseSchema.examples = [ - { - result: [ - { - metadata: { - id: "0", - uri: "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - name: "My Edition NFT", - description: "My Edition NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - type: "ERC1155", - supply: "100", - quantityOwned: "100", - }, - ], - }, -]; - -// LOGIC -export async function directListingsGetListing(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/direct-listings/get-listing", - schema: { - summary: "Get direct listing", - description: "Gets a direct listing on this marketplace contract.", - tags: ["Marketplace-DirectListings"], - operationId: "getDirectListing", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.directListings.getListing(listingId); - - reply.status(StatusCodes.OK).send({ - result: formatDirectListingV3Result(result), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-total-count.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-total-count.ts deleted file mode 100644 index 3a41ecf0a..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/get-total-count.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.String(), -}); - -responseSchema.examples = [ - { - result: "1", - }, -]; - -// LOGIC -export async function directListingsGetTotalCount(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/direct-listings/get-total-count", - schema: { - summary: "Transfer token from wallet", - description: - "Get the total number of direct listings on this marketplace contract.", - tags: ["Marketplace-DirectListings"], - operationId: "getDirectListingsTotalCount", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.directListings.getTotalCount(); - - reply.status(StatusCodes.OK).send({ - result: result.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/is-buyer-approved-for-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/is-buyer-approved-for-listing.ts deleted file mode 100644 index 5ff4ece65..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/is-buyer-approved-for-listing.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../../schemas/address"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The id of the listing to retrieve.", - }), - walletAddress: { - ...AddressSchema, - description: "The wallet address of the buyer to check.", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Boolean(), -}); - -responseSchema.examples = [ - { - result: true, - }, -]; - -// LOGIC -export async function directListingsIsBuyerApprovedForListing( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/direct-listings/is-buyer-approved-for-listing", - schema: { - summary: "Check approved buyer", - description: - "Check if a buyer is approved to purchase a specific direct listing.", - tags: ["Marketplace-DirectListings"], - operationId: "isBuyerApprovedForDirectListings", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId, walletAddress } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.directListings.isBuyerApprovedForListing( - listingId, - walletAddress, - ); - - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/is-currency-approved-for-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/is-currency-approved-for-listing.ts deleted file mode 100644 index b6decb98e..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/read/is-currency-approved-for-listing.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../../schemas/address"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The id of the listing to retrieve.", - }), - currencyContractAddress: { - ...AddressSchema, - description: "The smart contract address of the ERC20 token to check.", - }, -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Boolean(), -}); - -responseSchema.examples = [ - { - result: true, - }, -]; - -// LOGIC -export async function directListingsIsCurrencyApprovedForListing( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/direct-listings/is-currency-approved-for-listing", - schema: { - summary: "Check approved currency", - description: - "Check if a currency is approved for a specific direct listing.", - tags: ["Marketplace-DirectListings"], - operationId: "isCurrencyApprovedForDirectListings", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId, currencyContractAddress } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.directListings.isCurrencyApprovedForListing( - listingId, - currencyContractAddress, - ); - - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/approve-buyer-for-reserved-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/approve-buyer-for-reserved-listing.ts deleted file mode 100644 index 516f80d2f..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/approve-buyer-for-reserved-listing.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing you want to approve a buyer for.", - }), - buyer: Type.String({ - description: "The wallet address of the buyer to approve.", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - listingId: "0", - buyer: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - }, -]; - -// LOGIC -export async function directListingsApproveBuyerForReservedListing( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/approve-buyer-for-reserved-listing", - schema: { - summary: "Approve buyer for reserved listing", - description: "Approve a wallet address to buy from a reserved listing.", - tags: ["Marketplace-DirectListings"], - operationId: "approveBuyerForReservedListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId, buyer, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = - await contract.directListings.approveBuyerForReservedListing.prepare( - listingId, - buyer, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/buy-from-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/buy-from-listing.ts deleted file mode 100644 index 2fdbd5fde..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/buy-from-listing.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing you want to approve a buyer for.", - }), - quantity: Type.String({ - description: "The number of tokens to buy (default is 1 for ERC721 NFTs).", - }), - buyer: Type.String({ - description: "The wallet address of the buyer.", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - listingId: "0", - quantity: "1", - buyer: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - }, -]; - -// LOGIC -export async function directListingsBuyFromListing(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/buy-from-listing", - schema: { - summary: "Buy from direct listing", - description: - "Buy from a specific direct listing from this marketplace contract.", - tags: ["Marketplace-DirectListings"], - operationId: "buyFromDirectListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId, quantity, buyer, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.directListings.buyFromListing.prepare( - listingId, - quantity, - buyer, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/cancel-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/cancel-listing.ts deleted file mode 100644 index 1a713919c..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/cancel-listing.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing you want to cancel.", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function directListingsCancelListing(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/cancel-listing", - schema: { - summary: "Cancel direct listing", - description: - "Cancel a direct listing from this marketplace contract. Only the creator of the listing can cancel it.", - tags: ["Marketplace-DirectListings"], - operationId: "cancelDirectListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.directListings.cancelListing.prepare(listingId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/create-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/create-listing.ts deleted file mode 100644 index 839614c83..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/create-listing.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { directListingV3InputSchema } from "../../../../../../schemas/marketplace-v3/direct-listing"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - ...directListingV3InputSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - pricePerToken: "0.00000001", - isReservedListing: false, - quantity: "1", - startTimestamp: 1686006043038, - endTimestamp: 1686610889058, - }, -]; - -// LOGIC -export async function directListingsCreateListing(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/create-listing", - schema: { - summary: "Create direct listing", - description: "Create a direct listing on this marketplace contract.", - tags: ["Marketplace-DirectListings"], - operationId: "createDirectListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { - assetContractAddress, - tokenId, - pricePerToken, - currencyContractAddress, - isReservedListing, - quantity, - startTimestamp, - endTimestamp, - txOverrides, - } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.directListings.createListing.prepare({ - assetContractAddress, - tokenId, - pricePerToken, - currencyContractAddress, - isReservedListing, - quantity, - startTimestamp, - endTimestamp, - }); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/revoke-buyer-approval-for-reserved-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/revoke-buyer-approval-for-reserved-listing.ts deleted file mode 100644 index 8441a26f6..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/revoke-buyer-approval-for-reserved-listing.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../../schemas/address"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing you want to approve a buyer for.", - }), - buyerAddress: { - ...AddressSchema, - description: "The wallet address of the buyer to approve.", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - listingId: "0", - buyerAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - }, -]; - -// LOGIC -export async function directListingsRevokeBuyerApprovalForReservedListing( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/revoke-buyer-approval-for-reserved-listing", - schema: { - summary: "Revoke approval for reserved listings", - description: - "Revoke approval for a buyer to purchase a reserved listing.", - tags: ["Marketplace-DirectListings"], - operationId: "revokeBuyerApprovalForReservedListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId, buyerAddress, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = - await contract.directListings.revokeBuyerApprovalForReservedListing.prepare( - listingId, - buyerAddress, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/revoke-currency-approval-for-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/revoke-currency-approval-for-listing.ts deleted file mode 100644 index 173ae8b38..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/revoke-currency-approval-for-listing.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../../../schemas/address"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing you want to approve a buyer for.", - }), - currencyContractAddress: { - ...AddressSchema, - description: "The wallet address of the buyer to approve.", - }, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - listingId: "0", - currencyContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - }, -]; - -// LOGIC -export async function directListingsRevokeCurrencyApprovalForListing( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/revoke-currency-approval-for-listing", - schema: { - summary: "Revoke currency approval for reserved listing", - description: "Revoke approval of a currency for a reserved listing.", - tags: ["Marketplace-DirectListings"], - operationId: "revokeCurrencyApprovalForListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId, currencyContractAddress, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = - await contract.directListings.revokeCurrencyApprovalForListing.prepare( - listingId, - currencyContractAddress, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/update-listing.ts b/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/update-listing.ts deleted file mode 100644 index e58fb3ed6..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/direct-listings/write/update-listing.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { directListingV3InputSchema } from "../../../../../../schemas/marketplace-v3/direct-listing"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing you want to update.", - }), - ...directListingV3InputSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function directListingsUpdateListing(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/direct-listings/update-listing", - schema: { - summary: "Update direct listing", - description: "Update a direct listing on this marketplace contract.", - tags: ["Marketplace-DirectListings"], - operationId: "updateDirectListing", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { - listingId, - assetContractAddress, - tokenId, - pricePerToken, - currencyContractAddress, - isReservedListing, - quantity, - startTimestamp, - endTimestamp, - txOverrides, - } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.directListings.updateListing.prepare( - listingId, - { - assetContractAddress, - tokenId, - pricePerToken, - currencyContractAddress, - isReservedListing, - quantity, - startTimestamp, - endTimestamp, - }, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-direct-listings", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-all-valid.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-all-valid.ts deleted file mode 100644 index 1f52bacc9..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-all-valid.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { englishAuctionOutputSchema } from "../../../../../../schemas/marketplace-v3/english-auction"; -import { - marketplaceFilterSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatEnglishAuctionResult } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Omit(marketplaceFilterSchema, ["offeror"]); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(englishAuctionOutputSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - currencyContractAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - quantity: "1", - id: "0", - minimumBidAmount: "10000000000", - buyoutBidAmount: "10000000000", - buyoutCurrencyValue: { - name: "MATIC", - symbol: "MATIC", - decimals: 18, - value: "10000000000", - displayValue: "0.00000001", - }, - timeBufferInSeconds: 600, - bidBufferBps: 100, - startTimeInSeconds: 1686006043, - endTimeInSeconds: 1686610889, - asset: { - id: "0", - uri: "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - status: 1, - }, - ], - }, -]; - -// LOGIC -export async function englishAuctionsGetAllValid(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-all-valid", - schema: { - summary: "Get all valid English auctions", - description: - "Get all valid English auction listings on this marketplace contract.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "getAllValidEnglishAuctions", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count, seller, tokenContract, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getAllValid({ - start, - count, - tokenContract, - tokenId, - seller, - }); - - const finalResult = result.map((data) => { - return formatEnglishAuctionResult(data); - }); - reply.status(StatusCodes.OK).send({ - result: finalResult, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-all.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-all.ts deleted file mode 100644 index 489f8fc1c..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-all.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { englishAuctionOutputSchema } from "../../../../../../schemas/marketplace-v3/english-auction"; -import { - marketplaceFilterSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatEnglishAuctionResult } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Omit(marketplaceFilterSchema, ["offeror"]); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(englishAuctionOutputSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - currencyContractAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - quantity: "1", - id: "0", - minimumBidAmount: "10000000000", - buyoutBidAmount: "10000000000", - buyoutCurrencyValue: { - name: "MATIC", - symbol: "MATIC", - decimals: 18, - value: "10000000000", - displayValue: "0.00000001", - }, - timeBufferInSeconds: 600, - bidBufferBps: 100, - startTimeInSeconds: 1686006043, - endTimeInSeconds: 1686610889, - asset: { - id: "0", - uri: "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - status: 1, - }, - ], - }, -]; - -// LOGIC -export async function englishAuctionsGetAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-all", - schema: { - summary: "Get all English auctions", - description: - "Get all English auction listings on this marketplace contract.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "getAllEnglishAuctions", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count, seller, tokenContract, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getAll({ - start, - count, - tokenContract, - tokenId, - seller, - }); - - const finalResult = result.map((data) => { - return formatEnglishAuctionResult(data); - }); - reply.status(StatusCodes.OK).send({ - result: finalResult, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-auction.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-auction.ts deleted file mode 100644 index fd8bcce4b..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-auction.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { englishAuctionOutputSchema } from "../../../../../../schemas/marketplace-v3/english-auction"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatEnglishAuctionResult } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The id of the listing to retrieve.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: englishAuctionOutputSchema, -}); - -responseSchema.examples = [ - { - result: [ - { - metadata: { - id: "0", - uri: "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - name: "My Edition NFT", - description: "My Edition NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - type: "ERC1155", - supply: "100", - quantityOwned: "100", - }, - ], - }, -]; - -// LOGIC -export async function englishAuctionsGetAuction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-auction", - schema: { - summary: "Get English auction", - description: - "Get a specific English auction listing on this marketplace contract.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "getEnglishAuction", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getAuction(listingId); - - reply.status(StatusCodes.OK).send({ - result: formatEnglishAuctionResult(result), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-bid-buffer-bps.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-bid-buffer-bps.ts deleted file mode 100644 index 31a67e00f..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-bid-buffer-bps.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The id of the listing to retrieve.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Integer({ - description: - "Returns a number representing the basis points of the bid buffer.", - }), -}); - -responseSchema.examples = [ - { - result: "1", - }, -]; - -// LOGIC -export async function englishAuctionsGetBidBufferBps(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-bid-buffer-bps", - schema: { - summary: "Get bid buffer BPS", - description: `Get the basis points of the bid buffer. -This is the percentage higher that a new bid must be than the current highest bid in order to be placed. -If there is no current bid, the bid must be at least the minimum bid amount. -Returns the value in percentage format, e.g. 100 = 1%.`, - tags: ["Marketplace-EnglishAuctions"], - operationId: "getEnglishAuctionsBidBufferBps", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getBidBufferBps(listingId); - - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-minimum-next-bid.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-minimum-next-bid.ts deleted file mode 100644 index d0e572161..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-minimum-next-bid.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - currencyValueSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The id of the listing to retrieve.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: currencyValueSchema, -}); - -responseSchema.examples = [ - { - result: "1", - }, -]; - -// LOGIC -export async function englishAuctionsGetMinimumNextBid( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-minimum-next-bid", - schema: { - summary: "Get minimum next bid", - description: `Helper function to calculate the value that the next bid must be in order to be accepted. -If there is no current bid, the bid must be at least the minimum bid amount. -If there is a current bid, the bid must be at least the current bid amount + the bid buffer.`, - tags: ["Marketplace-EnglishAuctions"], - operationId: "getEnglishAuctionsMinimumNextBid", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = - await contract.englishAuctions.getMinimumNextBid(listingId); - - reply.status(StatusCodes.OK).send({ - result: { - ...result, - value: result.value.toString(), - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-total-count.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-total-count.ts deleted file mode 100644 index abeadd297..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-total-count.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.String(), -}); - -responseSchema.examples = [ - { - result: "1", - }, -]; - -// LOGIC -export async function englishAuctionsGetTotalCount(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-total-count", - schema: { - summary: "Get total listings", - description: - "Get the count of English auction listings on this marketplace contract.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "getEnglishAuctionsTotalCount", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getTotalCount(); - - reply.status(StatusCodes.OK).send({ - result: result.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-winner.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-winner.ts deleted file mode 100644 index fbad3aa62..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-winner.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to retrieve the winner for.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.String(), -}); - -responseSchema.examples = [ - { - result: "0x...", - }, -]; - -// LOGIC -export async function englishAuctionsGetWinner(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-winner", - schema: { - summary: "Get winner", - description: - "Get the winner of an English auction. Can only be called after the auction has ended.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "getEnglishAuctionsWinner", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getWinner(listingId); - - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-winning-bid.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-winning-bid.ts deleted file mode 100644 index ec8ad5859..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/get-winning-bid.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { bidSchema } from "../../../../../../schemas/marketplace-v3/english-auction"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to retrieve the winner for.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Optional(bidSchema), -}); - -responseSchema.examples = [ - { - result: "0x...", - }, -]; - -// LOGIC -export async function englishAuctionsGetWinningBid(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/get-winning-bid", - schema: { - summary: "Get winning bid", - description: "Get the current highest bid of an active auction.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "getEnglishAuctionsWinningBid", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getWinningBid(listingId); - - reply.status(StatusCodes.OK).send({ - result: { - ...result, - bidAmountCurrencyValue: { - ...result?.bidAmountCurrencyValue, - value: result?.bidAmountCurrencyValue.value.toString(), - }, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/is-winning-bid.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/is-winning-bid.ts deleted file mode 100644 index 71ffb1df5..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/read/is-winning-bid.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to retrieve the winner for.", - }), - bidAmount: Type.String({ - description: "The amount of the bid to check if it is the winning bid.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Boolean(), -}); - -responseSchema.examples = [ - { - result: true, - }, -]; - -// LOGIC -export async function englishAuctionsIsWinningBid(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/english-auctions/is-winning-bid", - schema: { - summary: "Check winning bid", - description: - "Check if a bid is or will be the winning bid for an auction.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "isEnglishAuctionsWinningBid", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { listingId, bidAmount } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.isWinningBid( - listingId, - bidAmount, - ); - - reply.status(StatusCodes.OK).send({ - result, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/buyout-auction.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/buyout-auction.ts deleted file mode 100644 index f034b5d34..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/buyout-auction.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to buy NFT(s) from.", - }), -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function englishAuctionsBuyoutAuction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/buyout-auction", - schema: { - summary: "Buyout English auction", - description: "Buyout the listing for this auction.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "buyoutEnglishAuction", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = - await contract.englishAuctions.buyoutAuction.prepare(listingId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/cancel-auction.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/cancel-auction.ts deleted file mode 100644 index 1de125d87..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/cancel-auction.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to cancel auction.", - }), -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function englishAuctionsCancelAuction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/cancel-auction", - schema: { - summary: "Cancel English auction", - description: - "Cancel an existing auction listing. Only the creator of the listing can cancel it. Auctions cannot be canceled once a bid has been made.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "cancelEnglishAuction", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = - await contract.englishAuctions.cancelAuction.prepare(listingId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/close-auction-for-bidder.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/close-auction-for-bidder.ts deleted file mode 100644 index 6cadc15b4..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/close-auction-for-bidder.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to execute the sale for.", - }), -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function englishAuctionsCloseAuctionForBidder( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/close-auction-for-bidder", - schema: { - summary: "Close English auction for bidder", - description: `After an auction has concluded (and a buyout did not occur), -execute the sale for the buyer, meaning the buyer receives the NFT(s). -You must also call closeAuctionForSeller to execute the sale for the seller, -meaning the seller receives the payment from the highest bid.`, - tags: ["Marketplace-EnglishAuctions"], - operationId: "closeEnglishAuctionForBidder", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = - await contract.englishAuctions.closeAuctionForBidder.prepare(listingId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/close-auction-for-seller.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/close-auction-for-seller.ts deleted file mode 100644 index 043e7b95f..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/close-auction-for-seller.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to execute the sale for.", - }), -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function englishAuctionsCloseAuctionForSeller( - fastify: FastifyInstance, -) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/close-auction-for-seller", - schema: { - summary: "Close English auction for seller", - description: `After an auction has concluded (and a buyout did not occur), -execute the sale for the seller, meaning the seller receives the payment from the highest bid. -You must also call closeAuctionForBidder to execute the sale for the buyer, meaning the buyer receives the NFT(s).`, - tags: ["Marketplace-EnglishAuctions"], - operationId: "closeEnglishAuctionForSeller", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = - await contract.englishAuctions.closeAuctionForSeller.prepare(listingId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/create-auction.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/create-auction.ts deleted file mode 100644 index d138acd2a..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/create-auction.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { englishAuctionInputSchema } from "../../../../../../schemas/marketplace-v3/english-auction"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = englishAuctionInputSchema; - -requestBodySchema.examples = [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - quantity: "1", - startTimestamp: 1686006043038, - endTimestamp: 1686610889058, - buyoutBidAmount: "0.00000001", - minimumBidAmount: "0.00000001", - currencyContractAddress: "0x...", - bidBufferBps: 100, - timeBufferInSeconds: 60 * 10, - }, -]; - -// LOGIC -export async function englishAuctionsCreateAuction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/create-auction", - schema: { - summary: "Create English auction", - description: - "Create an English auction listing on this marketplace contract.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "createEnglishAuction", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { - assetContractAddress, - tokenId, - buyoutBidAmount, - minimumBidAmount, - currencyContractAddress, - quantity, - startTimestamp, - endTimestamp, - bidBufferBps, - timeBufferInSeconds, - } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = await contract.englishAuctions.createAuction.prepare({ - assetContractAddress, - tokenId, - buyoutBidAmount, - minimumBidAmount, - currencyContractAddress, - quantity, - startTimestamp, - endTimestamp, - bidBufferBps, - timeBufferInSeconds, - }); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/execute-sale.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/execute-sale.ts deleted file mode 100644 index 355241e40..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/execute-sale.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to execute the sale for.", - }), -}); - -requestBodySchema.examples = [ - { - listingId: "0", - }, -]; - -// LOGIC -export async function englishAuctionsExecuteSale(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/execute-sale", - schema: { - summary: "Execute sale", - description: `Close the auction for both buyer and seller. -This means the NFT(s) will be transferred to the buyer and the seller will receive the funds. -This function can only be called after the auction has ended.`, - tags: ["Marketplace-EnglishAuctions"], - operationId: "executeEnglishAuctionSale", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = await contract.englishAuctions.executeSale.prepare(listingId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/make-bid.ts b/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/make-bid.ts deleted file mode 100644 index a9b254b35..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/english-auctions/write/make-bid.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - listingId: Type.String({ - description: "The ID of the listing to place a bid on.", - }), - bidAmount: Type.String({ - description: - "The amount of the bid to place in the currency of the listing. Use getNextBidAmount to get the minimum amount for the next bid.", - }), -}); - -requestBodySchema.examples = [ - { - listingId: "0", - bidAmount: "0.00000001", - }, -]; - -// LOGIC -export async function englishAuctionsMakeBid(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/english-auctions/make-bid", - schema: { - summary: "Make bid", - description: "Place a bid on an English auction listing.", - tags: ["Marketplace-EnglishAuctions"], - operationId: "makeEnglishAuctionBid", - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { listingId, bidAmount } = request.body; - const walletAddress = request.headers[ - "x-backend-wallet-address" - ] as string; - const accountAddress = request.headers["x-account-address"] as string; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - - const tx = await contract.englishAuctions.makeBid.prepare( - listingId, - bidAmount, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-english-auctions", - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/index.ts b/src/server/routes/contract/extensions/marketplace-v3/index.ts deleted file mode 100644 index cbddf19e3..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/index.ts +++ /dev/null @@ -1,93 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { directListingsGetAll } from "./direct-listings/read/get-all"; -import { directListingsGetAllValid } from "./direct-listings/read/get-all-valid"; -import { directListingsGetListing } from "./direct-listings/read/get-listing"; -import { directListingsGetTotalCount } from "./direct-listings/read/get-total-count"; -import { directListingsIsBuyerApprovedForListing } from "./direct-listings/read/is-buyer-approved-for-listing"; -import { directListingsIsCurrencyApprovedForListing } from "./direct-listings/read/is-currency-approved-for-listing"; -import { directListingsApproveBuyerForReservedListing } from "./direct-listings/write/approve-buyer-for-reserved-listing"; -import { directListingsBuyFromListing } from "./direct-listings/write/buy-from-listing"; -import { directListingsCancelListing } from "./direct-listings/write/cancel-listing"; -import { directListingsCreateListing } from "./direct-listings/write/create-listing"; -import { directListingsRevokeBuyerApprovalForReservedListing } from "./direct-listings/write/revoke-buyer-approval-for-reserved-listing"; -import { directListingsRevokeCurrencyApprovalForListing } from "./direct-listings/write/revoke-currency-approval-for-listing"; -import { directListingsUpdateListing } from "./direct-listings/write/update-listing"; - -import { englishAuctionsGetAll } from "./english-auctions/read/get-all"; -import { englishAuctionsGetAllValid } from "./english-auctions/read/get-all-valid"; -import { englishAuctionsGetAuction } from "./english-auctions/read/get-auction"; -import { englishAuctionsGetBidBufferBps } from "./english-auctions/read/get-bid-buffer-bps"; -import { englishAuctionsGetMinimumNextBid } from "./english-auctions/read/get-minimum-next-bid"; -import { englishAuctionsGetTotalCount } from "./english-auctions/read/get-total-count"; -import { englishAuctionsGetWinningBid } from "./english-auctions/read/get-winning-bid"; -import { englishAuctionsIsWinningBid } from "./english-auctions/read/is-winning-bid"; -import { englishAuctionsBuyoutAuction } from "./english-auctions/write/buyout-auction"; -import { englishAuctionsCancelAuction } from "./english-auctions/write/cancel-auction"; -import { englishAuctionsCloseAuctionForBidder } from "./english-auctions/write/close-auction-for-bidder"; -import { englishAuctionsCloseAuctionForSeller } from "./english-auctions/write/close-auction-for-seller"; -import { englishAuctionsCreateAuction } from "./english-auctions/write/create-auction"; -import { englishAuctionsExecuteSale } from "./english-auctions/write/execute-sale"; -import { englishAuctionsMakeBid } from "./english-auctions/write/make-bid"; - -import { englishAuctionsGetWinner } from "./english-auctions/read/get-winner"; -import { offersGetAll } from "./offers/read/get-all"; -import { offersGetAllValid } from "./offers/read/get-all-valid"; -import { offersGetOffer } from "./offers/read/get-offer"; -import { offersGetTotalCount } from "./offers/read/get-total-count"; -import { offersAcceptOffer } from "./offers/write/accept-offer"; -import { offersCancelOffer } from "./offers/write/cancel-offer"; -import { offersMakeOffer } from "./offers/write/make-offer"; - -export const marketplaceV3Routes = async (fastify: FastifyInstance) => { - // READ - - // Direct Listings - await fastify.register(directListingsGetAll); - await fastify.register(directListingsGetAllValid); - await fastify.register(directListingsGetListing); - await fastify.register(directListingsIsBuyerApprovedForListing); - await fastify.register(directListingsIsCurrencyApprovedForListing); - await fastify.register(directListingsGetTotalCount); - - // English Auctions - await fastify.register(englishAuctionsGetAll); - await fastify.register(englishAuctionsGetAllValid); - await fastify.register(englishAuctionsGetAuction); - await fastify.register(englishAuctionsGetBidBufferBps); - await fastify.register(englishAuctionsGetMinimumNextBid); - await fastify.register(englishAuctionsGetWinningBid); - await fastify.register(englishAuctionsGetTotalCount); - await fastify.register(englishAuctionsIsWinningBid); - await fastify.register(englishAuctionsGetWinner); - - // Offers - await fastify.register(offersGetAll); - await fastify.register(offersGetAllValid); - await fastify.register(offersGetOffer); - await fastify.register(offersGetTotalCount); - - // WRITE - - // Direct Listings - await fastify.register(directListingsCreateListing); - await fastify.register(directListingsUpdateListing); - await fastify.register(directListingsBuyFromListing); - await fastify.register(directListingsApproveBuyerForReservedListing); - await fastify.register(directListingsRevokeBuyerApprovalForReservedListing); - await fastify.register(directListingsRevokeCurrencyApprovalForListing); - await fastify.register(directListingsCancelListing); - - // English Auctions - await fastify.register(englishAuctionsBuyoutAuction); - await fastify.register(englishAuctionsCancelAuction); - await fastify.register(englishAuctionsCreateAuction); - await fastify.register(englishAuctionsCloseAuctionForBidder); - await fastify.register(englishAuctionsCloseAuctionForSeller); - await fastify.register(englishAuctionsExecuteSale); - await fastify.register(englishAuctionsMakeBid); - - // Offers - await fastify.register(offersMakeOffer); - await fastify.register(offersCancelOffer); - await fastify.register(offersAcceptOffer); -}; diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-all-valid.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-all-valid.ts deleted file mode 100644 index ee0eafbe8..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-all-valid.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { OfferV3OutputSchema } from "../../../../../../schemas/marketplace-v3/offer"; -import { - marketplaceFilterSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatOffersV3Result } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Omit(marketplaceFilterSchema, ["seller"]); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(OfferV3OutputSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - currencyContractAddress: "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", - quantity: "1", - id: "0", - offerorAddress: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - currencyValue: { - name: "Wrapped Matic", - symbol: "WMATIC", - decimals: 18, - value: "10000000000", - displayValue: "0.00000001", - }, - totalPrice: "10000000000", - asset: { - id: "0", - uri: "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - endTimeInSeconds: 1686610889, - status: 4, - }, - ], - }, -]; - -// LOGIC -export async function offersGetAllValid(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/offers/get-all-valid", - schema: { - summary: "Get all valid offers", - description: - "Get all valid offers on this marketplace contract. Valid offers are offers that have not expired, been canceled, or been accepted.", - tags: ["Marketplace-Offers"], - operationId: "getAllValidMarketplaceOffers", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count, offeror, tokenContract, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.offers.getAllValid({ - start, - count, - tokenContract, - tokenId, - offeror, - }); - - const finalResult = result.map((data) => { - return formatOffersV3Result(data); - }); - reply.status(StatusCodes.OK).send({ - result: finalResult, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-all.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-all.ts deleted file mode 100644 index c6fc6d0cf..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-all.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { OfferV3OutputSchema } from "../../../../../../schemas/marketplace-v3/offer"; -import { - marketplaceFilterSchema, - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatOffersV3Result } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Omit(marketplaceFilterSchema, ["seller"]); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(OfferV3OutputSchema), -}); - -responseSchema.examples = [ - { - result: [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - currencyContractAddress: "0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889", - quantity: "1", - id: "0", - offerorAddress: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - currencyValue: { - name: "Wrapped Matic", - symbol: "WMATIC", - decimals: 18, - value: "10000000000", - displayValue: "0.00000001", - }, - totalPrice: "10000000000", - asset: { - id: "0", - uri: "ipfs://QmPw2Dd1dnB6dQCnqGayCTnxUxHrB7m4YFeyph6PYPMboP/0", - name: "TJ-Origin", - description: "Origin", - external_url: "", - attributes: [ - { - trait_type: "Mode", - value: "GOD", - }, - ], - }, - endTimeInSeconds: 1686610889, - status: 4, - }, - ], - }, -]; - -// LOGIC -export async function offersGetAll(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/offers/get-all", - schema: { - summary: "Get all offers", - description: "Get all offers on this marketplace contract.", - tags: ["Marketplace-Offers"], - operationId: "getAllMarketplaceOffers", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { start, count, offeror, tokenContract, tokenId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.offers.getAll({ - start, - count, - tokenContract, - tokenId, - offeror, - }); - - const finalResult = result.map((data) => { - return formatOffersV3Result(data); - }); - reply.status(StatusCodes.OK).send({ - result: finalResult, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-offer.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-offer.ts deleted file mode 100644 index d1bca7099..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-offer.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { OfferV3OutputSchema } from "../../../../../../schemas/marketplace-v3/offer"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; -import { formatOffersV3Result } from "../../../../../../utils/marketplace-v3"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestQuerySchema = Type.Object({ - offerId: Type.String({ - description: "The ID of the offer to get information about.", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: OfferV3OutputSchema, -}); - -responseSchema.examples = [ - { - result: [ - { - metadata: { - id: "0", - uri: "ipfs://QmdaWX1GEwnFW4NooYRej5BQybKNLdxkWtMwyw8KiWRueS/0", - name: "My Edition NFT", - description: "My Edition NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - owner: "0xE79ee09bD47F4F5381dbbACaCff2040f2FbC5803", - type: "ERC1155", - supply: "100", - quantityOwned: "100", - }, - ], - }, -]; - -// LOGIC -export async function offersGetOffer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/offers/get-offer", - schema: { - summary: "Get offer", - description: "Get details about an offer.", - tags: ["Marketplace-Offers"], - operationId: "getMarketplaceOffer", - params: requestSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { offerId } = request.query; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.offers.getOffer(offerId); - - reply.status(StatusCodes.OK).send({ - result: formatOffersV3Result(result), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-total-count.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-total-count.ts deleted file mode 100644 index 6a2758d11..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/read/get-total-count.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - standardResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.String(), -}); - -responseSchema.examples = [ - { - result: "1", - }, -]; - -// LOGIC -export async function offersGetTotalCount(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/marketplace/:chain/:contractAddress/offers/get-total-count", - schema: { - summary: "Get total count", - description: - "Get the total number of offers on this marketplace contract.", - tags: ["Marketplace-Offers"], - operationId: "getMarketplaceOffersTotalCount", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - const result = await contract.englishAuctions.getTotalCount(); - - reply.status(StatusCodes.OK).send({ - result: result.toString(), - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/write/accept-offer.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/write/accept-offer.ts deleted file mode 100644 index 7941ce97e..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/write/accept-offer.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - offerId: Type.String({ - description: - "The ID of the offer to accept. You can view all offers with getAll or getAllValid.", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - offerId: "1", - }, -]; - -// LOGIC -export async function offersAcceptOffer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/offers/accept-offer", - schema: { - summary: "Accept offer", - description: "Accept a valid offer.", - tags: ["Marketplace-Offers"], - operationId: "acceptMarketplaceOffer", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { offerId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.offers.acceptOffer.prepare(offerId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-offers", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/write/cancel-offer.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/write/cancel-offer.ts deleted file mode 100644 index e8528703f..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/write/cancel-offer.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - offerId: Type.String({ - description: - "The ID of the offer to cancel. You can view all offers with getAll or getAllValid.", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - offerId: "1", - }, -]; - -// LOGIC -export async function offersCancelOffer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/offers/cancel-offer", - schema: { - summary: "Cancel offer", - description: "Cancel a valid offer made by the caller wallet.", - tags: ["Marketplace-Offers"], - operationId: "cancelMarketplaceOffer", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { offerId, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.offers.cancelOffer.prepare(offerId); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-offers", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/extensions/marketplace-v3/offers/write/make-offer.ts b/src/server/routes/contract/extensions/marketplace-v3/offers/write/make-offer.ts deleted file mode 100644 index 828b4173a..000000000 --- a/src/server/routes/contract/extensions/marketplace-v3/offers/write/make-offer.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../../../shared/utils/cache/get-contract"; -import { OfferV3InputSchema } from "../../../../../../schemas/marketplace-v3/offer"; -import { - marketplaceV3ContractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../../../utils/chain"; - -// INPUT -const requestSchema = marketplaceV3ContractParamSchema; -const requestBodySchema = Type.Object({ - ...OfferV3InputSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - assetContractAddress: "0x19411143085F1ec7D21a7cc07000CBA5188C5e8e", - tokenId: "0", - quantity: "1", - endTimestamp: 1686610889058, - currencyContractAddress: "0x...", - totalPrice: "0.00000001", - }, -]; - -// LOGIC -export async function offersMakeOffer(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/marketplace/:chain/:contractAddress/offers/make-offer", - schema: { - summary: "Make offer", - description: "Make an offer on a token. A valid listing is not required.", - tags: ["Marketplace-Offers"], - operationId: "makeMarketplaceOffer", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { - assetContractAddress, - tokenId, - totalPrice, - currencyContractAddress, - endTimestamp, - quantity, - txOverrides, - } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.offers.makeOffer.prepare({ - assetContractAddress, - tokenId, - totalPrice, - currencyContractAddress, - endTimestamp, - quantity, - }); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "marketplace-v3-offers", - idempotencyKey, - txOverrides, - }); - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/metadata/abi.ts b/src/server/routes/contract/metadata/abi.ts deleted file mode 100644 index 25407cf2b..000000000 --- a/src/server/routes/contract/metadata/abi.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../shared/utils/cache/get-contract"; -import { abiSchema } from "../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(abiSchema), -}); - -responseSchema.example = { - result: [ - { - type: "function", - name: "transferFrom", - inputs: [ - { - type: "address", - name: "from", - }, - { - type: "address", - name: "to", - }, - { - type: "uint256", - name: "tokenId", - }, - ], - }, - { - type: "event", - name: "Transfer", - inputs: [ - { - type: "address", - name: "from", - }, - { - type: "address", - name: "to", - }, - { - type: "uint256", - name: "tokenId", - }, - ], - }, - ], -}; - -export async function getABI(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/metadata/abi", - schema: { - summary: "Get ABI", - description: "Get the ABI of a contract.", - tags: ["Contract-Metadata"], - operationId: "getAbi", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = contract.abi; - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/metadata/events.ts b/src/server/routes/contract/metadata/events.ts deleted file mode 100644 index 2292be868..000000000 --- a/src/server/routes/contract/metadata/events.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../shared/utils/cache/get-contract"; -import { abiEventSchema } from "../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(abiEventSchema), -}); - -responseSchema.example = { - result: [ - { - name: "Approval", - inputs: [ - { - type: "address", - name: "owner", - }, - { - type: "address", - name: "approved", - }, - { - type: "uint256", - name: "tokenId", - }, - ], - outputs: [], - }, - { - name: "ApprovalForAll", - inputs: [ - { - type: "address", - name: "owner", - }, - { - type: "address", - name: "operator", - }, - { - type: "bool", - name: "approved", - }, - ], - outputs: [], - }, - ], -}; - -export async function extractEvents(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/metadata/events", - schema: { - summary: "Get events", - description: "Get details of all events implemented by a contract.", - tags: ["Contract-Metadata"], - operationId: "getContractEvents", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = await contract.publishedMetadata.extractEvents(); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/metadata/extensions.ts b/src/server/routes/contract/metadata/extensions.ts deleted file mode 100644 index 99da1ebc4..000000000 --- a/src/server/routes/contract/metadata/extensions.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import { getAllDetectedExtensionNames } from "@thirdweb-dev/sdk"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(Type.String(), { - description: "Array of detected extension names", - }), -}); - -responseSchema.example = { - result: [ - "ERC721", - "ERC721Burnable", - "ERC721Supply", - "ERC721LazyMintable", - "ERC721Revealable", - "ERC721ClaimPhasesV2", - "Royalty", - "PlatformFee", - "PrimarySale", - "Permissions", - "PermissionsEnumerable", - "ContractMetadata", - "Ownable", - "Gasless", - ], -}; - -export async function getContractExtensions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/metadata/extensions", - schema: { - summary: "Get extensions", - description: "Get all detected extensions for a contract.", - tags: ["Contract-Metadata"], - operationId: "getExtensions", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = getAllDetectedExtensionNames(contract.abi); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/metadata/functions.ts b/src/server/routes/contract/metadata/functions.ts deleted file mode 100644 index 073d10d90..000000000 --- a/src/server/routes/contract/metadata/functions.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../shared/utils/cache/get-contract"; -import { abiFunctionSchema } from "../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(abiFunctionSchema), -}); - -responseSchema.example = { - result: [ - { - name: "balanceOf", - inputs: [ - { - type: "address", - name: "owner", - }, - ], - outputs: [ - { - type: "uint256", - name: "", - }, - ], - comment: "See {IERC721-balanceOf}.", - signature: - 'contract.call("balanceOf", owner: string): Promise', - stateMutability: "view", - }, - { - name: "burn", - inputs: [ - { - type: "uint256", - name: "tokenId", - }, - ], - outputs: [], - comment: "Burns `tokenId`. See {ERC721-_burn}.", - signature: - 'contract.call("burn", tokenId: BigNumberish): Promise', - stateMutability: "nonpayable", - }, - ], -}; - -export async function extractFunctions(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/metadata/functions", - schema: { - summary: "Get functions", - description: "Get details of all functions implemented by the contract.", - tags: ["Contract-Metadata"], - operationId: "getFunctions", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = await contract.publishedMetadata.extractFunctions(); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/read/read-batch.ts b/src/server/routes/contract/read/read-batch.ts deleted file mode 100644 index 0a026bacd..000000000 --- a/src/server/routes/contract/read/read-batch.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import SuperJSON from "superjson"; -import { - encode, - getContract, - prepareContractCall, - readContract, - resolveMethod, -} from "thirdweb"; -import { prepareMethod } from "thirdweb/contract"; -import { decodeAbiParameters } from "viem/utils"; -import type { AbiFunction } from "viem"; -import { createCustomError } from "../../../middleware/error"; -import { getChainIdFromChain } from "../../../utils/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { getChain } from "../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../shared/utils/sdk"; -import { prettifyError } from "../../../../shared/utils/error"; - -const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11"; - -const MULTICALL3_AGGREGATE_ABI = - "function aggregate3((address target, bool allowFailure, bytes callData)[] calls) external payable returns ((bool success, bytes returnData)[])"; - -const readCallRequestItemSchema = Type.Object({ - contractAddress: Type.String(), - functionName: Type.String(), - functionAbi: Type.Optional(Type.String()), - args: Type.Optional(Type.Array(Type.Any())), -}); - -const readMulticallRequestSchema = Type.Object({ - calls: Type.Array(readCallRequestItemSchema), - multicallAddress: Type.Optional( - Type.String({ - description: `Address of the multicall contract to use. If omitted, multicall3 contract will be used (${MULTICALL3_ADDRESS}).`, - }), - ), -}); - -const responseSchema = Type.Object({ - results: Type.Array( - Type.Object({ - success: Type.Boolean(), - result: Type.Any(), - }), - ), -}); - -const paramsSchema = Type.Object({ - chain: Type.String(), -}); - -type RouteGeneric = { - Params: { chain: string }; - Body: Static; - Reply: Static; -}; - -export async function readBatchRoute(fastify: FastifyInstance) { - fastify.route({ - method: "POST", - url: "/contract/:chain/read-batch", - schema: { - summary: "Batch read from multiple contracts", - description: - "Execute multiple contract read operations in a single call using Multicall", - tags: ["Contract"], - operationId: "readBatch", - params: paramsSchema, - body: readMulticallRequestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain: chainSlug } = request.params; - const { calls, multicallAddress = MULTICALL3_ADDRESS } = request.body; - - const chainId = await getChainIdFromChain(chainSlug); - const chain = await getChain(chainId); - - try { - // Encode each read call - const encodedCalls = await Promise.all( - calls.map(async (call) => { - const contract = getContract({ - client: thirdwebClient, - chain, - address: call.contractAddress, - }); - - const method = - (call.functionAbi as unknown as AbiFunction) ?? - (await resolveMethod(call.functionName)(contract)); - - const transaction = prepareContractCall({ - contract, - method, - params: call.args || [], - }); - - const calldata = await encode(transaction); - if (!calldata) { - throw new Error("Failed to encode call data"); - } - - return { - target: call.contractAddress, - abiFunction: method, - allowFailure: true, - callData: calldata, - }; - }), - ); - - // Get Multicall3 contract - const multicall = await getContract({ - chain, - address: multicallAddress, - client: thirdwebClient, - }); - - // Execute batch read - const results = await readContract({ - contract: multicall, - method: MULTICALL3_AGGREGATE_ABI, - params: [encodedCalls], - }); - - // Process results - const processedResults = results.map((result: unknown, i) => { - const { success, returnData } = result as { - success: boolean; - returnData: unknown; - }; - - const [_sig, _inputs, outputs] = prepareMethod( - encodedCalls[i].abiFunction, - ); - - const decoded = decodeAbiParameters( - outputs, - returnData as `0x${string}`, - ); - - return { - success, - result: success ? decoded : null, - }; - }); - - reply.status(StatusCodes.OK).send({ - results: SuperJSON.serialize(processedResults).json as Static< - typeof responseSchema - >["results"], - }); - } catch (e) { - throw createCustomError( - prettifyError(e), - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - }, - }); -} diff --git a/src/server/routes/contract/read/read.ts b/src/server/routes/contract/read/read.ts deleted file mode 100644 index c84610df8..000000000 --- a/src/server/routes/contract/read/read.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../shared/utils/cache/get-contract"; -import { prettifyError } from "../../../../shared/utils/error"; -import { createCustomError } from "../../../middleware/error"; -import { - readRequestQuerySchema, - type readSchema, -} from "../../../schemas/contract"; -import { - partialRouteSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; -import { bigNumberReplacer } from "../../../utils/convertor"; - -const responseSchema = Type.Object({ - result: Type.Any(), -}); - -export async function readContract(fastify: FastifyInstance) { - fastify.route({ - method: "GET", - url: "/contract/:chain/:contractAddress/read", - schema: { - summary: "Read from contract", - description: "Call a read function on a contract.", - tags: ["Contract"], - operationId: "read", - ...partialRouteSchema, - querystring: readRequestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { functionName, args } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - let parsedArgs: unknown[] | undefined; - - try { - const jsonStringArgs = `[${args}]`; - parsedArgs = JSON.parse(jsonStringArgs); - } catch { - // fallback to string split - } - - parsedArgs ??= args?.split(",").map((arg) => { - if (arg === "true") { - return true; - } - if (arg === "false") { - return false; - } - return arg; - }); - - let returnData: unknown; - try { - returnData = await contract.call(functionName, parsedArgs ?? []); - } catch (e) { - throw createCustomError( - prettifyError(e), - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - returnData = bigNumberReplacer(returnData); - - reply.status(StatusCodes.OK).send({ - // biome-ignore lint/suspicious/noExplicitAny: data from chain - result: returnData as any, - }); - }, - }); -} diff --git a/src/server/routes/contract/roles/read/get-all.ts b/src/server/routes/contract/roles/read/get-all.ts deleted file mode 100644 index adfeca05f..000000000 --- a/src/server/routes/contract/roles/read/get-all.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { rolesResponseSchema } from "../../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: rolesResponseSchema, -}); - -requestSchema.examples = [ - { - result: { - admin: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - transfer: [ - "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - "0x0000000000000000000000000000000000000000", - ], - minter: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - pauser: [], - lister: [], - asset: [], - unwrap: [], - factory: [], - signer: [], - }, - }, -]; - -export async function getAllRoles(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/roles/get-all", - schema: { - summary: "Get wallets for all roles", - description: "Get all wallets in each role for a contract.", - tags: ["Contract-Roles"], - operationId: "listContractRoles", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = (await contract.roles.getAll()) as Static< - typeof responseSchema - >["result"]; - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/roles/read/get.ts b/src/server/routes/contract/roles/read/get.ts deleted file mode 100644 index 983c5b698..000000000 --- a/src/server/routes/contract/roles/read/get.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -const requestSchema = contractParamSchema; -const querystringSchema = Type.Object({ - role: Type.String({ - description: "The role to list wallet members", - }), -}); - -// OUTPUT -const responseSchema = Type.Object({ - result: Type.Array(Type.String()), -}); - -responseSchema.examples = [ - { - result: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }, -]; - -export async function getRoles(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/roles/get", - schema: { - summary: "Get wallets for role", - description: "Get all wallets with a specific role for a contract.", - tags: ["Contract-Roles"], - operationId: "getContractRole", - params: requestSchema, - querystring: querystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { role } = request.query; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = await contract.roles.get(role); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/roles/write/grant.ts b/src/server/routes/contract/roles/write/grant.ts deleted file mode 100644 index 9735ffc8b..000000000 --- a/src/server/routes/contract/roles/write/grant.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - role: Type.String({ - description: "The role to grant", - }), - address: { - ...AddressSchema, - description: "The address to grant the role to", - }, - ...txOverridesWithValueSchema.properties, -}); - -// OUTPUT -const responseSchema = transactionWritesResponseSchema; - -export async function grantRole(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/roles/grant", - schema: { - summary: "Grant role", - description: "Grant a role to a specific wallet.", - tags: ["Contract-Roles"], - operationId: "grantContractRole", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { role, address, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.roles.grant.prepare(role, address); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "roles", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/roles/write/revoke.ts b/src/server/routes/contract/roles/write/revoke.ts deleted file mode 100644 index b9dd3fa47..000000000 --- a/src/server/routes/contract/roles/write/revoke.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { AddressSchema } from "../../../../schemas/address"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - role: Type.String({ - description: "The role to revoke", - }), - address: { - ...AddressSchema, - description: "The address to revoke the role from", - }, - ...txOverridesWithValueSchema.properties, -}); - -// OUTPUT -const responseSchema = transactionWritesResponseSchema; - -export async function revokeRole(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/roles/revoke", - schema: { - summary: "Revoke role", - description: "Revoke a role from a specific wallet.", - tags: ["Contract-Roles"], - operationId: "revokeContractRole", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { role, address, txOverrides } = request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.roles.revoke.prepare(role, address); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "roles", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/royalties/read/get-default-royalty-info.ts b/src/server/routes/contract/royalties/read/get-default-royalty-info.ts deleted file mode 100644 index 1bdcd69d8..000000000 --- a/src/server/routes/contract/royalties/read/get-default-royalty-info.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { royaltySchema } from "../../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -const requestSchema = contractParamSchema; - -// OUTPUT -const responseSchema = Type.Object({ - result: royaltySchema, -}); - -responseSchema.examples = [ - { - result: { - fee_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - seller_fee_basis_points: 100, - }, - }, -]; - -export async function getDefaultRoyaltyInfo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/royalties/get-default-royalty-info", - schema: { - summary: "Get royalty details", - description: - "Gets the royalty recipient and BPS (basis points) of the smart contract.", - tags: ["Contract-Royalties"], - operationId: "getDefaultRoyaltyInfo", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = await contract.royalties.getDefaultRoyaltyInfo(); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/royalties/read/get-token-royalty-info.ts b/src/server/routes/contract/royalties/read/get-token-royalty-info.ts deleted file mode 100644 index 33f23cae0..000000000 --- a/src/server/routes/contract/royalties/read/get-token-royalty-info.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { royaltySchema } from "../../../../schemas/contract"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -const requestSchema = Type.Object({ - tokenId: Type.String(), - ...contractParamSchema.properties, -}); -// OUTPUT -const responseSchema = Type.Object({ - result: royaltySchema, -}); - -responseSchema.examples = [ - { - result: { - fee_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - seller_fee_basis_points: 100, - }, - }, -]; - -export async function getTokenRoyaltyInfo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/royalties/get-token-royalty-info/:tokenId", - schema: { - summary: "Get token royalty details", - description: - "Gets the royalty recipient and BPS (basis points) of a particular token in the contract.", - tags: ["Contract-Royalties"], - operationId: "getTokenRoyaltyInfo", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress, tokenId } = request.params; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - }); - - const returnData = await contract.royalties.getTokenRoyaltyInfo(tokenId); - - reply.status(StatusCodes.OK).send({ - result: returnData, - }); - }, - }); -} diff --git a/src/server/routes/contract/royalties/write/set-default-royalty-info.ts b/src/server/routes/contract/royalties/write/set-default-royalty-info.ts deleted file mode 100644 index 44d80ca7c..000000000 --- a/src/server/routes/contract/royalties/write/set-default-royalty-info.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { royaltySchema } from "../../../../schemas/contract"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - ...royaltySchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - fee_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - seller_fee_basis_points: 100, - }, -]; - -// OUTPUT -const responseSchema = transactionWritesResponseSchema; - -export async function setDefaultRoyaltyInfo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/royalties/set-default-royalty-info", - schema: { - summary: "Set royalty details", - description: "Set the royalty recipient and fee for the smart contract.", - tags: ["Contract-Royalties"], - operationId: "setDefaultRoyaltyInfo", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { seller_fee_basis_points, fee_recipient, txOverrides } = - request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.royalties.setDefaultRoyaltyInfo.prepare({ - seller_fee_basis_points, - fee_recipient, - }); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "none", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/royalties/write/set-token-royalty-info.ts b/src/server/routes/contract/royalties/write/set-token-royalty-info.ts deleted file mode 100644 index df1d2b0a3..000000000 --- a/src/server/routes/contract/royalties/write/set-token-royalty-info.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { queueTx } from "../../../../../shared/db/transactions/queue-tx"; -import { getContract } from "../../../../../shared/utils/cache/get-contract"; -import { royaltySchema } from "../../../../schemas/contract"; -import { - contractParamSchema, - requestQuerystringSchema, - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../../utils/chain"; - -// INPUTS -const requestSchema = contractParamSchema; -const requestBodySchema = Type.Object({ - ...royaltySchema.properties, - token_id: Type.String({ - description: "The token ID to set the royalty info for.", - }), - ...txOverridesWithValueSchema.properties, -}); - -requestBodySchema.examples = [ - { - fee_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - seller_fee_basis_points: 100, - token_id: "0", - }, -]; - -// OUTPUT -const responseSchema = transactionWritesResponseSchema; - -export async function setTokenRoyaltyInfo(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/royalties/set-token-royalty-info", - schema: { - summary: "Set token royalty details", - description: - "Set the royalty recipient and fee for a particular token in the contract.", - tags: ["Contract-Royalties"], - operationId: "setTokenRoyaltyInfo", - headers: walletWithAAHeaderSchema, - params: requestSchema, - body: requestBodySchema, - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { seller_fee_basis_points, fee_recipient, token_id, txOverrides } = - request.body; - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContract({ - chainId, - contractAddress, - walletAddress, - accountAddress, - }); - const tx = await contract.royalties.setTokenRoyaltyInfo.prepare( - token_id, - { - seller_fee_basis_points, - fee_recipient, - }, - ); - - const queueId = await queueTx({ - tx, - chainId, - simulateTx, - extension: "none", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/subscriptions/add-contract-subscription.ts b/src/server/routes/contract/subscriptions/add-contract-subscription.ts deleted file mode 100644 index 57545eda0..000000000 --- a/src/server/routes/contract/subscriptions/add-contract-subscription.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContract } from "thirdweb"; -import { isContractDeployed } from "thirdweb/utils"; -import { upsertChainIndexer } from "../../../../shared/db/chain-indexers/upsert-chain-indexer"; -import { createContractSubscription } from "../../../../shared/db/contract-subscriptions/create-contract-subscription"; -import { getContractSubscriptionsUniqueChainIds } from "../../../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { insertWebhook } from "../../../../shared/db/webhooks/create-webhook"; -import { WebhooksEventTypes } from "../../../../shared/schemas/webhooks"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { getChain } from "../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../shared/utils/sdk"; -import { createCustomError } from "../../../middleware/error"; -import { AddressSchema } from "../../../schemas/address"; -import { chainIdOrSlugSchema } from "../../../schemas/chain"; -import { - contractSubscriptionSchema, - toContractSubscriptionSchema, -} from "../../../schemas/contract-subscription"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; -import { isValidWebhookUrl } from "../../../utils/validator"; - -const bodySchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: { - ...AddressSchema, - description: "The address for the contract.", - }, - webhookUrl: Type.Optional( - Type.String({ - description: "Webhook URL", - examples: ["https://example.com/webhook"], - }), - ), - processEventLogs: Type.Boolean({ - description: "If true, parse event logs for this contract.", - }), - filterEvents: Type.Optional( - Type.Array(Type.String(), { - description: - "A case-sensitive list of event names to filter event logs. Parses all event logs by default.", - examples: ["Transfer"], - }), - ), - processTransactionReceipts: Type.Boolean({ - description: "If true, parse transaction receipts for this contract.", - }), - filterFunctions: Type.Optional( - Type.Array(Type.String(), { - description: - "A case-sensitive list of function names to filter transaction receipts. Parses all transaction receipts by default.", - examples: ["mintTo"], - }), - ), -}); - -const responseSchema = Type.Object({ - result: contractSubscriptionSchema, -}); - -responseSchema.example = { - result: { - chain: 1, - contractAddress: "0x....", - status: "success", - }, -}; - -export async function addContractSubscription(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/contract-subscriptions/add", - schema: { - summary: "Add contract subscription", - description: - "Subscribe to event logs and transaction receipts for a contract.", - tags: ["Contract-Subscriptions"], - operationId: "addContractSubscription", - body: bodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { - chain, - contractAddress, - webhookUrl, - processEventLogs, - filterEvents = [], - processTransactionReceipts, - filterFunctions = [], - } = request.body; - - const chainId = await getChainIdFromChain(chain); - - // Must parse logs or receipts. - if (!processEventLogs && !processTransactionReceipts) { - throw createCustomError( - "Contract Subscriptions must parse event logs and/or receipts.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - // Assert a valid contract. - const contract = getContract({ - client: thirdwebClient, - chain: await getChain(chainId), - address: contractAddress, - }); - const isValid = await isContractDeployed(contract); - if (!isValid) { - throw createCustomError( - "Invalid contract.", - StatusCodes.BAD_REQUEST, - "INVALID_CONTRACT", - ); - } - - // If not currently indexed, upsert the latest block number. - const subscribedChainIds = await getContractSubscriptionsUniqueChainIds(); - if (!subscribedChainIds.includes(chainId)) { - try { - const sdk = await getSdk({ chainId }); - const provider = sdk.getProvider(); - const currentBlockNumber = await provider.getBlockNumber(); - await upsertChainIndexer({ chainId, currentBlockNumber }); - } catch (_error) { - // this is fine, must be already locked, so don't need to update current block as this will be recent - } - } - - // Create the webhook (if provided). - let webhookId: number | undefined; - if (webhookUrl) { - if (!isValidWebhookUrl(webhookUrl)) { - throw createCustomError( - "Invalid webhook URL. Make sure it starts with 'https://'.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const webhook = await insertWebhook({ - eventType: WebhooksEventTypes.CONTRACT_SUBSCRIPTION, - name: "(Auto-generated)", - url: webhookUrl, - }); - webhookId = webhook.id; - } - - // Create the contract subscription. - const contractSubscription = await createContractSubscription({ - chainId, - contractAddress: contractAddress.toLowerCase(), - webhookId, - processEventLogs, - filterEvents, - processTransactionReceipts, - filterFunctions, - }); - - reply.status(StatusCodes.OK).send({ - result: toContractSubscriptionSchema(contractSubscription), - }); - }, - }); -} diff --git a/src/server/routes/contract/subscriptions/get-contract-indexed-block-range.ts b/src/server/routes/contract/subscriptions/get-contract-indexed-block-range.ts deleted file mode 100644 index 770b89a5e..000000000 --- a/src/server/routes/contract/subscriptions/get-contract-indexed-block-range.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getContractEventLogsIndexedBlockRange } from "../../../../shared/db/contract-event-logs/get-contract-event-logs"; -import { createCustomError } from "../../../middleware/error"; -import { AddressSchema } from "../../../schemas/address"; -import { chainIdOrSlugSchema } from "../../../schemas/chain"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const responseSchema = Type.Object({ - result: Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: AddressSchema, - fromBlock: Type.Integer(), - toBlock: Type.Integer(), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - chain: "ethereum", - contractAddress: "0x....", - fromBlock: 100, - toBlock: 200, - status: "success", - }, -}; - -export async function getContractIndexedBlockRange(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/subscriptions/get-indexed-blocks", - schema: { - summary: "Get subscribed contract indexed block range", - description: "Gets the subscribed contract's indexed block range", - tags: ["Contract-Subscriptions"], - operationId: "getContractIndexedBlockRange", - params: contractParamSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const standardizedContractAddress = contractAddress.toLowerCase(); - - const chainId = await getChainIdFromChain(chain); - - const result = await getContractEventLogsIndexedBlockRange({ - chainId, - contractAddress: standardizedContractAddress, - }); - - if (!result.fromBlock || !result.toBlock) { - const error = createCustomError( - `No logs found for chainId: ${chainId}, contractAddress: ${standardizedContractAddress}`, - StatusCodes.NOT_FOUND, - "LOG_NOT_FOUND", - ); - throw error; - } - - reply.status(StatusCodes.OK).send({ - result: { - chain, - contractAddress: standardizedContractAddress, - fromBlock: result.fromBlock, - toBlock: result.toBlock, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/subscriptions/get-contract-subscriptions.ts b/src/server/routes/contract/subscriptions/get-contract-subscriptions.ts deleted file mode 100644 index 747aa5870..000000000 --- a/src/server/routes/contract/subscriptions/get-contract-subscriptions.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAllContractSubscriptions } from "../../../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { - contractSubscriptionSchema, - toContractSubscriptionSchema, -} from "../../../schemas/contract-subscription"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const responseSchema = Type.Object({ - result: Type.Array(contractSubscriptionSchema), -}); - -responseSchema.example = { - result: [ - { - chain: "ethereum", - contractAddress: "0x....", - webhook: { - url: "https://.../", - }, - }, - ], -}; - -export async function getContractSubscriptions(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/contract-subscriptions/get-all", - schema: { - summary: "Get contract subscriptions", - description: "Get all contract subscriptions.", - tags: ["Contract-Subscriptions"], - operationId: "getContractSubscriptions", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (_request, reply) => { - const contractSubscriptions = await getAllContractSubscriptions(); - - reply.status(StatusCodes.OK).send({ - result: contractSubscriptions.map(toContractSubscriptionSchema), - }); - }, - }); -} diff --git a/src/server/routes/contract/subscriptions/get-latest-block.ts b/src/server/routes/contract/subscriptions/get-latest-block.ts deleted file mode 100644 index 3bfb99024..000000000 --- a/src/server/routes/contract/subscriptions/get-latest-block.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getLastIndexedBlock } from "../../../../shared/db/chain-indexers/get-chain-indexer"; -import { chainRequestQuerystringSchema } from "../../../schemas/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const responseSchema = Type.Object({ - result: Type.Object({ - lastBlock: Type.Integer(), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - lastBlock: 100, - status: "success", - }, -}; - -export async function getLatestBlock(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/contract-subscriptions/last-block", - schema: { - summary: "Get last processed block", - description: "Get the last processed block for a chain.", - tags: ["Contract-Subscriptions"], - operationId: "getLatestBlock", - querystring: chainRequestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.query; - const chainId = await getChainIdFromChain(chain); - - const lastBlock = await getLastIndexedBlock({ chainId }); - - reply.status(StatusCodes.OK).send({ - result: { - lastBlock: lastBlock ?? 0, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/subscriptions/remove-contract-subscription.ts b/src/server/routes/contract/subscriptions/remove-contract-subscription.ts deleted file mode 100644 index ef1c4d06c..000000000 --- a/src/server/routes/contract/subscriptions/remove-contract-subscription.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { deleteContractSubscription } from "../../../../shared/db/contract-subscriptions/delete-contract-subscription"; -import { deleteWebhook } from "../../../../shared/db/webhooks/revoke-webhook"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; - -const bodySchema = Type.Object({ - contractSubscriptionId: Type.String({ - description: "The ID for an existing contract subscription.", - }), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - status: "success", - }, -}; - -export async function removeContractSubscription(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/contract-subscriptions/remove", - schema: { - summary: "Remove contract subscription", - description: "Remove an existing contract subscription", - tags: ["Contract-Subscriptions"], - operationId: "removeContractSubscription", - body: bodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { contractSubscriptionId } = request.body; - - const contractSubscription = await deleteContractSubscription( - contractSubscriptionId, - ); - if (contractSubscription.webhookId) { - await deleteWebhook(contractSubscription.webhookId); - } - - reply.status(StatusCodes.OK).send({ - result: { - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/transactions/get-transaction-receipts-by-timestamp.ts b/src/server/routes/contract/transactions/get-transaction-receipts-by-timestamp.ts deleted file mode 100644 index 2b6136353..000000000 --- a/src/server/routes/contract/transactions/get-transaction-receipts-by-timestamp.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getTransactionReceiptsByBlockTimestamp } from "../../../../shared/db/contract-transaction-receipts/get-contract-transaction-receipts"; -import { AddressSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { transactionReceiptSchema } from "../../../schemas/transaction-receipt"; - -const requestQuerySchema = Type.Object({ - contractAddresses: Type.Optional(Type.Array(AddressSchema)), - fromBlockTimestamp: Type.Integer({ minimum: 0 }), - toBlockTimestamp: Type.Optional(Type.Integer({ minimum: 0 })), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - receipts: Type.Array(transactionReceiptSchema), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - receipts: [ - { - chainId: 1, - blockNumber: 100, - contractAddress: "0x...", - transactionHash: "0x...", - blockHash: "0x...", - timestamp: 100, - - to: "0x...", - from: "0x...", - transactionIndex: 1, - - gasUsed: "1000", - effectiveGasPrice: "1000", - status: 1, - }, - ], - status: "success", - }, -}; - -export async function getContractTransactionReceiptsByTimestamp( - fastify: FastifyInstance, -) { - fastify.route<{ - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/transactions/get-receipts", - schema: { - summary: "Get subscribed contract transaction receipts", - description: "Get transaction receipts for a subscribed contract", - tags: ["Contract-Transactions"], - operationId: "getContractTransactionReceiptsByTimestamp", - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { contractAddresses, fromBlockTimestamp, toBlockTimestamp } = - request.query; - - const standardizedContractAddresses = contractAddresses?.map((val) => - val.toLowerCase(), - ); - - const resultTransactionReceipts = - await getTransactionReceiptsByBlockTimestamp({ - fromBlockTimestamp, - toBlockTimestamp, - contractAddresses: standardizedContractAddresses, - }); - - const transactionReceipts = resultTransactionReceipts.map((txRcpt) => { - return { - chainId: Number.parseInt(txRcpt.chainId), - blockNumber: txRcpt.blockNumber, - contractAddress: txRcpt.contractAddress, - transactionHash: txRcpt.transactionHash, - blockHash: txRcpt.blockHash, - timestamp: txRcpt.timestamp.getTime(), - data: txRcpt.data, - value: txRcpt.value, - to: txRcpt.to, - from: txRcpt.from, - transactionIndex: txRcpt.transactionIndex, - - gasUsed: txRcpt.gasUsed, - effectiveGasPrice: txRcpt.effectiveGasPrice, - status: txRcpt.status, - }; - }); - - reply.status(StatusCodes.OK).send({ - result: { - receipts: transactionReceipts, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/transactions/get-transaction-receipts.ts b/src/server/routes/contract/transactions/get-transaction-receipts.ts deleted file mode 100644 index 4dcc02616..000000000 --- a/src/server/routes/contract/transactions/get-transaction-receipts.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { isContractSubscribed } from "../../../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { getContractTransactionReceiptsByBlock } from "../../../../shared/db/contract-transaction-receipts/get-contract-transaction-receipts"; -import { createCustomError } from "../../../middleware/error"; -import { - contractParamSchema, - standardResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { transactionReceiptSchema } from "../../../schemas/transaction-receipt"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestQuerySchema = Type.Object({ - fromBlock: Type.Integer({ minimum: 0 }), - toBlock: Type.Optional(Type.Integer({ minimum: 0 })), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - receipts: Type.Array(transactionReceiptSchema), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - receipts: [ - { - chainId: 1, - blockNumber: 100, - contractAddress: "0x...", - transactionHash: "0x...", - blockHash: "0x...", - timestamp: 100, - - to: "0x...", - from: "0x...", - transactionIndex: 1, - - gasUsed: "1000", - effectiveGasPrice: "1000", - status: 1, - }, - ], - status: "success", - }, -}; - -// TODO: throw this into config -const MAX_ALLOWED_QUERY_BLOCKS = 100; - -export async function getContractTransactionReceipts(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/:chain/:contractAddress/transactions/get-receipts", - schema: { - summary: "Get subscribed contract transaction receipts", - description: "Get event logs for a subscribed contract", - tags: ["Contract-Transactions"], - operationId: "getContractTransactionReceipts", - params: contractParamSchema, - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { fromBlock, toBlock } = request.query; - - if (toBlock && toBlock < fromBlock) { - throw createCustomError( - "toBlock cannot be less than fromBlock", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - if (toBlock && toBlock - fromBlock > MAX_ALLOWED_QUERY_BLOCKS) { - throw createCustomError( - `cannot query more than ${MAX_ALLOWED_QUERY_BLOCKS}`, - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const standardizedContractAddress = contractAddress.toLowerCase(); - - const chainId = await getChainIdFromChain(chain); - - // check if subscribed, if not tell user to subscribe - const isSubscribed = await isContractSubscribed({ - chainId, - contractAddress: standardizedContractAddress, - }); - - if (!isSubscribed) { - const subcriptionUrl = `/contract/${chain}/${contractAddress}/subscribe`; - throw createCustomError( - `Contract is not subscribed to! To subscribe, please use ${subcriptionUrl}`, - StatusCodes.NOT_FOUND, - "NOT_FOUND", - ); - } - - const resultTransactionReceipts = - await getContractTransactionReceiptsByBlock({ - chainId, - contractAddress: standardizedContractAddress, - fromBlock, - toBlock, - }); - - const transactionReceipts = resultTransactionReceipts.map((txRcpt) => { - return { - chainId: Number.parseInt(txRcpt.chainId), - blockNumber: txRcpt.blockNumber, - contractAddress: txRcpt.contractAddress, - transactionHash: txRcpt.transactionHash, - blockHash: txRcpt.blockHash, - timestamp: txRcpt.timestamp.getTime(), - data: txRcpt.data, - value: txRcpt.value, - to: txRcpt.to, - from: txRcpt.from, - transactionIndex: txRcpt.transactionIndex, - - gasUsed: txRcpt.gasUsed, - effectiveGasPrice: txRcpt.effectiveGasPrice, - status: txRcpt.status, - }; - }); - - reply.status(StatusCodes.OK).send({ - result: { - receipts: transactionReceipts, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/transactions/paginate-transaction-receipts.ts b/src/server/routes/contract/transactions/paginate-transaction-receipts.ts deleted file mode 100644 index 162ef3260..000000000 --- a/src/server/routes/contract/transactions/paginate-transaction-receipts.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getConfiguration } from "../../../../shared/db/configuration/get-configuration"; -import { getTransactionReceiptsByCursor } from "../../../../shared/db/contract-transaction-receipts/get-contract-transaction-receipts"; -import { AddressSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { - toTransactionReceiptSchema, - transactionReceiptSchema, -} from "../../../schemas/transaction-receipt"; - -/* Consider moving all cursor logic inside db file */ - -const requestQuerySchema = Type.Object({ - cursor: Type.Optional(Type.String()), - pageSize: Type.Optional(Type.Integer({ minimum: 1 })), - contractAddresses: Type.Optional(Type.Array(AddressSchema)), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - cursor: Type.Optional(Type.String()), - receipts: Type.Array(transactionReceiptSchema), - status: Type.String(), - }), -}); - -responseSchema.example = { - result: { - cursor: "abcd-xyz", - receipts: [ - { - chainId: 1, - blockNumber: 100, - contractAddress: "0x...", - transactionHash: "0x...", - blockHash: "0x...", - timestamp: 100, - - to: "0x...", - from: "0x...", - transactionIndex: 1, - - gasUsed: "1000", - effectiveGasPrice: "1000", - status: 1, - }, - ], - status: "success", - }, -}; - -export async function pageTransactionReceipts(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - Querystring: Static; - }>({ - method: "GET", - url: "/contract/transactions/paginate-receipts", - schema: { - summary: - "Get contract paginated transaction receipts for subscribed contract", - description: - "Get contract paginated transaction receipts for subscribed contract", - tags: ["Contract-Transactions"], - operationId: "pageTransactionReceipts", - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - hide: true, - }, - handler: async (request, reply) => { - const { cursor, pageSize, contractAddresses } = request.query; - - const standardizedContractAddresses = contractAddresses?.map((val) => - val.toLowerCase(), - ); - - // add lag behind to account for clock skew, concurrent writes, etc - const config = await getConfiguration(); - const maxCreatedAt = new Date( - Date.now() - config.cursorDelaySeconds * 1000, - ); - - const { cursor: newCursor, transactionReceipts } = - await getTransactionReceiptsByCursor({ - cursor, - limit: pageSize, - contractAddresses: standardizedContractAddresses, - maxCreatedAt, - }); - - reply.status(StatusCodes.OK).send({ - result: { - cursor: newCursor, - receipts: transactionReceipts.map(toTransactionReceiptSchema), - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/contract/write/write.ts b/src/server/routes/contract/write/write.ts deleted file mode 100644 index 8b9d6abc3..000000000 --- a/src/server/routes/contract/write/write.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { prepareContractCall, resolveMethod } from "thirdweb"; -import { parseAbiParams, type AbiFunction } from "thirdweb/utils"; -import { getContractV5 } from "../../../../shared/utils/cache/get-contractv5"; -import { prettifyError } from "../../../../shared/utils/error"; -import { queueTransaction } from "../../../../shared/utils/transaction/queue-transation"; -import { createCustomError } from "../../../middleware/error"; -import { abiArraySchema } from "../../../schemas/contract"; -import { - contractParamSchema, - requestQuerystringSchema, - transactionWritesResponseSchema, -} from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { - maybeAddress, - requiredAddress, - walletWithAAHeaderSchema, -} from "../../../schemas/wallet"; -import { sanitizeAbi, sanitizeFunctionName } from "../../../utils/abi"; -import { getChainIdFromChain } from "../../../utils/chain"; -import { parseTransactionOverrides } from "../../../utils/transaction-overrides"; - -// INPUT -const writeRequestBodySchema = Type.Object({ - functionName: Type.String({ - description: `The function to call on the contract. It is highly recommended to provide a full function signature, such as "function mintTo(address to, uint256 amount)", to avoid ambiguity and to skip ABI resolution.`, - examples: ["function mintTo(address to, uint256 amount)"], - }), - args: Type.Array(Type.Any(), { - description: - "An array of arguments to provide the function. Supports: numbers, strings, arrays, objects. Do not provide: BigNumber, bigint, Date objects", - examples: [ - [ - 1730380951, - "0x09530565aC1Ce08C3621f5B24Fca6d9a76574620", - ["a", "b", "c"], - ], - ], - }), - ...txOverridesWithValueSchema.properties, - abi: Type.Optional(abiArraySchema), -}); - -// LOGIC -export async function writeToContract(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Params: Static; - Reply: Static; - Querystring: Static; - }>({ - method: "POST", - url: "/contract/:chain/:contractAddress/write", - schema: { - summary: "Write to contract", - description: "Call a write function on a contract.", - tags: ["Contract"], - operationId: "write", - params: contractParamSchema, - headers: walletWithAAHeaderSchema, - querystring: requestQuerystringSchema, - body: writeRequestBodySchema, - response: { - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractAddress } = request.params; - const { simulateTx } = request.query; - const { functionName, args, txOverrides, abi } = request.body; - const { - "x-backend-wallet-address": fromAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - "x-account-factory-address": accountFactoryAddress, - "x-account-salt": accountSalt, - "x-transaction-mode": transactionMode, - } = request.headers as Static; - - const chainId = await getChainIdFromChain(chain); - const contract = await getContractV5({ - chainId, - contractAddress, - abi: sanitizeAbi(abi), - }); - - // 3 possible ways to get function from abi: - // 1. functionName passed as solidity signature - // 2. functionName passed as function name + passed in ABI - // 3. functionName passed as function name + inferred ABI (fetched at encode time) - // this is all handled inside the `resolveMethod` function - let method: AbiFunction; - let params: Array; - try { - const functionNameOrSignature = sanitizeFunctionName(functionName); - method = await resolveMethod(functionNameOrSignature)(contract); - params = parseAbiParams( - method.inputs.map((i) => i.type), - args, - ); - } catch (e) { - throw createCustomError( - prettifyError(e), - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const transaction = prepareContractCall({ - contract, - method, - params, - ...parseTransactionOverrides(txOverrides), - }); - - const queueId = await queueTransaction({ - functionName, - transaction, - fromAddress: requiredAddress(fromAddress, "x-backend-wallet-address"), - toAddress: maybeAddress(contractAddress, "to"), - accountAddress: maybeAddress(accountAddress, "x-account-address"), - accountFactoryAddress: maybeAddress( - accountFactoryAddress, - "x-account-factory-address", - ), - accountSalt, - txOverrides, - idempotencyKey, - transactionMode, - shouldSimulate: simulateTx, - }); - - reply.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/contract-types.ts b/src/server/routes/deploy/contract-types.ts deleted file mode 100644 index b9f671bf9..000000000 --- a/src/server/routes/deploy/contract-types.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import { PREBUILT_CONTRACTS_MAP } from "@thirdweb-dev/sdk"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -// OUTPUT -export const responseBodySchema = Type.Object({ - result: Type.Array(Type.String()), -}); - -export async function contractTypes(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/deploy/contract-types", - schema: { - summary: "Get contract types", - description: "Get all prebuilt contract types.", - tags: ["Deploy"], - operationId: "contractTypes", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_request, reply) => { - reply.status(StatusCodes.OK).send({ - result: Object.keys(PREBUILT_CONTRACTS_MAP), - }); - }, - }); -} diff --git a/src/server/routes/deploy/index.ts b/src/server/routes/deploy/index.ts deleted file mode 100644 index 641d894db..000000000 --- a/src/server/routes/deploy/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { deployPrebuiltEdition } from "./prebuilts/edition"; -import { deployPrebuiltEditionDrop } from "./prebuilts/edition-drop"; -import { deployPrebuiltMarketplaceV3 } from "./prebuilts/marketplace-v3"; -import { deployPrebuiltMultiwrap } from "./prebuilts/multiwrap"; -import { deployPrebuiltNFTCollection } from "./prebuilts/nft-collection"; -import { deployPrebuiltNFTDrop } from "./prebuilts/nft-drop"; -import { deployPrebuiltPack } from "./prebuilts/pack"; -import { deployPrebuiltSignatureDrop } from "./prebuilts/signature-drop"; -import { deployPrebuiltSplit } from "./prebuilts/split"; -import { deployPrebuiltToken } from "./prebuilts/token"; -import { deployPrebuiltTokenDrop } from "./prebuilts/token-drop"; -import { deployPrebuiltVote } from "./prebuilts/vote"; -import { deployPrebuilt } from "./prebuilt"; -import { deployPublished } from "./published"; -import { contractTypes } from "./contract-types"; - -export const prebuiltsRoutes = async (fastify: FastifyInstance) => { - await fastify.register(deployPrebuiltEdition); - await fastify.register(deployPrebuiltEditionDrop); - await fastify.register(deployPrebuiltMarketplaceV3); - await fastify.register(deployPrebuiltMultiwrap); - await fastify.register(deployPrebuiltNFTCollection); - await fastify.register(deployPrebuiltNFTDrop); - await fastify.register(deployPrebuiltPack); - await fastify.register(deployPrebuiltSignatureDrop); - await fastify.register(deployPrebuiltSplit); - await fastify.register(deployPrebuiltToken); - await fastify.register(deployPrebuiltTokenDrop); - await fastify.register(deployPrebuiltVote); - - await fastify.register(deployPrebuilt); - await fastify.register(deployPublished); - await fastify.register(contractTypes); -}; diff --git a/src/server/routes/deploy/prebuilt.ts b/src/server/routes/deploy/prebuilt.ts deleted file mode 100644 index 883768b6d..000000000 --- a/src/server/routes/deploy/prebuilt.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../shared/utils/cache/get-sdk"; -import { AddressSchema } from "../../schemas/address"; -import { contractDeployBasicSchema } from "../../schemas/contract"; -import { - prebuiltDeployParamSchema, - standardResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployParamSchema; -const requestBodySchema = Type.Object({ - // TODO need to type this - contractMetadata: Type.Any({ - description: "Arguments for the deployment.", - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Contract", - description: "Contract deployed from thirdweb Engine", - primary_sale_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - seller_fee_basis_points: 500, - fee_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - platform_fee_basis_points: 10, - platform_fee_recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - }, - }, -]; - -// OUTPUT -const responseSchema = Type.Object({ - queueId: Type.Optional(Type.String()), - deployedAddress: Type.Optional(AddressSchema), -}); - -export async function deployPrebuilt(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/:contractType", - schema: { - description: "Deploy prebuilt contract", - tags: ["Deploy"], - operationId: "deployPrebuilt", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - hide: true, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, contractType } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - contractType, - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - deployedAddress, - queueId, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/edition-drop.ts b/src/server/routes/deploy/prebuilts/edition-drop.ts deleted file mode 100644 index cd20d61e7..000000000 --- a/src/server/routes/deploy/prebuilts/edition-drop.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - merkleSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...merkleSchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Edition Drop", - symbol: "EDD", - primary_sale_recipient: "", - }, - }, -]; -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltEditionDrop(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/edition-drop", - schema: { - summary: "Deploy Edition Drop", - description: "Deploy an Edition Drop contract.", - tags: ["Deploy"], - operationId: "deployEditionDrop", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "edition-drop", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "edition-drop", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/edition.ts b/src/server/routes/deploy/prebuilts/edition.ts deleted file mode 100644 index c81807151..000000000 --- a/src/server/routes/deploy/prebuilts/edition.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts/index"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body - -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Edition", - symbol: "ED", - primary_sale_recipient: "", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltEdition(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/edition", - schema: { - summary: "Deploy Edition", - description: "Deploy an Edition contract.", - tags: ["Deploy"], - operationId: "deployEdition", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "edition", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "edition", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/marketplace-v3.ts b/src/server/routes/deploy/prebuilts/marketplace-v3.ts deleted file mode 100644 index c01e93121..000000000 --- a/src/server/routes/deploy/prebuilts/marketplace-v3.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Marketplace", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltMarketplaceV3(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/marketplace-v3", - schema: { - summary: "Deploy Marketplace", - description: "Deploy a Marketplace contract.", - tags: ["Deploy"], - operationId: "deployMarketplaceV3", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "marketplace-v3", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "marketplace-v3", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/multiwrap.ts b/src/server/routes/deploy/prebuilts/multiwrap.ts deleted file mode 100644 index 42f295d90..000000000 --- a/src/server/routes/deploy/prebuilts/multiwrap.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...commonSymbolSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Multiwrap", - symbol: "Mw", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltMultiwrap(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/multiwrap", - schema: { - summary: "Deploy Multiwrap", - description: "Deploy a Multiwrap contract.", - tags: ["Deploy"], - operationId: "deployMultiwrap", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "multiwrap", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "multiwrap", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/nft-collection.ts b/src/server/routes/deploy/prebuilts/nft-collection.ts deleted file mode 100644 index 43d5c330a..000000000 --- a/src/server/routes/deploy/prebuilts/nft-collection.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My NFT Collection", - symbol: "NFT", - }, - }, -]; -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltNFTCollection(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/nft-collection", - schema: { - summary: "Deploy NFT Collection", - description: "Deploy an NFT Collection contract.", - tags: ["Deploy"], - operationId: "deployNFTCollection", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "nft-collection", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "nft-collection", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/nft-drop.ts b/src/server/routes/deploy/prebuilts/nft-drop.ts deleted file mode 100644 index 2c33ddff1..000000000 --- a/src/server/routes/deploy/prebuilts/nft-drop.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - merkleSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...merkleSchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My NFT Drop", - symbol: "NFTD", - primary_sale_recipient: "", - }, - }, -]; -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltNFTDrop(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/nft-drop", - schema: { - summary: "Deploy NFT Drop", - description: "Deploy an NFT Drop contract.", - tags: ["Deploy"], - operationId: "deployNFTDrop", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "nft-drop", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "nft-drop", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/pack.ts b/src/server/routes/deploy/prebuilts/pack.ts deleted file mode 100644 index 009ee543b..000000000 --- a/src/server/routes/deploy/prebuilts/pack.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Pack", - symbol: "PACK", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltPack(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/pack", - schema: { - summary: "Deploy Pack", - description: "Deploy a Pack contract.", - tags: ["Deploy"], - operationId: "deployPack", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "pack", - contractMetadata, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "pack", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/signature-drop.ts b/src/server/routes/deploy/prebuilts/signature-drop.ts deleted file mode 100644 index 3656ae887..000000000 --- a/src/server/routes/deploy/prebuilts/signature-drop.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonRoyaltySchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - merkleSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonRoyaltySchema.properties, - ...merkleSchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My NFT Drop", - symbol: "NFTD", - primary_sale_recipient: "", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltSignatureDrop(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/signature-drop", - schema: { - summary: "Deploy Signature Drop", - description: "Deploy a Signature Drop contract.", - tags: ["Deploy"], - operationId: "deploySignatureDrop", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "signature-drop", - contractMetadata, - version, - { saltForProxyDeploy, forceDirectDeploy, compilerOptions }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "signature-drop", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/split.ts b/src/server/routes/deploy/prebuilts/split.ts deleted file mode 100644 index 8d81f2c6a..000000000 --- a/src/server/routes/deploy/prebuilts/split.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, - splitRecipientInputSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - recipients: Type.Array(splitRecipientInputSchema), - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Split", - recipients: [ - { - recipient: "0x3EcDBF3B911d0e9052b64850693888b008e18373", - percent: 50, - }, - { - recipient: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - percent: 50, - }, - ], - }, - }, -]; -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltSplit(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/split", - schema: { - summary: "Deploy Split", - description: "Deploy a Split contract.", - tags: ["Deploy"], - operationId: "deploySplit", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "split", - contractMetadata, - version, - { saltForProxyDeploy, forceDirectDeploy, compilerOptions }, - ); - const deployedAddress = (await tx.simulate()) as Address; - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "split", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/token-drop.ts b/src/server/routes/deploy/prebuilts/token-drop.ts deleted file mode 100644 index 891ac65de..000000000 --- a/src/server/routes/deploy/prebuilts/token-drop.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - merkleSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...merkleSchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Signature Drop", - symbol: "SIGD", - primary_sale_recipient: "", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltTokenDrop(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/token-drop", - schema: { - summary: "Deploy Token Drop", - description: "Deploy a Token Drop contract.", - tags: ["Deploy"], - operationId: "deployTokenDrop", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "token-drop", - contractMetadata, - version, - { saltForProxyDeploy, forceDirectDeploy, compilerOptions }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "token-drop", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/token.ts b/src/server/routes/deploy/prebuilts/token.ts deleted file mode 100644 index f965aeef4..000000000 --- a/src/server/routes/deploy/prebuilts/token.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonPlatformFeeSchema, - commonPrimarySaleSchema, - commonSymbolSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...commonSymbolSchema.properties, - ...commonPlatformFeeSchema.properties, - ...commonPrimarySaleSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Token", - symbol: "TKN", - primary_sale_recipient: "", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltToken(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/token", - schema: { - summary: "Deploy Token", - description: "Deploy a Token contract.", - tags: ["Deploy"], - operationId: "deployToken", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "token", - contractMetadata, - version, - { saltForProxyDeploy, forceDirectDeploy, compilerOptions }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "token", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/prebuilts/vote.ts b/src/server/routes/deploy/prebuilts/vote.ts deleted file mode 100644 index 87f50daae..000000000 --- a/src/server/routes/deploy/prebuilts/vote.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import type { Address } from "thirdweb"; -import { queueTx } from "../../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../../schemas/contract"; -import { - commonContractSchema, - commonTrustedForwarderSchema, - prebuiltDeployContractParamSchema, - prebuiltDeployResponseSchema, - voteSettingsInputSchema, -} from "../../../schemas/prebuilts"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUTS -const requestSchema = prebuiltDeployContractParamSchema; -const requestBodySchema = Type.Object({ - contractMetadata: Type.Object({ - ...commonContractSchema.properties, - ...voteSettingsInputSchema.properties, - ...commonTrustedForwarderSchema.properties, - }), - ...contractDeployBasicSchema.properties, - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - contractMetadata: { - name: "My Vote", - }, - }, -]; - -// OUTPUT -const responseSchema = prebuiltDeployResponseSchema; - -export async function deployPrebuiltVote(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/prebuilts/vote", - schema: { - summary: "Deploy Vote", - description: "Deploy a Vote contract.", - tags: ["Deploy"], - operationId: "deployVote", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain } = request.params; - const { - contractMetadata, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployBuiltInContract.prepare( - "vote", - contractMetadata, - version, - { saltForProxyDeploy, forceDirectDeploy, compilerOptions }, - ); - const deployedAddress = (await tx.simulate()) as Address; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-prebuilt", - deployedContractAddress: deployedAddress, - deployedContractType: "vote", - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - result: { - deployedAddress, - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/deploy/published.ts b/src/server/routes/deploy/published.ts deleted file mode 100644 index a4bcc9274..000000000 --- a/src/server/routes/deploy/published.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { isAddress } from "thirdweb"; -import { queueTx } from "../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../shared/utils/cache/get-sdk"; -import { contractDeployBasicSchema } from "../../schemas/contract"; -import { - publishedDeployParamSchema, - standardResponseSchema, -} from "../../schemas/shared-api-schemas"; -import { txOverridesWithValueSchema } from "../../schemas/tx-overrides"; -import { walletWithAAHeaderSchema } from "../../schemas/wallet"; -import { getChainIdFromChain } from "../../utils/chain"; - -// INPUTS -const requestSchema = publishedDeployParamSchema; -const requestBodySchema = Type.Object({ - ...contractDeployBasicSchema.properties, - constructorParams: Type.Array(Type.Any(), { - description: "Constructor arguments for the deployment.", - }), - ...txOverridesWithValueSchema.properties, -}); - -// Example for the Request Body -requestBodySchema.examples = [ - { - constructorParams: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"], - }, -]; - -// OUTPUT -const responseSchema = Type.Object({ - queueId: Type.Optional(Type.String()), - deployedAddress: Type.Optional( - Type.String({ - description: "Not all contracts return a deployed address.", - }), - ), - message: Type.Optional(Type.String()), -}); - -export async function deployPublished(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/deploy/:chain/:publisher/:contractName", - schema: { - summary: "Deploy published contract", - description: "Deploy a published contract to the blockchain.", - tags: ["Deploy"], - operationId: "deployPublished", - params: requestSchema, - body: requestBodySchema, - headers: walletWithAAHeaderSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (request, reply) => { - const { chain, publisher, contractName } = request.params; - const { - constructorParams, - version, - txOverrides, - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - } = request.body; - const chainId = await getChainIdFromChain(chain); - const { - "x-backend-wallet-address": walletAddress, - "x-account-address": accountAddress, - "x-idempotency-key": idempotencyKey, - } = request.headers as Static; - - const sdk = await getSdk({ chainId, walletAddress, accountAddress }); - const tx = await sdk.deployer.deployPublishedContract.prepare( - publisher, - contractName, - constructorParams, - version, - { - saltForProxyDeploy, - forceDirectDeploy, - compilerOptions, - }, - ); - const _deployedAddress = await tx.simulate(); - const deployedAddress = isAddress(_deployedAddress) - ? _deployedAddress - : undefined; - - const queueId = await queueTx({ - tx, - chainId, - extension: "deploy-published", - deployedContractAddress: deployedAddress, - deployedContractType: contractName, - idempotencyKey, - txOverrides, - }); - - reply.status(StatusCodes.OK).send({ - deployedAddress, - queueId, - message: !deployedAddress - ? `To retrieve the deployed contract address, use the endpoint '/transaction/status/${queueId}' and check the value of the 'deployedContractAddress' field` - : undefined, - }); - }, - }); -} diff --git a/src/server/routes/health.ts b/src/server/routes/health.ts new file mode 100644 index 000000000..066426fc7 --- /dev/null +++ b/src/server/routes/health.ts @@ -0,0 +1,45 @@ +import { Hono } from "hono"; +import { isRedisReachable } from "../../lib/redis.js"; +import { env } from "../../lib/env.js"; +import { thirdwebClientId } from "../../lib/thirdweb-client.js"; +import { getConfigInDb } from "../../lib/config.js"; + +export const healthCheckRoute = new Hono(); + +healthCheckRoute.get("/", async (c) => { + const redis = await isRedisReachable(); + const auth = await isAuthValid(); + const db = await isDatabaseReachable(); + + const isHealthy = db && redis && auth; + + return c.json( + { + db, + redis, + auth, + engineVersion: env.ENGINE_VERSION, + engineTier: env.ENGINE_TIER ?? "SELF_HOSTED", + clientId: thirdwebClientId, + }, + isHealthy ? 200 : 503, + ); +}); + +async function isAuthValid() { + try { + const resp = await fetch("http://github.com/service/https://api.thirdweb.com/v2/keys/use", { + headers: { + "x-secret-key": env.THIRDWEB_API_SECRET_KEY, + }, + }); + return resp.ok; + } catch { + return false; + } +} + +async function isDatabaseReachable() { + const response = await getConfigInDb(); + return response.isOk(); +} diff --git a/src/server/routes/home.ts b/src/server/routes/home.ts deleted file mode 100644 index 212126800..000000000 --- a/src/server/routes/home.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; - -const responseBodySchema = Type.Object({ - message: Type.String(), -}); - -export async function home(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/", - schema: { - hide: true, - summary: "/", - description: "Instructions to manage your Engine", - tags: ["System"], - operationId: "home", - response: { - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_, res) => { - return res.status(StatusCodes.OK).send({ - message: - "Engine is set up successfully. Manage your Engine from https://thirdweb.com/dashboard/engine.", - }); - }, - }); -} diff --git a/src/server/routes/index.ts b/src/server/routes/index.ts deleted file mode 100644 index be174a78f..000000000 --- a/src/server/routes/index.ts +++ /dev/null @@ -1,286 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { getNonceDetailsRoute } from "./admin/nonces"; -import { getTransactionDetails } from "./admin/transaction"; -import { createAccessToken } from "./auth/access-tokens/create"; -import { getAllAccessTokens } from "./auth/access-tokens/get-all"; -import { revokeAccessToken } from "./auth/access-tokens/revoke"; -import { updateAccessToken } from "./auth/access-tokens/update"; -import { addKeypair } from "./auth/keypair/add"; -import { listPublicKeys } from "./auth/keypair/list"; -import { removePublicKey } from "./auth/keypair/remove"; -import { getAllPermissions } from "./auth/permissions/get-all"; -import { grantPermissions } from "./auth/permissions/grant"; -import { revokePermissions } from "./auth/permissions/revoke"; -import { cancelBackendWalletNoncesRoute } from "./backend-wallet/cancel-nonces"; -import { createBackendWallet } from "./backend-wallet/create"; -import { getAll } from "./backend-wallet/get-all"; -import { getBalance } from "./backend-wallet/get-balance"; -import { getBackendWalletNonce } from "./backend-wallet/get-nonce"; -import { getTransactionsForBackendWallet } from "./backend-wallet/get-transactions"; -import { getTransactionsForBackendWalletByNonce } from "./backend-wallet/get-transactions-by-nonce"; -import { importBackendWallet } from "./backend-wallet/import"; -import { removeBackendWallet } from "./backend-wallet/remove"; -import { resetBackendWalletNoncesRoute } from "./backend-wallet/reset-nonces"; -import { sendTransaction } from "./backend-wallet/send-transaction"; -import { sendTransactionBatch } from "./backend-wallet/send-transaction-batch"; -import { signMessageRoute } from "./backend-wallet/sign-message"; -import { signTransaction } from "./backend-wallet/sign-transaction"; -import { signTypedData } from "./backend-wallet/sign-typed-data"; -import { simulateTransaction } from "./backend-wallet/simulate-transaction"; -import { transfer } from "./backend-wallet/transfer"; -import { updateBackendWallet } from "./backend-wallet/update"; -import { withdraw } from "./backend-wallet/withdraw"; -import { getChainData } from "./chain/get"; -import { getAllChainData } from "./chain/get-all"; -import { getAuthConfiguration } from "./configuration/auth/get"; -import { updateAuthConfiguration } from "./configuration/auth/update"; -import { getBackendWalletBalanceConfiguration } from "./configuration/backend-wallet-balance/get"; -import { updateBackendWalletBalanceConfiguration } from "./configuration/backend-wallet-balance/update"; -import { getCacheConfiguration } from "./configuration/cache/get"; -import { updateCacheConfiguration } from "./configuration/cache/update"; -import { getChainsConfiguration } from "./configuration/chains/get"; -import { updateChainsConfiguration } from "./configuration/chains/update"; -import { getContractSubscriptionsConfiguration } from "./configuration/contract-subscriptions/get"; -import { updateContractSubscriptionsConfiguration } from "./configuration/contract-subscriptions/update"; -import { addUrlToCorsConfiguration } from "./configuration/cors/add"; -import { getCorsConfiguration } from "./configuration/cors/get"; -import { removeUrlToCorsConfiguration } from "./configuration/cors/remove"; -import { setUrlsToCorsConfiguration } from "./configuration/cors/set"; -import { getIpAllowlist } from "./configuration/ip/get"; -import { setIpAllowlist } from "./configuration/ip/set"; -import { getTransactionConfiguration } from "./configuration/transactions/get"; -import { updateTransactionConfiguration } from "./configuration/transactions/update"; -import { getWalletsConfiguration } from "./configuration/wallets/get"; -import { updateWalletsConfiguration } from "./configuration/wallets/update"; -import { getAllEvents } from "./contract/events/get-all-events"; -import { getContractEventLogs } from "./contract/events/get-contract-event-logs"; -import { getEventLogs } from "./contract/events/get-event-logs-by-timestamp"; -import { getEvents } from "./contract/events/get-events"; -import { pageEventLogs } from "./contract/events/paginate-event-logs"; -import { accountRoutes } from "./contract/extensions/account"; -import { accountFactoryRoutes } from "./contract/extensions/account-factory"; -import { erc1155Routes } from "./contract/extensions/erc1155"; -import { erc20Routes } from "./contract/extensions/erc20"; -import { erc721Routes } from "./contract/extensions/erc721"; -import { marketplaceV3Routes } from "./contract/extensions/marketplace-v3/index"; -import { getABI } from "./contract/metadata/abi"; -import { extractEvents } from "./contract/metadata/events"; -import { getContractExtensions } from "./contract/metadata/extensions"; -import { extractFunctions } from "./contract/metadata/functions"; -import { readContract } from "./contract/read/read"; -import { getRoles } from "./contract/roles/read/get"; -import { getAllRoles } from "./contract/roles/read/get-all"; -import { grantRole } from "./contract/roles/write/grant"; -import { revokeRole } from "./contract/roles/write/revoke"; -import { getDefaultRoyaltyInfo } from "./contract/royalties/read/get-default-royalty-info"; -import { getTokenRoyaltyInfo } from "./contract/royalties/read/get-token-royalty-info"; -import { setDefaultRoyaltyInfo } from "./contract/royalties/write/set-default-royalty-info"; -import { setTokenRoyaltyInfo } from "./contract/royalties/write/set-token-royalty-info"; -import { addContractSubscription } from "./contract/subscriptions/add-contract-subscription"; -import { getContractIndexedBlockRange } from "./contract/subscriptions/get-contract-indexed-block-range"; -import { getContractSubscriptions } from "./contract/subscriptions/get-contract-subscriptions"; -import { getLatestBlock } from "./contract/subscriptions/get-latest-block"; -import { removeContractSubscription } from "./contract/subscriptions/remove-contract-subscription"; -import { getContractTransactionReceipts } from "./contract/transactions/get-transaction-receipts"; -import { getContractTransactionReceiptsByTimestamp } from "./contract/transactions/get-transaction-receipts-by-timestamp"; -import { pageTransactionReceipts } from "./contract/transactions/paginate-transaction-receipts"; -import { writeToContract } from "./contract/write/write"; -import { prebuiltsRoutes } from "./deploy"; -import { home } from "./home"; -import { relayTransaction } from "./relayer"; -import { createRelayer } from "./relayer/create"; -import { getAllRelayers } from "./relayer/get-all"; -import { revokeRelayer } from "./relayer/revoke"; -import { updateRelayer } from "./relayer/update"; -import { healthCheck } from "./system/health"; -import { queueStatus } from "./system/queue"; -import { getTransactionLogs } from "./transaction/blockchain/get-logs"; -import { getTransactionReceipt } from "./transaction/blockchain/get-receipt"; -import { getUserOpReceipt } from "./transaction/blockchain/get-user-op-receipt"; -import { sendSignedTransaction } from "./transaction/blockchain/send-signed-tx"; -import { sendSignedUserOp } from "./transaction/blockchain/send-signed-user-op"; -import { cancelTransaction } from "./transaction/cancel"; -import { getAllTransactions } from "./transaction/get-all"; -import { getAllDeployedContracts } from "./transaction/get-all-deployed-contracts"; -import { retryTransaction } from "./transaction/retry"; -import { retryFailedTransactionRoute } from "./transaction/retry-failed"; -import { checkTxStatus } from "./transaction/status"; -import { syncRetryTransactionRoute } from "./transaction/sync-retry"; -import { createWebhookRoute } from "./webhooks/create"; -import { getWebhooksEventTypes } from "./webhooks/events"; -import { getAllWebhooksData } from "./webhooks/get-all"; -import { revokeWebhook } from "./webhooks/revoke"; -import { testWebhookRoute } from "./webhooks/test"; -import { readBatchRoute } from "./contract/read/read-batch"; -import { sendTransactionBatchAtomicRoute } from "./backend-wallet/send-transaction-batch-atomic"; -import { createWalletCredentialRoute } from "./wallet-credentials/create"; -import { getWalletCredentialRoute } from "./wallet-credentials/get"; -import { getAllWalletCredentialsRoute } from "./wallet-credentials/get-all"; -import { updateWalletCredentialRoute } from "./wallet-credentials/update"; - -export async function withRoutes(fastify: FastifyInstance) { - // Backend Wallets - await fastify.register(createBackendWallet); - await fastify.register(removeBackendWallet); - await fastify.register(importBackendWallet); - await fastify.register(updateBackendWallet); - await fastify.register(getBalance); - await fastify.register(getAll); - await fastify.register(transfer); - await fastify.register(withdraw); - await fastify.register(sendTransaction); - await fastify.register(sendTransactionBatch); - await fastify.register(sendTransactionBatchAtomicRoute); - await fastify.register(signTransaction); - await fastify.register(signMessageRoute); - await fastify.register(signTypedData); - await fastify.register(getTransactionsForBackendWallet); - await fastify.register(getTransactionsForBackendWalletByNonce); - await fastify.register(resetBackendWalletNoncesRoute); - await fastify.register(cancelBackendWalletNoncesRoute); - await fastify.register(getBackendWalletNonce); - await fastify.register(simulateTransaction); - - // Credentials - await fastify.register(createWalletCredentialRoute); - await fastify.register(getWalletCredentialRoute); - await fastify.register(getAllWalletCredentialsRoute); - await fastify.register(updateWalletCredentialRoute); - - // Configuration - await fastify.register(getWalletsConfiguration); - await fastify.register(updateWalletsConfiguration); - await fastify.register(getChainsConfiguration); - await fastify.register(updateChainsConfiguration); - await fastify.register(getTransactionConfiguration); - await fastify.register(updateTransactionConfiguration); - await fastify.register(getAuthConfiguration); - await fastify.register(updateAuthConfiguration); - await fastify.register(getBackendWalletBalanceConfiguration); - await fastify.register(updateBackendWalletBalanceConfiguration); - await fastify.register(getCorsConfiguration); - await fastify.register(addUrlToCorsConfiguration); - await fastify.register(removeUrlToCorsConfiguration); - await fastify.register(setUrlsToCorsConfiguration); - await fastify.register(getCacheConfiguration); - await fastify.register(updateCacheConfiguration); - await fastify.register(getContractSubscriptionsConfiguration); - await fastify.register(updateContractSubscriptionsConfiguration); - await fastify.register(getIpAllowlist); - await fastify.register(setIpAllowlist); - - // Webhooks - await fastify.register(getAllWebhooksData); - await fastify.register(createWebhookRoute); - await fastify.register(revokeWebhook); - await fastify.register(getWebhooksEventTypes); - await fastify.register(testWebhookRoute); - - // Permissions - await fastify.register(getAllPermissions); - await fastify.register(grantPermissions); - await fastify.register(revokePermissions); - - // Access Tokens - await fastify.register(getAllAccessTokens); - await fastify.register(createAccessToken); - await fastify.register(revokeAccessToken); - await fastify.register(updateAccessToken); - - // Keypairs - await fastify.register(listPublicKeys); - await fastify.register(addKeypair); - await fastify.register(removePublicKey); - - // Chains - await fastify.register(getChainData); - await fastify.register(getAllChainData); - - // Relayer - await fastify.register(getAllRelayers); - await fastify.register(createRelayer); - await fastify.register(revokeRelayer); - await fastify.register(updateRelayer); - await fastify.register(relayTransaction); - - // Generic - await fastify.register(readContract); - await fastify.register(readBatchRoute); - await fastify.register(writeToContract); - - // Contract Events - await fastify.register(getAllEvents); - await fastify.register(getEvents); - - // Contract Metadata - await fastify.register(getABI); - await fastify.register(extractEvents); - await fastify.register(getContractExtensions); - await fastify.register(extractFunctions); - - // Contract Roles - await fastify.register(getRoles); - await fastify.register(getAllRoles); - await fastify.register(grantRole); - await fastify.register(revokeRole); - - // Contract Royalties - await fastify.register(getDefaultRoyaltyInfo); - await fastify.register(getTokenRoyaltyInfo); - await fastify.register(setDefaultRoyaltyInfo); - await fastify.register(setTokenRoyaltyInfo); - - // Deploy - await fastify.register(prebuiltsRoutes); - - // Transactions - await fastify.register(getAllTransactions); - await fastify.register(checkTxStatus); - await fastify.register(getAllDeployedContracts); - await fastify.register(retryTransaction); - await fastify.register(syncRetryTransactionRoute); - await fastify.register(retryFailedTransactionRoute); - await fastify.register(cancelTransaction); - await fastify.register(sendSignedTransaction); - await fastify.register(sendSignedUserOp); - await fastify.register(getTransactionReceipt); - await fastify.register(getUserOpReceipt); - await fastify.register(getTransactionLogs); - - // Extensions - await fastify.register(accountFactoryRoutes); - await fastify.register(accountRoutes); - await fastify.register(erc20Routes); - await fastify.register(erc721Routes); - await fastify.register(erc1155Routes); - await fastify.register(marketplaceV3Routes); - - // System - // These should be hidden by default - await fastify.register(home); - await fastify.register(healthCheck); - await fastify.register(queueStatus); - - // Contract Subscriptions - await fastify.register(getContractSubscriptions); - await fastify.register(addContractSubscription); - await fastify.register(removeContractSubscription); - await fastify.register(getContractIndexedBlockRange); - await fastify.register(getLatestBlock); - - // Contract Transactions - // @deprecated - await fastify.register(getContractTransactionReceipts); - await fastify.register(getContractTransactionReceiptsByTimestamp); - await fastify.register(pageTransactionReceipts); - - // Contract Event Logs - // @deprecated - await fastify.register(getContractEventLogs); - await fastify.register(getEventLogs); - await fastify.register(pageEventLogs); - - // Admin - await fastify.register(getTransactionDetails); - await fastify.register(getNonceDetailsRoute); -} diff --git a/src/server/routes/queues.ts b/src/server/routes/queues.ts new file mode 100644 index 000000000..d86e5fb16 --- /dev/null +++ b/src/server/routes/queues.ts @@ -0,0 +1,58 @@ +import { serveStatic } from "hono/bun"; +import { createBullBoard } from "@bull-board/api"; +import { BullMQAdapter } from "@bull-board/api/bullMQAdapter"; +import { HonoAdapter } from "@bull-board/hono"; +import { externalBundlerConfirmQueue } from "../../executors/external-bundler/index.js"; +import { + externalBundlerConfirmQueue as externalBundlerConfirmQueueAsync, + externalBundlerSendQueue, +} from "../../executors/external-bundler-async/index.js"; +import { Hono } from "hono"; +import { basicAuth } from "hono/basic-auth"; +import { env } from "../../lib/env.js"; +import { testQueue } from "../../executors/test/index.js"; + +import "../../executors/test/worker.js"; + +const serverAdapter = new HonoAdapter(serveStatic); + +const queues = [ + externalBundlerConfirmQueue, + testQueue, + externalBundlerConfirmQueueAsync, + externalBundlerSendQueue, +]; +const bullBoardQueues = queues.map((queue) => new BullMQAdapter(queue)); + +export function setupQueuesUiRoutes(app: Hono, basePath: string) { + const realm = "Thirdweb Engine Admin"; + + createBullBoard({ + queues: bullBoardQueues, + serverAdapter, + }); + + serverAdapter.setBasePath(basePath); + + const bullmqRoutes = new Hono(); + + bullmqRoutes.use( + basicAuth({ + username: "admin", + password: env.THIRDWEB_API_SECRET_KEY, + invalidUserMessage: "Invalid username or password", + realm, + }), + ); + + bullmqRoutes.route("", serverAdapter.registerPlugin()); + + // we need a custom error handler because the default error has an invalid response (hono bug?) + // this causes the browser to keep retrying even if authentication fails, and the browser window freezes + bullmqRoutes.onError((_err, c) => { + c.header("WWW-Authenticate", `Basic realm="${realm}"`); + return c.json({ error: "Incorrect username or password" }, 401); + }); + + app.route(basePath, bullmqRoutes); +} diff --git a/src/server/routes/relayer/create.ts b/src/server/routes/relayer/create.ts deleted file mode 100644 index 975a93c12..000000000 --- a/src/server/routes/relayer/create.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { prisma } from "../../../shared/db/client"; -import { AddressSchema } from "../../schemas/address"; -import { chainIdOrSlugSchema } from "../../schemas/chain"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../utils/chain"; - -const requestBodySchema = Type.Object({ - name: Type.Optional(Type.String()), - chain: chainIdOrSlugSchema, - backendWalletAddress: { - ...AddressSchema, - description: - "The address of the backend wallet to use for relaying transactions.", - }, - allowedContracts: Type.Optional(Type.Array(AddressSchema)), - allowedForwarders: Type.Optional(Type.Array(AddressSchema)), -}); - -requestBodySchema.examples = [ - { - name: "My relayer", - chain: "mainnet", - backendWalletAddress: "0", - allowedContracts: ["0x1234...."], - allowedForwarders: ["0x1234..."], - }, -]; - -const responseBodySchema = Type.Object({ - result: Type.Object({ - relayerId: Type.String(), - }), -}); - -export async function createRelayer(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/relayer/create", - schema: { - summary: "Create a new meta-transaction relayer", - description: "Create a new meta-transaction relayer", - tags: ["Relayer"], - operationId: "createRelayer", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { - name, - chain, - backendWalletAddress, - allowedContracts, - allowedForwarders, - } = req.body; - - const chainId = (await getChainIdFromChain(chain)).toString(); - const relayer = await prisma.relayers.create({ - data: { - name, - chainId, - backendWalletAddress, - allowedContracts: allowedContracts - ? JSON.stringify( - allowedContracts.map((address) => address.toLowerCase()), - ) - : null, - allowedForwarders: allowedForwarders - ? JSON.stringify( - allowedForwarders.map((address) => address.toLowerCase()), - ) - : null, - }, - }); - - return res.status(StatusCodes.OK).send({ - result: { - relayerId: relayer.id, - }, - }); - }, - }); -} diff --git a/src/server/routes/relayer/get-all.ts b/src/server/routes/relayer/get-all.ts deleted file mode 100644 index 8311f3464..000000000 --- a/src/server/routes/relayer/get-all.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { prisma } from "../../../shared/db/client"; -import { AddressSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const responseBodySchema = Type.Object({ - result: Type.Array( - Type.Object({ - id: Type.String(), - name: Type.Union([Type.String(), Type.Null()]), - chainId: Type.String(), - backendWalletAddress: AddressSchema, - allowedContracts: Type.Union([Type.Array(Type.String()), Type.Null()]), - allowedForwarders: Type.Union([Type.Array(Type.String()), Type.Null()]), - }), - ), -}); - -export async function getAllRelayers(fastify: FastifyInstance) { - fastify.route({ - method: "GET", - url: "/relayer/get-all", - schema: { - summary: "Get all meta-transaction relayers", - description: "Get all meta-transaction relayers", - tags: ["Relayer"], - operationId: "listRelayers", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const relayers = await prisma.relayers.findMany(); - - return res.status(StatusCodes.OK).send({ - result: relayers.map((relayer) => ({ - ...relayer, - allowedContracts: relayer.allowedContracts - ? JSON.parse(relayer.allowedContracts) - : null, - allowedForwarders: relayer.allowedForwarders - ? JSON.parse(relayer.allowedForwarders) - : null, - })), - }); - }, - }); -} diff --git a/src/server/routes/relayer/index.ts b/src/server/routes/relayer/index.ts deleted file mode 100644 index 2f5883768..000000000 --- a/src/server/routes/relayer/index.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { ethers, utils } from "ethers"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - ERC20PermitAbi, - ERC2771ContextAbi, - ForwarderAbi, - ForwarderAbiEIP712ChainlessDomain, - NativeMetaTransaction, -} from "../../../shared/schemas/relayer"; -import { getRelayerById } from "../../../shared/db/relayer/get-relayer-by-id"; -import { queueTx } from "../../../shared/db/transactions/queue-tx"; -import { getSdk } from "../../../shared/utils/cache/get-sdk"; -import { AddressSchema } from "../../schemas/address"; -import { - standardResponseSchema, - transactionWritesResponseSchema, -} from "../../schemas/shared-api-schemas"; - -const ParamsSchema = Type.Object({ - relayerId: Type.String(), -}); - -const requestBodySchema = Type.Union([ - Type.Object({ - type: Type.Literal("forward"), - request: Type.Object({ - from: Type.String(), - to: Type.String(), - value: Type.String(), - gas: Type.String(), - nonce: Type.String(), - data: Type.String(), - chainid: Type.Optional(Type.String()), - }), - signature: Type.String(), - forwarderAddress: AddressSchema, - }), - Type.Object({ - type: Type.Literal("permit"), - request: Type.Object({ - to: Type.String(), - owner: Type.String(), - spender: Type.String(), - value: Type.String(), - nonce: Type.String(), - deadline: Type.String(), - }), - signature: Type.String(), - }), - Type.Object({ - type: Type.Literal("execute-meta-transaction"), - request: Type.Object({ - from: Type.String(), - to: Type.String(), - data: Type.String(), - }), - signature: Type.String(), - }), -]); - -const responseBodySchema = Type.Composite([ - Type.Object({ - result: Type.Optional( - Type.Object({ - queueId: Type.String({ - description: "Queue ID", - }), - }), - ), - }), - Type.Object({ - error: Type.Optional( - Type.Object({ - message: Type.String(), - }), - ), - }), -]); - -export async function relayTransaction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - Body: Static; - }>({ - method: "POST", - url: "/relayer/:relayerId", - schema: { - summary: "Relay a meta-transaction", - description: "Relay an EIP-2771 meta-transaction", - tags: ["Relayer"], - operationId: "relay", - params: ParamsSchema, - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: transactionWritesResponseSchema, - }, - }, - handler: async (req, res) => { - const { relayerId } = req.params; - - const relayer = await getRelayerById({ id: relayerId }); - if (!relayer) { - return res.status(400).send({ - error: { - message: `No relayer found with id '${relayerId}'`, - }, - }); - } - - const sdk = await getSdk({ - chainId: relayer.chainId, - walletAddress: relayer.backendWalletAddress, - }); - - if (req.body.type === "execute-meta-transaction") { - // Polygon Execute Meta Transaction - const { request, signature } = req.body; - const { v, r, s } = utils.splitSignature(signature); - - if ( - relayer.allowedContracts && - !relayer.allowedContracts.includes(request.to.toLowerCase()) - ) { - return res.status(400).send({ - error: { - message: `Requesting to relay transaction to unauthorized contract ${request.to}.`, - }, - }); - } - - const target = await sdk.getContractFromAbi( - request.to.toLowerCase(), - NativeMetaTransaction, - ); - - const tx = target.prepare("executeMetaTransaction", [ - request.from, - request.data, - r, - s, - v, - ]); - - const queueId = await queueTx({ - tx, - chainId: relayer.chainId, - extension: "relayer", - }); - - res.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - return; - }if (req.body.type === "permit") { - // EIP-2612 - const { request, signature } = req.body; - const { v, r, s } = utils.splitSignature(signature); - - // TODO: Remaining for backwards compatibility, but should enforce in the future - if ( - relayer.allowedContracts && - !relayer.allowedContracts.includes(request.to.toLowerCase()) - ) { - return res.status(400).send({ - error: { - message: `Requesting to relay transaction to unauthorized contract ${request.to}.`, - }, - }); - } - - const target = await sdk.getContractFromAbi( - request.to.toLowerCase(), - ERC20PermitAbi, - ); - - const tx = target.prepare("permit", [ - request.owner, - request.spender, - request.value, - request.deadline, - v, - r, - s, - ]); - - const queueId = await queueTx({ - tx, - chainId: relayer.chainId, - extension: "relayer", - }); - - res.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - return; - } - - // EIP-2771 - const { request, signature, forwarderAddress } = req.body; - - if ( - relayer.allowedForwarders && - !relayer.allowedForwarders.includes(forwarderAddress.toLowerCase()) - ) { - return res.status(400).send({ - error: { - message: `Requesting to relay transaction with unauthorized forwarder ${forwarderAddress}.`, - }, - }); - } - - // TODO: Remaining for backwards compatibility, but should enforce in the future - if ( - relayer.allowedContracts && - !relayer.allowedContracts.includes(request.to.toLowerCase()) - ) { - return res.status(400).send({ - error: { - message: `Requesting to relay transaction to unauthorized contract ${request.to}.`, - }, - }); - } - - if (request.value !== "0") { - return res.status(400).send({ - error: { - message: `Requesting to relay transaction with non-zero value ${request.value}.`, - }, - }); - } - - // EIP-2771 - const target = await sdk.getContractFromAbi( - request.to.toLowerCase(), - ERC2771ContextAbi, - ); - - const isTrustedForwarder = await target.call("isTrustedForwarder", [ - forwarderAddress, - ]); - if (!isTrustedForwarder) { - res.status(400).send({ - error: { - message: `Requesting to relay transaction with untrusted forwarder ${forwarderAddress}.`, - }, - }); - return; - } - - const isForwarderEIP712ChainlessDomain = !!request.chainid; - const forwarderAbi = isForwarderEIP712ChainlessDomain - ? ForwarderAbiEIP712ChainlessDomain - : ForwarderAbi; - - const forwarder = await sdk.getContractFromAbi( - forwarderAddress, - forwarderAbi, - ); - - const fixedSignature = ethers.utils.joinSignature( - ethers.utils.splitSignature(signature), - ); - const valid = await forwarder.call("verify", [request, fixedSignature]); - - if (!valid) { - res.status(400).send({ - error: { - message: "Verification failed with provided message and signature", - }, - }); - return; - } - - const tx = forwarder.prepare("execute", [request, fixedSignature]); - const queueId = await queueTx({ - tx, - chainId: relayer.chainId, - extension: "relayer", - }); - - res.status(StatusCodes.OK).send({ - result: { - queueId, - }, - }); - }, - }); -} diff --git a/src/server/routes/relayer/revoke.ts b/src/server/routes/relayer/revoke.ts deleted file mode 100644 index 3ceedb940..000000000 --- a/src/server/routes/relayer/revoke.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { prisma } from "../../../shared/db/client"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - id: Type.String(), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function revokeRelayer(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/relayer/revoke", - schema: { - summary: "Revoke a relayer", - description: "Revoke a relayer", - tags: ["Relayer"], - operationId: "revokeRelayer", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { id } = req.body; - - await prisma.relayers.delete({ - where: { - id, - }, - }); - - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/relayer/update.ts b/src/server/routes/relayer/update.ts deleted file mode 100644 index ed55603ef..000000000 --- a/src/server/routes/relayer/update.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { prisma } from "../../../shared/db/client"; -import { AddressSchema } from "../../schemas/address"; -import { chainIdOrSlugSchema } from "../../schemas/chain"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../utils/chain"; - -const requestBodySchema = Type.Object({ - id: Type.String(), - name: Type.Optional(Type.String()), - chain: Type.Optional(chainIdOrSlugSchema), - backendWalletAddress: Type.Optional(AddressSchema), - allowedContracts: Type.Optional(Type.Array(Type.String())), - allowedForwarders: Type.Optional(Type.Array(Type.String())), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function updateRelayer(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/relayer/update", - schema: { - summary: "Update a relayer", - description: "Update a relayer", - tags: ["Relayer"], - operationId: "updateRelayer", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { - id, - name, - chain, - backendWalletAddress, - allowedContracts, - allowedForwarders, - } = req.body; - - const chainId = chain - ? (await getChainIdFromChain(chain)).toString() - : undefined; - await prisma.relayers.update({ - where: { - id, - }, - data: { - name, - chainId, - backendWalletAddress, - allowedContracts: allowedContracts - ? JSON.stringify( - allowedContracts.map((address) => address.toLowerCase()), - ) - : null, - allowedForwarders: allowedForwarders - ? JSON.stringify( - allowedForwarders.map((address) => address.toLowerCase()), - ) - : null, - }, - }); - - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/system/health.ts b/src/server/routes/system/health.ts deleted file mode 100644 index ed3718df1..000000000 --- a/src/server/routes/system/health.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { isDatabaseReachable } from "../../../shared/db/client"; -import { env } from "../../../shared/utils/env"; -import { isRedisReachable } from "../../../shared/utils/redis/redis"; -import { thirdwebClientId } from "../../../shared/utils/sdk"; - -type EngineFeature = - | "KEYPAIR_AUTH" - | "CONTRACT_SUBSCRIPTIONS" - | "IP_ALLOWLIST" - | "HETEROGENEOUS_WALLET_TYPES" - | "SMART_BACKEND_WALLETS" - | "WALLET_CREDENTIALS"; - -const ReplySchema = Type.Object({ - db: Type.Boolean(), - redis: Type.Boolean(), - auth: Type.Boolean(), - engineVersion: Type.Optional(Type.String()), - engineTier: Type.Optional(Type.String()), - features: Type.Array( - Type.Union([ - Type.Literal("KEYPAIR_AUTH"), - Type.Literal("CONTRACT_SUBSCRIPTIONS"), - Type.Literal("IP_ALLOWLIST"), - Type.Literal("HETEROGENEOUS_WALLET_TYPES"), - Type.Literal("SMART_BACKEND_WALLETS"), - Type.Literal("WALLET_CREDENTIALS"), - ]), - ), - clientId: Type.String(), -}); - -export async function healthCheck(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/system/health", - schema: { - hide: true, - summary: "Check health", - description: "Check the system health of Engine", - tags: ["System"], - operationId: "checkHealth", - response: { - [StatusCodes.OK]: ReplySchema, - [StatusCodes.SERVICE_UNAVAILABLE]: ReplySchema, - }, - }, - handler: async (_, res) => { - const db = await isDatabaseReachable(); - const redis = await isRedisReachable(); - const auth = await isAuthValid(); - const isHealthy = db && redis && auth; - - res - .status(isHealthy ? StatusCodes.OK : StatusCodes.SERVICE_UNAVAILABLE) - .send({ - db, - redis, - auth, - engineVersion: env.ENGINE_VERSION, - engineTier: env.ENGINE_TIER ?? "SELF_HOSTED", - features: getFeatures(), - clientId: thirdwebClientId, - }); - }, - }); -} - -const getFeatures = (): EngineFeature[] => { - // Default list is populated with features that are always enabled. - // Added here to make dashboard UI backwards compatible. - const features: EngineFeature[] = [ - "IP_ALLOWLIST", - "HETEROGENEOUS_WALLET_TYPES", - "CONTRACT_SUBSCRIPTIONS", - "SMART_BACKEND_WALLETS", - "WALLET_CREDENTIALS", - ]; - - if (env.ENABLE_KEYPAIR_AUTH) features.push("KEYPAIR_AUTH"); - - return features; -}; - -async function isAuthValid() { - try { - const resp = await fetch("http://github.com/service/https://api.thirdweb.com/v2/keys/use", { - headers: { - "x-secret-key": env.THIRDWEB_API_SECRET_KEY, - }, - }); - return resp.ok; - } catch { - return false; - } -} diff --git a/src/server/routes/system/queue.ts b/src/server/routes/system/queue.ts deleted file mode 100644 index 54b3adf58..000000000 --- a/src/server/routes/system/queue.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { getPercentile } from "../../../shared/utils/math"; -import type { MinedTransaction } from "../../../shared/utils/transaction/types"; -import { MineTransactionQueue } from "../../../worker/queues/mine-transaction-queue"; -import { SendTransactionQueue } from "../../../worker/queues/send-transaction-queue"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const responseBodySchema = Type.Object({ - result: Type.Object({ - queued: Type.Integer(), - pending: Type.Integer(), - latency: Type.Object({ - msToSend: Type.Object({ - p50: Type.Number(), - p90: Type.Number(), - }), - msToMine: Type.Object({ - p50: Type.Number(), - p90: Type.Number(), - }), - }), - }), -}); - -export async function queueStatus(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/system/queue", - schema: { - hide: true, - summary: "Check queue status", - description: "Check the status of the queue", - tags: ["System"], - operationId: "queueStatus", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - // Get # queued and sent transactions. - const queued = await SendTransactionQueue.length(); - const pending = await MineTransactionQueue.length(); - - // Get last 1k mined transactions. - const minedTransactionsList = - await TransactionDB.getTransactionListByStatus({ - status: "mined", - page: 1, - limit: 1_000, - }); - const minedTransactions = - minedTransactionsList.transactions as MinedTransaction[]; - - // Get "queue -> send" and "queue -> mine" times. - const msToSendArr: number[] = []; - const msToMineArr: number[] = []; - for (const transaction of minedTransactions) { - const queuedAt = transaction.queuedAt.getTime(); - const sentAt = transaction.sentAt.getTime(); - const minedAt = transaction.minedAt.getTime(); - msToSendArr.push(sentAt - queuedAt); - msToMineArr.push(minedAt - queuedAt); - } - - res.status(StatusCodes.OK).send({ - result: { - queued, - pending, - latency: { - msToSend: { - p50: getPercentile(msToSendArr, 50), - p90: getPercentile(msToSendArr, 90), - }, - msToMine: { - p50: getPercentile(msToMineArr, 50), - p90: getPercentile(msToMineArr, 90), - }, - }, - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/blockchain/get-logs.ts b/src/server/routes/transaction/blockchain/get-logs.ts deleted file mode 100644 index 171e1262d..000000000 --- a/src/server/routes/transaction/blockchain/get-logs.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { AbiEvent } from "abitype"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import superjson from "superjson"; -import { - eth_getTransactionReceipt, - getContract, - getRpcClient, - parseEventLogs, - prepareEvent, - type Hex, -} from "thirdweb"; -import { resolveContractAbi } from "thirdweb/contract"; -import type { TransactionReceipt } from "thirdweb/transaction"; -import { TransactionDB } from "../../../../shared/db/transactions/db"; -import { getChain } from "../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../shared/utils/sdk"; -import { createCustomError } from "../../../middleware/error"; -import { AddressSchema, TransactionHashSchema } from "../../../schemas/address"; -import { chainIdOrSlugSchema } from "../../../schemas/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUT -const requestQuerystringSchema = Type.Object({ - chain: chainIdOrSlugSchema, - queueId: Type.Optional( - Type.String({ - description: "The queue ID for a mined transaction.", - }), - ), - transactionHash: Type.Optional({ - ...TransactionHashSchema, - description: "The transaction hash for a mined transaction.", - }), - parseLogs: Type.Optional( - Type.Boolean({ - description: - "If true, parse the raw logs as events defined in the contract ABI. (Default: true)", - }), - ), -}); - -// OUTPUT -const LogSchema = Type.Object({ - address: AddressSchema, - topics: Type.Array(Type.String()), - data: Type.String(), - blockNumber: Type.String(), - transactionHash: TransactionHashSchema, - transactionIndex: Type.Integer(), - blockHash: Type.String(), - logIndex: Type.Integer(), - removed: Type.Boolean(), - - // Additional properties only for parsed logs - eventName: Type.Optional( - Type.String({ - description: "Event name, only returned when `parseLogs` is true", - }), - ), - args: Type.Optional( - Type.Unknown({ - description: "Event arguments. Only returned when `parseLogs` is true", - examples: [ - { - from: "0xdeadbeeefdeadbeeefdeadbeeefdeadbeeefdead", - to: "0xdeadbeeefdeadbeeefdeadbeeefdeadbeeefdead", - value: "1000000000000000000n", - }, - ], - }), - ), -}); - -// DO NOT USE type.union -// this is known to cause issues with the generated types -export const responseBodySchema = Type.Object({ - result: Type.Array(LogSchema), -}); - -responseBodySchema.example = { - result: [ - { - eventName: "Transfer", - args: { - from: "0x0000000000000000000000000000000000000000", - to: "0x71B6267b5b2b0B64EE058C3D27D58e4E14e7327f", - value: "1000000000000000000n", - }, - address: "0x71b6267b5b2b0b64ee058c3d27d58e4e14e7327f", - topics: [ - "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000071b6267b5b2b0b64ee058c3d27d58e4e14e7327f", - ], - data: "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000", - blockNumber: "79326434", - transactionHash: - "0x568eb49d738f7c02ebb24aa329efcf10883d951b1e13aa000b0e073d54a0246e", - transactionIndex: 1, - blockHash: - "0xaffbcf3232a76152206de5f6999c549404efc76060a34f8826b90c95993464c3", - logIndex: 0, - removed: false, - }, - ], -}; - -export async function getTransactionLogs(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/transaction/logs", - schema: { - summary: "Get transaction logs", - description: - "Get transaction logs for a mined transaction. A tranasction queue ID or hash must be provided. Set `parseLogs` to parse the event logs.", - tags: ["Transaction"], - operationId: "getTransactionLogs", - querystring: requestQuerystringSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { - chain: inputChain, - queueId, - transactionHash, - parseLogs = true, - } = request.query; - - const chainId = await getChainIdFromChain(inputChain); - const chain = await getChain(chainId); - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain, - }); - - if (!queueId && !transactionHash) { - throw createCustomError( - "Either a queue ID or transaction hash must be provided.", - StatusCodes.BAD_REQUEST, - "MISSING_TRANSACTION_ID", - ); - } - - // Get the transaction hash from the provided input. - let hash: Hex | undefined; - if (queueId) { - const transaction = await TransactionDB.get(queueId); - if (transaction?.status === "mined") { - hash = transaction.transactionHash; - } - } else if (transactionHash) { - hash = transactionHash as Hex; - } - if (!hash) { - throw createCustomError( - "Could not find transaction, or transaction is not mined.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_MINED", - ); - } - - // Try to get the receipt. - let transactionReceipt: TransactionReceipt | undefined; - try { - transactionReceipt = await eth_getTransactionReceipt(rpcRequest, { - hash, - }); - } catch { - throw createCustomError( - "Unable to get transaction receipt. The transaction may not have been mined yet.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_MINED", - ); - } - - if (!parseLogs) { - return reply.status(StatusCodes.OK).send({ - result: superjson.serialize(transactionReceipt.logs).json as Static< - typeof LogSchema - >[], - }); - } - - if (!transactionReceipt.to) { - throw createCustomError( - "Transaction logs are only supported for contract calls.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_LOGS_UNAVAILABLE", - ); - } - - const contract = getContract({ - address: transactionReceipt.to, - chain, - client: thirdwebClient, - }); - - const abi: AbiEvent[] = await resolveContractAbi(contract); - const eventSignatures = abi.filter((item) => item.type === "event"); - if (eventSignatures.length === 0) { - throw createCustomError( - "No events found in contract or could not resolve contract ABI", - StatusCodes.BAD_REQUEST, - "NO_EVENTS_FOUND", - ); - } - - const preparedEvents = eventSignatures.map((signature) => - prepareEvent({ signature }), - ); - const parsedLogs = parseEventLogs({ - events: preparedEvents, - logs: transactionReceipt.logs, - }); - - reply.status(StatusCodes.OK).send({ - result: superjson.serialize(parsedLogs).json as Static< - typeof LogSchema - >[], - }); - }, - }); -} diff --git a/src/server/routes/transaction/blockchain/get-receipt.ts b/src/server/routes/transaction/blockchain/get-receipt.ts deleted file mode 100644 index e3473026b..000000000 --- a/src/server/routes/transaction/blockchain/get-receipt.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - eth_getTransactionReceipt, - getRpcClient, - toHex, - type Hex, -} from "thirdweb"; -import { stringify } from "thirdweb/utils"; -import type { TransactionReceipt } from "viem"; -import { getChain } from "../../../../shared/utils/chain"; -import { - fromTransactionStatus, - fromTransactionType, - thirdwebClient, -} from "../../../../shared/utils/sdk"; -import { createCustomError } from "../../../middleware/error"; -import { AddressSchema, TransactionHashSchema } from "../../../schemas/address"; -import { chainIdOrSlugSchema } from "../../../schemas/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUT -const requestSchema = Type.Object({ - chain: chainIdOrSlugSchema, - transactionHash: { - ...TransactionHashSchema, - description: "Transaction hash", - }, -}); - -// OUTPUT -export const responseBodySchema = Type.Object({ - result: Type.Union([ - Type.Partial( - Type.Object({ - to: Type.String(), - from: Type.String(), - contractAddress: Type.Union([AddressSchema, Type.Null()]), - transactionIndex: Type.Integer(), - root: Type.String(), - gasUsed: Type.String(), - logsBloom: Type.String(), - blockHash: Type.String(), - transactionHash: TransactionHashSchema, - logs: Type.Array(Type.Any()), - blockNumber: Type.Integer(), - confirmations: Type.Integer(), - cumulativeGasUsed: Type.String(), - effectiveGasPrice: Type.String(), - byzantium: Type.Boolean(), - type: Type.Integer(), - status: Type.Integer(), - }), - ), - Type.Null(), - ]), -}); - -responseBodySchema.example = { - result: { - to: "0xd7419703c2D5737646525A8660906eCb612875BD", - from: "0x9783Eb2a93A58b24CFeC56F94b30aB6e29fF4b38", - contractAddress: null, - transactionIndex: 69, - gasUsed: "21000", - logsBloom: - "0x00000000000200000000000000000000000000000000000000000000000000000000000000000000000000100002000000008000000000000000000000002000000000000000000000000000000000800000000000000000000100000000040000000000000000000000000000000000008000000000000080000000000000000000000000000000000000000000000000000000000000040000000000000000200000000000004000800000000000000000000000000000000000000000004000000000000000000001000000000000000000000000800000108000000000000000000000000000000000000000000000000000000000000000008000100000", - blockHash: - "0x9be85de9e6a0717ed2e7c9035f7bd748a4b20bc9d6e04a6875fa69311421d971", - transactionHash: - "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - logs: [ - { - transactionIndex: 69, - blockNumber: 51048531, - transactionHash: - "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - address: "0x0000000000000000000000000000000000001010", - topics: [ - "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x0000000000000000000000009783eb2a93a58b24cfec56f94b30ab6e29ff4b38", - "0x000000000000000000000000d7419703c2d5737646525a8660906ecb612875bd", - ], - data: "0x00000000000000000000000000000000000000000000000006a4d6a25acff49800000000000000000000000000000000000000000000000006b787e1bb9f06f80000000000000000000000000000000000000000000000051ac78aecb02246820000000000000000000000000000000000000000000000000012b13f60cf1260000000000000000000000000000000000000000000000005216c618f0af23b1a", - logIndex: 181, - blockHash: - "0x9be85de9e6a0717ed2e7c9035f7bd748a4b20bc9d6e04a6875fa69311421d971", - }, - { - transactionIndex: 69, - blockNumber: 51048531, - transactionHash: - "0xd9bcba8f5bc4ce5bf4d631b2a0144329c1df3b56ddb9fc64637ed3a4219dd087", - address: "0x0000000000000000000000000000000000001010", - topics: [ - "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x0000000000000000000000009783eb2a93a58b24cfec56f94b30ab6e29ff4b38", - "0x000000000000000000000000a8b52f02108aa5f4b675bdcc973760022d7c6020", - ], - data: "0x00000000000000000000000000000000000000000000000000046a2c9f9fd11800000000000000000000000000000000000000000000000006ce8dc1a70476680000000000000000000000000000000000000000000006df390338516c1391c300000000000000000000000000000000000000000000000006ca23950764a5500000000000000000000000000000000000000000000006df3907a27e0bb362db", - logIndex: 182, - blockHash: - "0x9be85de9e6a0717ed2e7c9035f7bd748a4b20bc9d6e04a6875fa69311421d971", - }, - ], - blockNumber: 51048531, - confirmations: 3232643, - cumulativeGasUsed: "5751865", - effectiveGasPrice: "257158085297", - status: 1, - type: 2, - byzantium: true, - }, -}; - -export async function getTransactionReceipt(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/transaction/:chain/tx-hash/:transactionHash", - schema: { - summary: "Get transaction receipt", - description: "Get the transaction receipt from a transaction hash.", - tags: ["Transaction"], - operationId: "getTransactionReceipt", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, transactionHash } = request.params; - - const chainId = await getChainIdFromChain(chain); - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - - let receipt: TransactionReceipt; - try { - receipt = await eth_getTransactionReceipt(rpcRequest, { - hash: transactionHash as Hex, - }); - } catch { - throw createCustomError( - "Transaction is not mined.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_MINED", - ); - } - - reply.status(StatusCodes.OK).send({ - result: { - ...JSON.parse(stringify(receipt)), - gasUsed: toHex(receipt.gasUsed), - cumulativeGasUsed: toHex(receipt.cumulativeGasUsed), - effectiveGasPrice: toHex(receipt.effectiveGasPrice), - blockNumber: Number(receipt.blockNumber), - type: fromTransactionType(receipt.type), - status: fromTransactionStatus(receipt.status), - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/blockchain/get-user-op-receipt.ts b/src/server/routes/transaction/blockchain/get-user-op-receipt.ts deleted file mode 100644 index cee358858..000000000 --- a/src/server/routes/transaction/blockchain/get-user-op-receipt.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { env } from "../../../../shared/utils/env"; -import { createCustomError } from "../../../middleware/error"; -import { TransactionHashSchema } from "../../../schemas/address"; -import { chainIdOrSlugSchema } from "../../../schemas/chain"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { getChainIdFromChain } from "../../../utils/chain"; - -// INPUT -const requestSchema = Type.Object({ - chain: chainIdOrSlugSchema, - userOpHash: { - ...TransactionHashSchema, - description: "User operation hash", - }, -}); - -// OUTPUT -export const responseBodySchema = Type.Object({ - // TODO: Use Type.Any() instead of strict typing. - // UserOp receipts from different providers/chains may not have a consistent response, - // so Engine would prefer to return _any_ result than fail due to strict typing errors. - result: Type.Any(), -}); - -responseBodySchema.example = { - result: { - userOpHash: - "0xa5a579c6fd86c2d8a4d27f5bb22796614d3a31bbccaba8f3019ec001e001b95f", - sender: "0x8C6bdb488F664EB98E12cB2671fE2389Cc227D33", - nonce: "0x18554d9a95404c5e8ac591f8608a18f80000000000000000", - actualGasCost: "0x4b3b147f788710", - actualGasUsed: "0x7f550", - success: true, - paymaster: "0xe3dc822D77f8cA7ac74c30B0dfFEA9FcDCAAA321", - logs: [], - receipt: { - type: "eip1559", - status: "success", - cumulativeGasUsed: "0x4724c3", - logsBloom: - "0x010004000800020000000040000000000000040000000000000010000004000000080000001000000212841100000000041080000000000020000240000000000800000022001000400000080000028000040000000000200001000010000000000000000a0000000000000000800800000000004110004080800110282000000000000002000000000000000000000000000200000400000000000000240040200002000000000000400000000002000140000000000000000002200000004000000002000000000021000000000000000000000000800080108020000020000000080000000000000000000000000000000000000000000108000000102000", - logs: [], - transactionHash: - "0x57465d20d634421008a167cfcfcde94847dba9d6b5d3652b071d4b84e5ce74ff", - from: "0x43370996a3aff7b66b3ac7676dd973d01ecec039", - to: "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789", - contractAddress: null, - gasUsed: "0x7ff5a", - effectiveGasPrice: "0x89b098f46", - blockHash: - "0xeaeec1eff4095bdcae44d86574cf1bf08b14b26be571b7c2290f32f9f250c103", - blockNumber: "0x31de70e", - transactionIndex: 32, - blobGasUsed: "0x0", - }, - }, -}; - -export async function getUserOpReceipt(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/transaction/:chain/userop-hash/:userOpHash", - schema: { - summary: "Get transaction receipt from user-op hash", - description: "Get the transaction receipt from a user-op hash.", - tags: ["Transaction"], - operationId: "useropHashReceipt", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { chain, userOpHash } = request.params; - const chainId = await getChainIdFromChain(chain); - - try { - const url = `https://${chainId}.bundler.thirdweb.com`; - const resp = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/json", - "x-secret-key": env.THIRDWEB_API_SECRET_KEY, - }, - body: JSON.stringify({ - id: 0, - jsonrpc: "2.0", - method: "eth_getUserOperationReceipt", - params: [userOpHash], - }), - }); - if (!resp.ok) { - throw `Unexpected status ${resp.status} - ${await resp.text()}`; - } - - const json = await resp.json(); - reply.status(StatusCodes.OK).send({ - result: json.result, - }); - } catch (_e) { - throw createCustomError( - "Unable to get receipt.", - StatusCodes.INTERNAL_SERVER_ERROR, - "UserOpReceiptError", - ); - } - }, - }); -} diff --git a/src/server/routes/transaction/blockchain/send-signed-tx.ts b/src/server/routes/transaction/blockchain/send-signed-tx.ts deleted file mode 100644 index 862fc261b..000000000 --- a/src/server/routes/transaction/blockchain/send-signed-tx.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { eth_sendRawTransaction, getRpcClient, isHex } from "thirdweb"; -import { getChain } from "../../../../shared/utils/chain"; -import { thirdwebClient } from "../../../../shared/utils/sdk"; -import { createCustomError } from "../../../middleware/error"; -import { TransactionHashSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { walletChainParamSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; - -const requestBodySchema = Type.Object({ - signedTransaction: Type.String(), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - transactionHash: TransactionHashSchema, - }), -}); - -export async function sendSignedTransaction(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/transaction/:chain/send-signed-transaction", - schema: { - summary: "Send a signed transaction", - description: "Send a signed transaction", - tags: ["Transaction"], - operationId: "sendRawTransaction", - params: walletChainParamSchema, - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { chain } = req.params; - const { signedTransaction } = req.body; - const chainId = await getChainIdFromChain(chain); - - if (!isHex(signedTransaction)) { - throw createCustomError( - "SignedTransaction is not a valid hex string.", - StatusCodes.BAD_REQUEST, - "SendSignedTxError", - ); - } - - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - const transactionHash = await eth_sendRawTransaction( - rpcRequest, - signedTransaction, - ); - - res.status(StatusCodes.OK).send({ - result: { - transactionHash, - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/blockchain/send-signed-user-op.ts b/src/server/routes/transaction/blockchain/send-signed-user-op.ts deleted file mode 100644 index 03acb2cc3..000000000 --- a/src/server/routes/transaction/blockchain/send-signed-user-op.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { Value } from "@sinclair/typebox/value"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { env } from "../../../../shared/utils/env"; -import { thirdwebClientId } from "../../../../shared/utils/sdk"; -import { TransactionHashSchema } from "../../../schemas/address"; -import { standardResponseSchema } from "../../../schemas/shared-api-schemas"; -import { walletChainParamSchema } from "../../../schemas/wallet"; -import { getChainIdFromChain } from "../../../utils/chain"; -import { prettifyError } from "../../../../shared/utils/error"; - -const UserOp = Type.Object({ - sender: Type.String(), - nonce: Type.String(), - initCode: Type.String(), - callData: Type.String(), - callGasLimit: Type.String(), - verificationGasLimit: Type.String(), - preVerificationGas: Type.String(), - maxFeePerGas: Type.String(), - maxPriorityFeePerGas: Type.String(), - paymasterAndData: Type.String(), - signature: Type.String(), -}); - -const UserOpString = Type.Transform(Type.String()) - .Decode((signedUserOp) => JSON.parse(signedUserOp) as Static) - .Encode((userOp) => JSON.stringify(userOp)); - -const requestBodySchema = Type.Object({ - // signedUserOp: Type.Union([UserOpString, UserOp]), - signedUserOp: Type.Any(), -}); - -const responseBodySchema = Type.Union([ - Type.Object({ - result: Type.Object({ - userOpHash: TransactionHashSchema, - }), - }), - Type.Object({ - error: Type.Object({ - message: Type.String(), - }), - }), -]); - -type RpcResponse = - | { - result: string; - error: undefined; - } - | { - result: undefined; - error: { - message: string; - }; - }; - -export async function sendSignedUserOp(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/transaction/:chain/send-signed-user-op", - schema: { - summary: "Send a signed user operation", - description: "Send a signed user operation", - tags: ["Transaction"], - operationId: "sendSignedUserOp", - params: walletChainParamSchema, - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { chain } = req.params; - const { signedUserOp } = req.body; - const chainId = await getChainIdFromChain(chain); - - let userOp: Static; - if (typeof signedUserOp === "string") { - try { - userOp = Value.Decode(UserOpString, signedUserOp); - } catch (err) { - return res.status(400).send({ - error: { - message: `Invalid signed user operation. - ${prettifyError(err)}`, - }, - }); - } - } else { - userOp = signedUserOp; - } - - const entryPointAddress = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"; - const userOpRes = await fetch(`https://${chainId}.bundler.thirdweb.com`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "x-client-id": thirdwebClientId, - "x-secret-key": env.THIRDWEB_API_SECRET_KEY, - }, - body: JSON.stringify({ - id: 1, - jsonrpc: "2.0", - method: "eth_sendUserOperation", - params: [userOp, entryPointAddress], - }), - }); - - const { result: userOpHash, error } = - (await userOpRes.json()) as RpcResponse; - - if (error) { - return res.status(400).send({ - error: { - message: `Failed to send - ${error.message || error}`, - }, - }); - } - - return res.status(StatusCodes.OK).send({ - result: { - userOpHash, - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/cancel.ts b/src/server/routes/transaction/cancel.ts deleted file mode 100644 index 866e207eb..000000000 --- a/src/server/routes/transaction/cancel.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { getBlockNumberish } from "../../../shared/utils/block"; -import { getConfig } from "../../../shared/utils/cache/get-config"; -import { getChain } from "../../../shared/utils/chain"; -import { msSince } from "../../../shared/utils/date"; -import { sendCancellationTransaction } from "../../../shared/utils/transaction/cancel-transaction"; -import type { CancelledTransaction } from "../../../shared/utils/transaction/types"; -import { enqueueTransactionWebhook } from "../../../shared/utils/transaction/webhook"; -import { reportUsage } from "../../../shared/utils/usage"; -import { SendTransactionQueue } from "../../../worker/queues/send-transaction-queue"; -import { createCustomError } from "../../middleware/error"; -import { TransactionHashSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -// INPUT -const requestBodySchema = Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), -}); - -// OUTPUT -export const responseBodySchema = Type.Object({ - result: Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), - status: Type.String({ - description: "Response status", - examples: ["success, error"], - }), - message: Type.String({ - description: "Response message", - examples: ["Transaction cancelled on-chain successfully"], - }), - transactionHash: Type.Optional(TransactionHashSchema), - }), -}); - -responseBodySchema.example = { - result: { - queueId: "a20ed4ce-301d-4251-a7af-86bd88f6c015", - status: "success", - }, -}; - -export async function cancelTransaction(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/transaction/cancel", - schema: { - summary: "Cancel transaction", - description: - "Attempt to cancel a transaction by sending a null transaction with a higher gas setting. This transaction is not guaranteed to be cancelled.", - tags: ["Transaction"], - operationId: "cancel", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { queueId } = request.body; - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - throw createCustomError( - "Transaction not found.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_FOUND", - ); - } - - const message = "Transaction successfully cancelled."; - let cancelledTransaction: CancelledTransaction | null = null; - if (!transaction.isUserOp) { - if (transaction.status === "queued") { - // Remove all retries from the SEND_TRANSACTION queue. - const config = await getConfig(); - for ( - let resendCount = 0; - resendCount < config.maxRetriesPerTx; - resendCount++ - ) { - await SendTransactionQueue.remove({ queueId, resendCount }); - } - - cancelledTransaction = { - ...transaction, - status: "cancelled", - cancelledAt: new Date(), - - // Dummy data since the transaction was never sent. - sentAt: new Date(), - sentAtBlock: await getBlockNumberish(transaction.chainId), - - isUserOp: false, - gas: 0n, - nonce: -1, - sentTransactionHashes: [], - }; - } else if (transaction.status === "sent") { - // Cancel a sent transaction with the same nonce. - const { chainId, from, nonce } = transaction; - const transactionHash = await sendCancellationTransaction({ - chainId, - from, - nonce, - }); - cancelledTransaction = { - ...transaction, - status: "cancelled", - cancelledAt: new Date(), - sentTransactionHashes: [transactionHash], - }; - } - } - - if (!cancelledTransaction) { - throw createCustomError( - "Transaction cannot be cancelled.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_CANNOT_BE_CANCELLED", - ); - } - - // A queued or sent transaction was successfully cancelled. - await TransactionDB.set(cancelledTransaction); - await enqueueTransactionWebhook(cancelledTransaction); - await _reportUsageSuccess(cancelledTransaction); - - return reply.status(StatusCodes.OK).send({ - result: { - queueId, - status: "success", - message, - transactionHash: cancelledTransaction.sentTransactionHashes.at(-1), - }, - }); - }, - }); -} - -const _reportUsageSuccess = async ( - cancelledTransaction: CancelledTransaction, -) => { - const chain = await getChain(cancelledTransaction.chainId); - reportUsage([ - { - action: "cancel_tx", - input: { - ...cancelledTransaction, - provider: chain.rpc, - msSinceQueue: msSince(cancelledTransaction.queuedAt), - msSinceSend: msSince(cancelledTransaction.sentAt), - }, - }, - ]); -}; diff --git a/src/server/routes/transaction/get-all-deployed-contracts.ts b/src/server/routes/transaction/get-all-deployed-contracts.ts deleted file mode 100644 index 11802e01d..000000000 --- a/src/server/routes/transaction/get-all-deployed-contracts.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { - TransactionSchema, - toTransactionSchema, -} from "../../schemas/transaction"; - -const requestQuerySchema = Type.Object({ - page: Type.Integer({ - description: "Specify the page number for pagination.", - examples: [1], - default: 1, - minimum: 1, - }), - limit: Type.Integer({ - description: "Specify the number of transactions to return per page.", - examples: [10], - default: 10, - minimum: 1, - }), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - transactions: Type.Array(TransactionSchema), - totalCount: Type.Integer(), - }), -}); - -responseBodySchema.example = { - result: { - transactions: [ - { - queueId: "8fe7d546-2b8b-465e-b0d2-f1cb5d3d0db3", - walletAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - contractAddress: "0x5dbc7b840baa9dabcbe9d2492e45d7244b54a2a0", - chainId: "80001", - extension: "deploy_prebuilt", - status: "submitted", - encodedInputData: - "0x11b804ab0000000000000000000000004fa15bae96f5816c268f3b473cf67e223644d536000000000000000000000000000000000000000000000000000000000000006033373131393539310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000284e15916340000000000000000000000003ecdbf3b911d0e9052b64850693888b008e183730000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000003ecdbf3b911d0e9052b64850693888b008e18373000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034949490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000349494900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037697066733a2f2f516d5553734471664a4879686375686f504e653650374566336547717864466e78516977526d37585a434234724b2f300000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c82bbe41f2cf04e3a8efa18f7032bdd7f6d98a810000000000000000000000009399bb24dbb5c4b782c70c2969f58716ebbd6a3b00000000000000000000000000000000000000000000000000000000", - txType: 2, - gasPrice: "", - gasLimit: "925188", - maxPriorityFeePerGas: "1500000000", - maxFeePerGas: "1500000032", - txHash: - "0x383b0ef55b76f1848f81c1016580f83faf3cde9f6affd66f789e741e39861f30", - submittedTxNonce: 111, - createdTimestamp: "2023-06-21T18:05:18.979Z", - txSubmittedTimestamp: "2023-06-21T18:05:21.823Z", - txProcessedTimestamp: "2023-06-21T18:05:21.823Z", - deployedContractAddress: "0x8dE0E40e8a5108Da3e0D65cFc908269fE083DfE7", - contractType: "edition", - }, - ], - totalCount: 1, - }, -}; - -export async function getAllDeployedContracts(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/transaction/get-all-deployed-contracts", - schema: { - summary: "Get all deployment transactions", - description: "Get all transaction requests to deploy contracts.", - tags: ["Transaction"], - operationId: "getAllDeployedContracts", - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { page, limit } = request.query; - - const { transactions } = await TransactionDB.getTransactionListByStatus({ - status: "queued", - page, - limit, - }); - const deploymentTransactions = transactions.filter( - (t) => !!t.deployedContractAddress, - ); - - reply.status(StatusCodes.OK).send({ - result: { - transactions: deploymentTransactions.map(toTransactionSchema), - // @TODO: this is inaccurate. - totalCount: 0, - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/get-all.ts b/src/server/routes/transaction/get-all.ts deleted file mode 100644 index c18e875dd..000000000 --- a/src/server/routes/transaction/get-all.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { PaginationSchema } from "../../schemas/pagination"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { - TransactionSchema, - toTransactionSchema, -} from "../../schemas/transaction"; - -const requestQuerySchema = Type.Object({ - ...PaginationSchema.properties, - status: Type.Union( - [ - // Note: 'queued' returns all transcations, not just transactions currently queued. - Type.Literal("queued"), - Type.Literal("mined"), - Type.Literal("cancelled"), - Type.Literal("errored"), - ], - { - description: - "The status to query: 'queued', 'mined', 'errored', or 'cancelled'. Default: 'queued'", - default: "queued", - }, - ), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - transactions: Type.Array(TransactionSchema), - totalCount: Type.Integer(), - }), -}); - -responseBodySchema.example = { - result: { - transactions: [ - { - queueId: "3bb66998-4c99-436c-9753-9dc931214a9b", - chainId: "80001", - fromAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - toAddress: "0x365b83d67d5539c6583b9c0266a548926bf216f4", - data: "0xa9059cbb0000000000000000000000003ecdbf3b911d0e9052b64850693888b008e183730000000000000000000000000000000000000000000000000000000000000064", - extension: "none", - value: "0x00", - nonce: 1758, - gasLimit: "39580", - gasPrice: "2008818932", - maxFeePerGas: "2209700838", - maxPriorityFeePerGas: "2008818916", - transactionType: 2, - transactionHash: - "0xf11ca950299c9e72b8d6cac8a03623c6e5a43af1d1b0d45b3fd804c129b573f8", - queuedAt: "2023-09-29T18:17:36.929Z", - sentAt: "2023-09-29T18:17:40.832Z", - minedAt: "2023-09-29T18:17:44.000Z", - cancelledAt: null, - deployedContractAddress: null, - deployedContractType: null, - errorMessage: null, - sentAtBlockNumber: 40653754, - blockNumber: 40653756, - status: "mined", - retryCount: 0, - retryGasValues: false, - retryMaxFeePerGas: null, - retryMaxPriorityFeePerGas: null, - signerAddress: null, - accountAddress: null, - target: null, - sender: null, - initCode: null, - callData: null, - callGasLimit: null, - verificationGasLimit: null, - preVerificationGas: null, - paymasterAndData: null, - userOpHash: null, - functionName: "transfer", - functionArgs: "0x3ecdbf3b911d0e9052b64850693888b008e18373,100", - }, - ], - totalCount: 1, - }, -}; - -export async function getAllTransactions(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/transaction/get-all", - schema: { - summary: "Get all transactions", - description: "Get all transaction requests.", - tags: ["Transaction"], - operationId: "listTransactions", - querystring: requestQuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { status, page, limit } = request.query; - - const { transactions, totalCount } = - await TransactionDB.getTransactionListByStatus({ - status, - page, - limit, - }); - - reply.status(StatusCodes.OK).send({ - result: { - transactions: transactions.map(toTransactionSchema), - totalCount, - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/retry-failed.ts b/src/server/routes/transaction/retry-failed.ts deleted file mode 100644 index cf42c54b4..000000000 --- a/src/server/routes/transaction/retry-failed.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { - getReceiptForEOATransaction, - getReceiptForUserOp, -} from "../../../shared/lib/transaction/get-transaction-receipt"; -import type { QueuedTransaction } from "../../../shared/utils/transaction/types"; -import { MineTransactionQueue } from "../../../worker/queues/mine-transaction-queue"; -import { SendTransactionQueue } from "../../../worker/queues/send-transaction-queue"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), -}); - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - message: Type.String(), - status: Type.String(), - }), -}); - -responseBodySchema.example = { - result: { - message: "Sent transaction to be retried.", - status: "success", - }, -}; - -export async function retryFailedTransactionRoute(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/transaction/retry-failed", - schema: { - summary: "Retry failed transaction", - description: "Retry a failed transaction", - tags: ["Transaction"], - operationId: "retryFailed", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { queueId } = request.body; - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - throw createCustomError( - "Transaction not found.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_FOUND", - ); - } - if (transaction.status !== "errored") { - throw createCustomError( - `Cannot retry a transaction with status ${transaction.status}.`, - StatusCodes.BAD_REQUEST, - "TRANSACTION_CANNOT_BE_RETRIED", - ); - } - - const receipt = transaction.isUserOp - ? await getReceiptForUserOp(transaction) - : await getReceiptForEOATransaction(transaction); - if (receipt) { - throw createCustomError( - "Cannot retry a transaction that is already mined.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_CANNOT_BE_RETRIED", - ); - } - - // Remove existing jobs. - const sendJob = await SendTransactionQueue.q.getJob( - SendTransactionQueue.jobId({ - queueId: transaction.queueId, - resendCount: 0, - }), - ); - await sendJob?.remove(); - - const mineJob = await MineTransactionQueue.q.getJob( - MineTransactionQueue.jobId({ - queueId: transaction.queueId, - }), - ); - await mineJob?.remove(); - - // Reset the failed job as "queued" and re-enqueue it. - const { errorMessage, ...omitted } = transaction; - const queuedTransaction: QueuedTransaction = { - ...omitted, - status: "queued", - queuedAt: new Date(), - resendCount: 0, - }; - await TransactionDB.set(queuedTransaction); - - await SendTransactionQueue.add({ - queueId: transaction.queueId, - resendCount: 0, - }); - - reply.status(StatusCodes.OK).send({ - result: { - message: "Sent transaction to be retried.", - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/retry.ts b/src/server/routes/transaction/retry.ts deleted file mode 100644 index 8d058a95e..000000000 --- a/src/server/routes/transaction/retry.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { maybeBigInt } from "../../../shared/utils/primitive-types"; -import type { SentTransaction } from "../../../shared/utils/transaction/types"; -import { SendTransactionQueue } from "../../../worker/queues/send-transaction-queue"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), - maxFeePerGas: Type.String(), - maxPriorityFeePerGas: Type.String(), -}); - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - message: Type.String(), - status: Type.String(), - }), -}); - -responseBodySchema.example = { - result: { - message: - "Transaction gas values updated for queueId: a20ed4ce-301d-4251-a7af-86bd88f6c015", - status: "success", - }, -}; - -export async function retryTransaction(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/transaction/retry", - schema: { - summary: "Retry transaction", - description: "Retry a transaction with updated gas settings.", - tags: ["Transaction"], - operationId: "retry", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - deprecated: true, - hide: true, - }, - handler: async (request, reply) => { - const { queueId, maxFeePerGas, maxPriorityFeePerGas } = request.body; - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - throw createCustomError( - "Transaction not found.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_FOUND", - ); - } - if (transaction.status !== "sent") { - throw createCustomError( - "Transaction cannot be retried.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_CANNOT_BE_RETRIED", - ); - } - - // Override the gas settings. - const sentTransaction: SentTransaction = { - ...transaction, - maxFeePerGas: maybeBigInt(maxFeePerGas), - maxPriorityFeePerGas: maybeBigInt(maxPriorityFeePerGas), - }; - await TransactionDB.set(sentTransaction); - await SendTransactionQueue.add({ - queueId: sentTransaction.queueId, - resendCount: sentTransaction.resendCount + 1, - }); - - reply.status(StatusCodes.OK).send({ - result: { - message: `Transaction gas values updated for queueId: ${queueId}`, - status: "success", - }, - }); - }, - }); -} diff --git a/src/server/routes/transaction/status.ts b/src/server/routes/transaction/status.ts deleted file mode 100644 index 60dcb18ba..000000000 --- a/src/server/routes/transaction/status.ts +++ /dev/null @@ -1,137 +0,0 @@ -import type { SocketStream } from "@fastify/websocket"; -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { logger } from "../../../shared/utils/logger"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { - TransactionSchema, - toTransactionSchema, -} from "../../schemas/transaction"; -import { - findOrAddWSConnectionInSharedState, - formatSocketMessage, - getStatusMessageAndConnectionStatus, - onClose, - onError, - onMessage, -} from "../../utils/websocket"; - -// INPUT -const requestSchema = Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), -}); - -// OUTPUT -export const responseBodySchema = Type.Object({ - result: TransactionSchema, -}); - -responseBodySchema.example = { - result: { - queueId: "a20ed4ce-301d-4251-a7af-86bd88f6c015", - walletAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - contractAddress: "0x365b83d67d5539c6583b9c0266a548926bf216f4", - chainId: "80001", - extension: "non-extension", - status: "mined", - encodedInputData: - "0xa9059cbb0000000000000000000000001946267d81fb8adeeea28e6b98bcd446c824847300000000000000000000000000000000000000000000000000000000000186a0", - txType: 2, - gasPrice: "1500000017", - gasLimit: "46512", - maxPriorityFeePerGas: "1500000000", - maxFeePerGas: "1500000034", - txHash: - "0x6de86da898fa4beb13d965c42bf331ad46cfa061cadf75f69791f31c9d8a4f66", - submittedTxNonce: 698, - createdTimestamp: "2023-08-25T22:42:26.910Z", - txProcessedTimestamp: "2023-08-25T22:42:27.302Z", - txSubmittedTimestamp: "2023-08-25T22:42:28.743Z", - deployedContractAddress: "", - contractType: "", - errorMessage: "", - txMinedTimestamp: "2023-08-25T22:42:33.000Z", - blockNumber: 39398545, - onChainTxStatus: 1, - }, -}; - -export async function checkTxStatus(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/transaction/status/:queueId", - schema: { - summary: "Get transaction status", - description: "Get the status for a transaction request.", - tags: ["Transaction"], - operationId: "status", - params: requestSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { queueId } = request.params; - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - throw createCustomError( - "Transaction not found.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_FOUND", - ); - } - - reply.status(StatusCodes.OK).send({ - result: toTransactionSchema(transaction), - }); - }, - wsHandler: async (connection: SocketStream, request) => { - const { queueId } = request.params; - - findOrAddWSConnectionInSharedState(connection, queueId, request); - - const transaction = await TransactionDB.get(queueId); - const returnData = transaction ? toTransactionSchema(transaction) : null; - - const { message, closeConnection } = - await getStatusMessageAndConnectionStatus(returnData); - - connection.socket.send(await formatSocketMessage(returnData, message)); - - if (closeConnection) { - connection.socket.close(); - return; - } - - connection.socket.on("error", (error) => { - logger({ - service: "websocket", - level: "error", - message: "Websocket error", - error, - }); - - onError(error, connection, request); - }); - - connection.socket.on("message", async (_message, _isBinary) => { - onMessage(connection, request); - }); - - connection.socket.on("close", () => { - onClose(connection, request); - }); - }, - }); -} diff --git a/src/server/routes/transaction/sync-retry.ts b/src/server/routes/transaction/sync-retry.ts deleted file mode 100644 index e212afc9a..000000000 --- a/src/server/routes/transaction/sync-retry.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { toSerializableTransaction } from "thirdweb"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { getReceiptForEOATransaction } from "../../../shared/lib/transaction/get-transaction-receipt"; -import { getAccount } from "../../../shared/utils/account"; -import { getBlockNumberish } from "../../../shared/utils/block"; -import { getChain } from "../../../shared/utils/chain"; -import { - getChecksumAddress, - maybeBigInt, -} from "../../../shared/utils/primitive-types"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import type { SentTransaction } from "../../../shared/utils/transaction/types"; -import { enqueueTransactionWebhook } from "../../../shared/utils/transaction/webhook"; -import { MineTransactionQueue } from "../../../worker/queues/mine-transaction-queue"; -import { createCustomError } from "../../middleware/error"; -import { TransactionHashSchema } from "../../schemas/address"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - queueId: Type.String({ - description: "Transaction queue ID", - examples: ["9eb88b00-f04f-409b-9df7-7dcc9003bc35"], - }), - maxFeePerGas: Type.Optional(Type.String()), - maxPriorityFeePerGas: Type.Optional(Type.String()), -}); - -export const responseBodySchema = Type.Object({ - result: Type.Object({ - transactionHash: TransactionHashSchema, - }), -}); - -responseBodySchema.example = { - result: { - transactionHash: - "0xc3b437073c164c33f95065fb325e9bc419f306cb39ae8b4ca233f33efaa74ead", - }, -}; - -export async function syncRetryTransactionRoute(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/transaction/sync-retry", - schema: { - summary: "Retry transaction (synchronous)", - description: - "Retry a transaction with updated gas settings. Blocks until the transaction is mined or errors.", - tags: ["Transaction"], - operationId: "syncRetry", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (request, reply) => { - const { queueId, maxFeePerGas, maxPriorityFeePerGas } = request.body; - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - throw createCustomError( - "Transaction not found.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_NOT_FOUND", - ); - } - - if (transaction.isUserOp || !("nonce" in transaction)) { - throw createCustomError( - "Transaction cannot be retried.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_CANNOT_BE_RETRIED", - ); - } - - const receipt = await getReceiptForEOATransaction(transaction); - if (receipt) { - throw createCustomError( - "Cannot retry a transaction that is already mined.", - StatusCodes.BAD_REQUEST, - "TRANSACTION_CANNOT_BE_RETRIED", - ); - } - - const { chainId, from } = transaction; - - // Prepare transaction. - const populatedTransaction = await toSerializableTransaction({ - from: getChecksumAddress(from), - transaction: { - client: thirdwebClient, - chain: await getChain(chainId), - ...transaction, - // Explicitly reuse the same nonce the transaction had previously acquired. - nonce: transaction.nonce, - maxFeePerGas: maybeBigInt(maxFeePerGas), - maxPriorityFeePerGas: maybeBigInt(maxPriorityFeePerGas), - }, - }); - - // Send transaction. - const account = await getAccount({ chainId, from }); - const { transactionHash } = - await account.sendTransaction(populatedTransaction); - - // Update state if the send was successful. - const sentTransaction: SentTransaction = { - ...transaction, - status: "sent", - resendCount: transaction.resendCount + 1, - sentAt: new Date(), - sentAtBlock: await getBlockNumberish(chainId), - sentTransactionHashes: [ - ...transaction.sentTransactionHashes, - transactionHash, - ], - gas: populatedTransaction.gas, - gasPrice: populatedTransaction.gasPrice, - maxFeePerGas: populatedTransaction.maxFeePerGas, - maxPriorityFeePerGas: populatedTransaction.maxPriorityFeePerGas, - }; - await TransactionDB.set(sentTransaction); - await MineTransactionQueue.add({ queueId: sentTransaction.queueId }); - await enqueueTransactionWebhook(sentTransaction); - - reply.status(StatusCodes.OK).send({ - result: { - transactionHash, - }, - }); - }, - }); -} diff --git a/src/server/routes/transactions/analytics.ts b/src/server/routes/transactions/analytics.ts new file mode 100644 index 000000000..4d59e45b6 --- /dev/null +++ b/src/server/routes/transactions/analytics.ts @@ -0,0 +1,382 @@ +import { type SQL, and, count, gte, lte, sql } from "drizzle-orm"; + +import { z } from "zod"; +import { + buildAdvancedFilters, + filterItemSchema, + filterOperationSchema, +} from "./filter.js"; + +import { + engineErrToHttpException, + mapDbError, + type ValidationErr, +} from "../../../lib/errors.js"; +import { transactions } from "../../../db/schema.js"; +import { describeRoute } from "hono-openapi"; +import { resolver, validator as zValidator } from "hono-openapi/zod"; +import { wrapResponseSchema } from "../../schemas/shared-api-schemas.js"; +import { ResultAsync } from "neverthrow"; +import { db } from "../../../db/connection.js"; +import { transactionsRoutesFactory } from "./factory.js"; + +function validateTimeRange( + startDate: Date, + endDate: Date, + resolution: TimeResolution, +): void { + const durationMs = endDate.getTime() - startDate.getTime(); + const maxDurations: Record = { + hour: 48 * 60 * 60 * 1000, // 48 hours + day: 90 * 24 * 60 * 60 * 1000, // 90 days + week: 52 * 7 * 24 * 60 * 60 * 1000, // 52 weeks + month: 24 * 30 * 24 * 60 * 60 * 1000, // ~24 months + }; + + if (durationMs > maxDurations[resolution]) { + // Create a ValidationErr for the time range validation + const error: ValidationErr = { + kind: "validation", + code: "parse_error", + status: 400, + message: `Time range too large for ${resolution} resolution. Maximum duration is ${maxDurations[resolution] / (1000 * 60 * 60 * 24)} days.`, + }; + + // Throw using the engineErrToHttpException helper + throw engineErrToHttpException(error); + } +} + +// Define the time resolution types +type TimeResolution = "hour" | "day" | "week" | "month"; + +// Create Zod schema for time resolution +const timeResolutionSchema = z.enum(["hour", "day", "week", "month"]); + +// Analytics request schema +const transactionsAnalyticsSchema = z.object({ + // Time range + startDate: z.string().datetime(), + endDate: z.string().datetime(), + resolution: timeResolutionSchema, + + // Filters (using the same pattern as search) + filters: z.array(filterItemSchema).optional(), + filtersOperation: filterOperationSchema.optional().default("AND"), +}); + +// Get appropriate time bucket SQL expression +function getTimeBucketExpression(resolution: TimeResolution): SQL { + switch (resolution) { + case "hour": + return sql`date_trunc('hour', ${transactions.createdAt})`; + case "day": + return sql`date_trunc('day', ${transactions.createdAt})`; + case "week": + return sql`date_trunc('week', ${transactions.createdAt})`; + case "month": + return sql`date_trunc('month', ${transactions.createdAt})`; + default: + throw new Error(`Unsupported resolution: ${resolution}`); + } +} + +export const analyticsHandler = transactionsRoutesFactory.createHandlers( + zValidator("json", transactionsAnalyticsSchema), + describeRoute({ + summary: "Transaction Analytics", + description: "Get transaction count analytics over time with filtering", + tags: ["Transactions"], + operationId: "getTransactionAnalytics", + responses: { + 200: { + description: "Transaction Analytics", + content: { + "application/json": { + schema: resolver( + wrapResponseSchema( + z.object({ + analytics: z.array( + z.object({ + timeBucket: z.string(), + chainId: z.string(), + count: z.number(), + }), + ), + metadata: z.object({ + resolution: timeResolutionSchema, + startDate: z.string(), + endDate: z.string(), + }), + }), + ), + ), + }, + }, + }, + // 400: { + // description: "Bad Request", + // content: { + // "application/json": { + // schema: errorResponseSchema, + // }, + // }, + // }, + }, + }), + async (c) => { + const params = c.req.valid("json"); + + // Parse dates + const startDate = new Date(params.startDate); + const endDate = new Date(params.endDate); + + // Validate time range based on resolution + validateTimeRange(startDate, endDate, params.resolution); + + // Create the time bucket expression based on resolution + const timeBucket = getTimeBucketExpression(params.resolution); + + // Build advanced filters if present + let filtersClause: SQL | undefined; + if (params.filters && params.filters.length > 0) { + filtersClause = buildAdvancedFilters( + params.filters, + params.filtersOperation, + ); + } + + // Build the complete where clause + const whereClause = [ + gte(transactions.createdAt, startDate), + lte(transactions.createdAt, endDate), + filtersClause, + ].filter(Boolean); + + // Execute query + const result = await ResultAsync.fromPromise( + db + .select({ + timeBucket: timeBucket, + chainId: transactions.chainId, + count: count(), + }) + .from(transactions) + .where(whereClause.length > 0 ? and(...whereClause) : undefined) + .groupBy(timeBucket, transactions.chainId) + .orderBy(timeBucket, transactions.chainId), + mapDbError, + ); + + if (result.isErr()) { + throw result.error; + } + + return c.json({ + result: { + analytics: result.value, + metadata: { + resolution: params.resolution, + startDate: startDate.toISOString(), + endDate: endDate.toISOString(), + }, + }, + }); + }, +); + +// Example usage: +/* +POST /transactions/analytics +{ + "startDate": "2023-01-01T00:00:00Z", + "endDate": "2023-01-31T23:59:59Z", + "resolution": "day", + "filters": [ + { + "field": "chainId", + "values": ["1", "137"], + "operation": "OR" + }, + { + "field": "signerAddress", + "values": ["0x1234..."], + "operation": "OR" + } + ], + "filtersOperation": "AND" +} +*/ + +// Schema for the request body - Allows nested filters +const analyticsSummaryRequestSchema = z.object({ + startDate: z + .string() + .datetime("Start date must be a valid ISO 8601 string") + .optional(), + endDate: z + .string() + .datetime("End date must be a valid ISO 8601 string") + .optional(), + filters: z.array(filterItemSchema).optional(), // Use filterItemSchema for nesting + filtersOperation: filterOperationSchema.optional().default("AND"), +}); + +// Schema for the successful response data +const analyticsSummarySuccessSchema = z.object({ + summary: z.object({ + totalCount: z + .number() + .int() + .min(0) + .describe("Total number of transactions matching the criteria."), + // Use string for potentially very large numbers from gas calculation sum + totalGasCostWei: z + .string() + .describe( + "Sum of actualGasCost (in wei) for all matching transactions, as a string.", + ), + // ADDED: Total gas units used + totalGasUnitsUsed: z + .string() + .describe( + "Sum of actualGasUsed (gas units) for all matching transactions, as a string.", + ), + }), + metadata: z.object({ + startDate: z.string().datetime().optional(), + endDate: z.string().datetime().optional(), + }), +}); + +// Schema for the final wrapped API response +const analyticsSummaryResponseSchema = wrapResponseSchema( + analyticsSummarySuccessSchema, +); + +// --- Route Handler --- + +export const analyticsSummaryHandler = transactionsRoutesFactory.createHandlers( + zValidator("json", analyticsSummaryRequestSchema), + describeRoute({ + summary: "Transaction Analytics Summary", + description: + "Get a summary (total count and total gas calculation) for transactions within a time range, supporting complex nested filters.", + tags: ["Transactions"], + operationId: "getTransactionAnalyticsSummary", + responses: { + 200: { + description: "Transaction Analytics Summary", + content: { + "application/json": { + schema: resolver(analyticsSummaryResponseSchema), + }, + }, + }, + 400: { + description: + "Bad Request (e.g., invalid date format, filter depth exceeded)", + }, + 500: { + description: "Internal Server Error (e.g., database error)", + }, + }, + }), + async (c) => { + const params = c.req.valid("json"); + + // Parse dates + const startDate = params.startDate ? new Date(params.startDate) : undefined; + const endDate = params.endDate ? new Date(params.endDate) : undefined; + + // --- Build Filters --- + let filtersClause: SQL | undefined; + try { + if (params.filters && params.filters.length > 0) { + // Use buildAdvancedFilters which handles nesting + filtersClause = buildAdvancedFilters( + params.filters, + params.filtersOperation, + // You can optionally pass maxDepth here if needed, otherwise it uses default + ); + } + } catch (error: any) { + // Handle potential maxDepth error from buildAdvancedFilters + // Assuming buildAdvancedFilters throws a standard Error + throw engineErrToHttpException({ + kind: "validation", + code: "filter_error", + status: 400, + message: error.message || "Failed to build filters.", + }); + } + + // Combine time range and advanced filters + const whereConditions = [ + startDate ? gte(transactions.createdAt, startDate) : undefined, + endDate ? lte(transactions.createdAt, endDate) : undefined, + filtersClause, // Add the potentially complex filter clause + ].filter((condition): condition is SQL => condition !== undefined); // Type guard and filter out undefined + + const finalWhereClause = + whereConditions.length > 0 ? and(...whereConditions) : undefined; + + // --- Database Query --- + // Sum of actualGasCost (wei) + const totalGasCostWeiSql = sql`SUM( + COALESCE(CAST(${transactions.executionResult}->>'actualGasCost' AS numeric), 0) + )`; + + // ADDED: Sum of actualGasUsed (units) + const totalGasUnitsUsedSql = sql`SUM( + COALESCE(CAST(${transactions.executionResult}->>'actualGasUsed' AS numeric), 0) + )`; + + const summaryResult = await ResultAsync.fromPromise( + db + .select({ + totalCount: count(), + totalGasCostWei: totalGasCostWeiSql, + // ADDED: Select the total gas units + totalGasUnitsUsed: totalGasUnitsUsedSql, + }) + .from(transactions) + .where(finalWhereClause) + .then((rows) => rows[0]), + mapDbError, + ); + + if (summaryResult.isErr()) { + throw engineErrToHttpException(summaryResult.error); + } + + const summaryData = summaryResult.value; + + // Handle nulls/undefined from SUM if no rows match + const totalGasCostWeiString = summaryData?.totalGasCostWei ?? "0"; + // ADDED: Handle null/undefined for gas units + const totalGasUnitsUsedString = summaryData?.totalGasUnitsUsed ?? "0"; + const totalCount = summaryData?.totalCount ?? 0; + + // --- Format Response --- + const responseMetadata: { startDate?: string; endDate?: string } = {}; + if (startDate) { + responseMetadata.startDate = startDate.toISOString(); + } + if (endDate) { + responseMetadata.endDate = endDate.toISOString(); + } + + return c.json({ + result: { + summary: { + totalCount: totalCount, + totalGasCostWei: totalGasCostWeiString, + // ADDED: Include total gas units in the response + totalGasUnitsUsed: totalGasUnitsUsedString, + }, + metadata: responseMetadata, + }, + }); + }, +); diff --git a/src/server/routes/transactions/factory.ts b/src/server/routes/transactions/factory.ts new file mode 100644 index 000000000..0eac7cf88 --- /dev/null +++ b/src/server/routes/transactions/factory.ts @@ -0,0 +1,3 @@ +import { createFactory } from "hono/factory"; + +export const transactionsRoutesFactory = createFactory(); diff --git a/src/server/routes/transactions/filter.ts b/src/server/routes/transactions/filter.ts new file mode 100644 index 000000000..24447b5bf --- /dev/null +++ b/src/server/routes/transactions/filter.ts @@ -0,0 +1,232 @@ +import { and, eq, or, type SQL, sql } from "drizzle-orm"; +import { getAddress } from "thirdweb"; +import { z } from "zod"; +import { transactions } from "../../../db/schema.js"; + +// Define filter operation type +type FilterOperation = "AND" | "OR"; + +// Define the supported filter fields +type FilterField = + | "id" + | "batchIndex" + | "from" + | "signerAddress" + | "smartAccountAddress" + | "chainId"; + +// Define filter value type +type FilterValue = { + field: FilterField; + values: string[]; + operation?: FilterOperation; +}; + +// Nested filter structure for combining multiple filters +type FilterNested = { + operation: FilterOperation; + filters: (FilterNested | FilterValue)[]; +}; + +// Type to represent a filter item which can be either a value filter or a nested filter +type FilterItem = FilterValue | FilterNested; + +/** + * Helper function to check if a filter item is a nested filter + */ +function isNestedFilter(filter: FilterItem): filter is FilterNested { + return "operation" in filter && "filters" in filter; +} + +/** + * Builds SQL filter conditions from a filter value + * + * @param filter - The filter value to process + * @returns SQL condition or undefined if invalid + */ +function buildValueFilter(filter: FilterValue): SQL | undefined { + if (!filter.values || filter.values.length === 0) return undefined; + + const operation = filter.operation || "OR"; // Default to OR for values within a filter + const conditions: SQL[] = []; + + for (const value of filter.values) { + switch (filter.field) { + case "id": + conditions.push(eq(transactions.id, value)); + break; + case "batchIndex": { + const batchIndex = Number.parseInt(value, 10); + if (!Number.isNaN(batchIndex)) { + conditions.push(eq(transactions.batchIndex, batchIndex)); + } + break; + } + case "from": + // TODO: use getAddressResult, and neverthrow-ify this function + conditions.push(eq(transactions.from, getAddress(value))); + break; + case "chainId": + conditions.push(eq(transactions.chainId, value)); + break; + case "signerAddress": + conditions.push( + sql`${transactions.executionParams}->>'signerAddress' = ${getAddress(value)}`, + ); + break; + case "smartAccountAddress": + conditions.push( + sql`${transactions.executionParams}->>'smartAccountAddress' = ${getAddress(value)}`, + ); + break; + } + } + + if (conditions.length > 0) { + return operation === "OR" ? or(...conditions) : and(...conditions); + } + + return undefined; +} + +/** + * Builds advanced SQL filters from filter objects, supporting nested filter structures + * + * @param filters - Array of filter items (value or nested) + * @param outerOperation - Operation to use when combining conditions (AND/OR) + * @param maxDepth - Maximum allowed nesting depth + * @param currentDepth - Current nesting depth (for internal use) + * @returns SQL condition or undefined if no valid filters + * @throws Error if nesting depth exceeds maxDepth + */ +function buildAdvancedFilters( + filters: FilterItem[], + outerOperation: FilterOperation = "AND", + maxDepth = 5, + currentDepth = 0, +): SQL | undefined { + if (currentDepth > maxDepth) { + throw new Error(`Maximum filter nesting depth of ${maxDepth} exceeded`); + } + + if (!filters || filters.length === 0) return undefined; + + const filterConditions: SQL[] = []; + + // Process value filters + const valueFilters = filters.filter( + (filter): filter is FilterValue => !isNestedFilter(filter), + ); + + if (valueFilters.length > 0) { + if (currentDepth === 0) { + // Group by field at top level (existing behavior) + const filtersByField: Record = { + id: [], + batchIndex: [], + from: [], + chainId: [], + signerAddress: [], + smartAccountAddress: [], + }; + + for (const filter of valueFilters) { + filtersByField[filter.field].push(filter); + } + + for (const [_field, fieldFilters] of Object.entries(filtersByField) as [ + FilterField, + FilterValue[], + ][]) { + if (fieldFilters.length === 0) continue; + + const fieldConditionGroups: SQL[] = []; + for (const filter of fieldFilters) { + const condition = buildValueFilter(filter); + if (condition) { + fieldConditionGroups.push(condition); + } + } + // Use AND for top-level grouping (or outerOperation if desired) + if (fieldConditionGroups.length > 0) { + const condition = and(...fieldConditionGroups); + if (condition) filterConditions.push(condition); + } + } + } else { + // Within a nested group, preserve order and use the nested outerOperation + for (const filter of valueFilters) { + const condition = buildValueFilter(filter); + if (condition) filterConditions.push(condition); + } + } + } + + // Process nested filters recursively + const nestedFilters = filters.filter(isNestedFilter); + for (const nestedFilter of nestedFilters) { + const nestedCondition = buildAdvancedFilters( + nestedFilter.filters, + nestedFilter.operation, + maxDepth, + currentDepth + 1, + ); + if (nestedCondition) { + filterConditions.push(nestedCondition); + } + } + + if (filterConditions.length > 0) { + return outerOperation === "OR" + ? or(...filterConditions) + : and(...filterConditions); + } + + return undefined; +} + +// Export Zod schemas for validation +export const filterOperationSchema = z.enum(["AND", "OR"]); + +export const filterValueSchema = z + .object({ + field: z.enum([ + "id", + "batchIndex", + "from", + "signerAddress", + "smartAccountAddress", + "chainId", + ]), + values: z.array(z.string()), + operation: filterOperationSchema.optional().default("OR"), + }) + .openapi({ + ref: "TransactionsFilterValue", + }); + +// Define schema for nested filters with recursive type +export const filterNestedSchema: z.ZodType = z + .lazy(() => + z.object({ + operation: filterOperationSchema, + filters: z.array(z.union([filterValueSchema, filterNestedSchema])), + }), + ) + .openapi({ + ref: "TransactionsFilterNested", + }); + +// Combined schema for filter items +export const filterItemSchema: z.ZodType = z.union([ + filterValueSchema, + filterNestedSchema, +]); + +export const searchFiltersSchema = z.object({ + filters: z.array(filterItemSchema).optional(), + filtersOperation: filterOperationSchema.optional().default("AND"), + maxDepth: z.number().int().positive().default(5), +}); + +export { buildAdvancedFilters }; diff --git a/src/server/routes/transactions/index.ts b/src/server/routes/transactions/index.ts new file mode 100644 index 000000000..dc0da25de --- /dev/null +++ b/src/server/routes/transactions/index.ts @@ -0,0 +1,10 @@ +import { Hono } from "hono"; +import { analyticsHandler, analyticsSummaryHandler } from "./analytics.js"; +import { getTransactionsHandler, searchTransactionsHandler } from "./search.js"; + +export const transactionsRoutes = new Hono(); + +transactionsRoutes.get("/", ...getTransactionsHandler); +transactionsRoutes.post("/analytics", ...analyticsHandler); +transactionsRoutes.post("/analytics-summary", ...analyticsSummaryHandler); +transactionsRoutes.post("/search", ...searchTransactionsHandler); diff --git a/src/server/routes/transactions/search.ts b/src/server/routes/transactions/search.ts new file mode 100644 index 000000000..bd3e06fc8 --- /dev/null +++ b/src/server/routes/transactions/search.ts @@ -0,0 +1,254 @@ +import { describeRoute } from "hono-openapi"; +import { resolver, validator as zValidator } from "hono-openapi/zod"; +import { ResultAsync } from "neverthrow"; +import { z } from "zod"; +import { db } from "../../../db/connection.js"; +import { mapDbError } from "../../../lib/errors.js"; +import { + wrapResponseSchema, + requestPaginationSchema, +} from "../../schemas/shared-api-schemas.js"; +import { transactionDbEntrySchema } from "../../../db/derived-schemas.js"; +import { and, asc, desc, eq, type SQL, sql } from "drizzle-orm"; +import { transactions as transactionsTable } from "../../../db/schema.js"; +import { evmAddressSchema } from "../../../lib/zod.js"; +import { + buildAdvancedFilters, + filterItemSchema, + filterOperationSchema, +} from "./filter.js"; +import { transactionsRoutesFactory } from "./factory.js"; + +const getTransactionsSchema = requestPaginationSchema.extend({ + // Search criteria + id: z.string().optional(), + batchIndex: z.number().optional(), + from: evmAddressSchema.optional(), + signerAddress: evmAddressSchema.optional(), + + // Sorting + sortBy: z.enum(["createdAt", "confirmedAt"]).default("createdAt"), + sortDirection: z.enum(["asc", "desc"]).default("desc"), +}); + +// transactionsRoutes.get( +// "/", +export const getTransactionsHandler = transactionsRoutesFactory.createHandlers( + zValidator("query", getTransactionsSchema), + describeRoute({ + summary: "Get Transactions", + description: "Search transactions with various filters and pagination", + tags: ["Transactions"], + operationId: "getTransactions", + responses: { + 200: { + description: "Transactions", + content: { + "application/json": { + schema: resolver( + wrapResponseSchema( + z.object({ + transactions: z.array(transactionDbEntrySchema), + pagination: z.object({ + totalCount: z.number(), + page: z.number(), + limit: z.number(), + }), + }), + ), + ), + }, + }, + }, + }, + }), + async (c) => { + const params = c.req.valid("query"); + const skip = (params.page - 1) * params.limit; + + // Build where conditions + const whereConditions = []; + + if (params.id) { + whereConditions.push(eq(transactionsTable.id, params.id)); + } + + if (params.batchIndex !== undefined) { + whereConditions.push(eq(transactionsTable.batchIndex, params.batchIndex)); + } + + if (params.from) { + whereConditions.push(eq(transactionsTable.from, params.from)); + } + + if (params.signerAddress) { + // Search in executionParams JSON for signerAddress + whereConditions.push( + sql`${transactionsTable.executionParams}->>'signerAddress' = ${params.signerAddress}`, + ); + } + + const baseQuery = { + where: whereConditions.length > 0 ? and(...whereConditions) : undefined, + orderBy: [ + params.sortBy === "createdAt" + ? params.sortDirection === "asc" + ? asc(transactionsTable.createdAt) + : desc(transactionsTable.createdAt) + : params.sortDirection === "asc" + ? asc(transactionsTable.confirmedAt) + : desc(transactionsTable.confirmedAt), + ], + }; + + const combined = await ResultAsync.combine([ + ResultAsync.fromPromise( + db.query.transactions.findMany({ + ...baseQuery, + offset: skip, + limit: params.limit, + }), + mapDbError, + ), + ResultAsync.fromPromise( + db + .select({ count: sql`count(*)` }) + .from(transactionsTable) + .where(baseQuery.where || undefined) + .then((rows) => rows[0]?.count || 0), + mapDbError, + ), + ]); + + if (combined.isErr()) { + throw combined.error; + } + + const [txns, totalCount] = combined.value; + + return c.json({ + result: { + transactions: txns, + pagination: { + totalCount, + page: params.page, + limit: params.limit, + }, + }, + }); + }, +); + +// Advanced search: + +// Advanced search schema accepts nested filters using filterItemSchema +const searchTransactionsBodySchema = z.object({ + // Pagination + page: z.number().int().positive().default(1), + limit: z.number().int().positive().max(100).default(20), + + // Filters: simple and nested filters are allowed. + filters: z.array(filterItemSchema).optional(), + filtersOperation: filterOperationSchema.optional().default("AND"), + + // Sorting + sortBy: z.enum(["createdAt", "confirmedAt"]).default("createdAt"), + sortDirection: z.enum(["asc", "desc"]).default("desc"), +}); + +// Add the search endpoint that supports nested filters. +export const searchTransactionsHandler = + transactionsRoutesFactory.createHandlers( + zValidator("json", searchTransactionsBodySchema), + describeRoute({ + summary: "Search Transactions", + description: + "Advanced search for transactions with complex nested filters", + tags: ["Transactions"], + operationId: "searchTransactions", + responses: { + 200: { + description: "Transactions", + content: { + "application/json": { + schema: resolver( + wrapResponseSchema( + z.object({ + transactions: z.array(transactionDbEntrySchema), + pagination: z.object({ + totalCount: z.number(), + page: z.number(), + limit: z.number(), + }), + }), + ), + ), + }, + }, + }, + }, + }), + async (c) => { + const params = c.req.valid("json"); + const skip = (params.page - 1) * params.limit; + + // Process the advanced filters if provided. + // buildAdvancedFilters will handle nested filters recursively, using an internal default maxDepth. + let whereClause: SQL | undefined; + if (params.filters && params.filters.length > 0) { + whereClause = buildAdvancedFilters( + params.filters, + params.filtersOperation, + ); + } + + const baseQuery = { + where: whereClause, + orderBy: [ + params.sortBy === "createdAt" + ? params.sortDirection === "asc" + ? asc(transactionsTable.createdAt) + : desc(transactionsTable.createdAt) + : params.sortDirection === "asc" + ? asc(transactionsTable.confirmedAt) + : desc(transactionsTable.confirmedAt), + ], + }; + + const combined = await ResultAsync.combine([ + ResultAsync.fromPromise( + db.query.transactions.findMany({ + ...baseQuery, + offset: skip, + limit: params.limit, + }), + mapDbError, + ), + ResultAsync.fromPromise( + db + .select({ count: sql`count(*)` }) + .from(transactionsTable) + .where(baseQuery.where || undefined) + .then((rows) => rows[0]?.count || 0), + mapDbError, + ), + ]); + + if (combined.isErr()) { + throw combined.error; + } + + const [txns, totalCount] = combined.value; + + return c.json({ + result: { + transactions: txns, + pagination: { + totalCount, + page: params.page, + limit: params.limit, + }, + }, + }); + }, + ); diff --git a/src/server/routes/wallet-credentials/create.ts b/src/server/routes/wallet-credentials/create.ts deleted file mode 100644 index 5afbffc93..000000000 --- a/src/server/routes/wallet-credentials/create.ts +++ /dev/null @@ -1,103 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { createWalletCredential } from "../../../shared/db/wallet-credentials/create-wallet-credential"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { type Static, Type } from "@sinclair/typebox"; -import { WalletCredentialsError } from "../../../shared/db/wallet-credentials/get-wallet-credential"; -import { createCustomError } from "../../middleware/error"; - -const requestBodySchema = Type.Object({ - label: Type.String(), - type: Type.Literal("circle"), - entitySecret: Type.String({ - description: - "32-byte hex string. Consult https://developers.circle.com/w3s/entity-secret-management to create and register an entity secret.", - pattern: "^[0-9a-fA-F]{64}$", - }), - isDefault: Type.Optional( - Type.Boolean({ - description: - "Whether this credential should be set as the default for its type. Only one credential can be default per type.", - default: false, - }), - ), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - id: Type.String(), - type: Type.String(), - label: Type.String(), - isDefault: Type.Union([Type.Boolean(), Type.Null()]), - createdAt: Type.String(), - updatedAt: Type.String(), - }), -}); - -responseSchema.example = { - result: { - id: "123e4567-e89b-12d3-a456-426614174000", - type: "circle", - label: "My Circle Credential", - isDefault: false, - createdAt: "2024-01-01T00:00:00.000Z", - updatedAt: "2024-01-01T00:00:00.000Z", - }, -}; - -export const createWalletCredentialRoute = async (fastify: FastifyInstance) => { - fastify.withTypeProvider().route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/wallet-credentials", - schema: { - summary: "Create wallet credentials", - description: "Create a new set of wallet credentials.", - tags: ["Wallet Credentials"], - operationId: "createWalletCredential", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - const { label, type, entitySecret, isDefault } = req.body; - - let createdWalletCredential: Awaited< - ReturnType - > | null = null; - - try { - createdWalletCredential = await createWalletCredential({ - type, - label, - entitySecret, - isDefault, - }); - - reply.status(StatusCodes.OK).send({ - result: { - id: createdWalletCredential.id, - type: createdWalletCredential.type, - label: createdWalletCredential.label, - isDefault: createdWalletCredential.isDefault, - createdAt: createdWalletCredential.createdAt.toISOString(), - updatedAt: createdWalletCredential.updatedAt.toISOString(), - }, - }); - } catch (e: unknown) { - if (e instanceof WalletCredentialsError) { - throw createCustomError( - e.message, - StatusCodes.BAD_REQUEST, - "WALLET_CREDENTIAL_ERROR", - ); - } - throw e; - } - }, - }); -}; diff --git a/src/server/routes/wallet-credentials/get-all.ts b/src/server/routes/wallet-credentials/get-all.ts deleted file mode 100644 index f7a48a654..000000000 --- a/src/server/routes/wallet-credentials/get-all.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAllWalletCredentials } from "../../../shared/db/wallet-credentials/get-all-wallet-credentials"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { PaginationSchema } from "../../schemas/pagination"; - -const QuerySchema = PaginationSchema; - -const responseSchema = Type.Object({ - result: Type.Array( - Type.Object({ - id: Type.String(), - type: Type.String(), - label: Type.Union([Type.String(), Type.Null()]), - isDefault: Type.Union([Type.Boolean(), Type.Null()]), - createdAt: Type.String(), - updatedAt: Type.String(), - }), - ), -}); - -responseSchema.example = { - result: [ - { - id: "123e4567-e89b-12d3-a456-426614174000", - type: "circle", - label: "My Circle Credential", - isDefault: false, - createdAt: "2024-01-01T00:00:00.000Z", - updatedAt: "2024-01-01T00:00:00.000Z", - deletedAt: null, - }, - ], -}; - -export async function getAllWalletCredentialsRoute(fastify: FastifyInstance) { - fastify.route<{ - Querystring: Static; - Reply: Static; - }>({ - method: "GET", - url: "/wallet-credentials", - schema: { - summary: "Get all wallet credentials", - description: "Get all wallet credentials with pagination.", - tags: ["Wallet Credentials"], - operationId: "getAllWalletCredentials", - querystring: QuerySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, res) => { - const credentials = await getAllWalletCredentials({ - page: req.query.page, - limit: req.query.limit, - }); - - res.status(StatusCodes.OK).send({ - result: credentials.map((cred) => ({ - ...cred, - createdAt: cred.createdAt.toISOString(), - updatedAt: cred.updatedAt.toISOString(), - })), - }); - }, - }); -} diff --git a/src/server/routes/wallet-credentials/get.ts b/src/server/routes/wallet-credentials/get.ts deleted file mode 100644 index f132c08a7..000000000 --- a/src/server/routes/wallet-credentials/get.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { - getWalletCredential, - WalletCredentialsError, -} from "../../../shared/db/wallet-credentials/get-wallet-credential"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const ParamsSchema = Type.Object({ - id: Type.String({ - description: "The ID of the wallet credential to get.", - }), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - id: Type.String(), - type: Type.String(), - label: Type.Union([Type.String(), Type.Null()]), - isDefault: Type.Union([Type.Boolean(), Type.Null()]), - createdAt: Type.String(), - updatedAt: Type.String(), - deletedAt: Type.Union([Type.String(), Type.Null()]), - }), -}); - -responseSchema.example = { - result: { - id: "123e4567-e89b-12d3-a456-426614174000", - type: "circle", - label: "My Circle Credential", - isDefault: false, - createdAt: "2024-01-01T00:00:00.000Z", - updatedAt: "2024-01-01T00:00:00.000Z", - deletedAt: null, - }, -}; - -export async function getWalletCredentialRoute(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "GET", - url: "/wallet-credentials/:id", - schema: { - summary: "Get wallet credential", - description: "Get a wallet credential by ID.", - tags: ["Wallet Credentials"], - operationId: "getWalletCredential", - params: ParamsSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - try { - const credential = await getWalletCredential({ - id: req.params.id, - }); - - reply.status(StatusCodes.OK).send({ - result: { - id: credential.id, - type: credential.type, - label: credential.label, - isDefault: credential.isDefault, - createdAt: credential.createdAt.toISOString(), - updatedAt: credential.updatedAt.toISOString(), - deletedAt: credential.deletedAt?.toISOString() || null, - }, - }); - } catch (e) { - if (e instanceof WalletCredentialsError) { - throw createCustomError( - e.message, - StatusCodes.NOT_FOUND, - "WALLET_CREDENTIAL_NOT_FOUND", - ); - } - throw e; - } - }, - }); -} diff --git a/src/server/routes/wallet-credentials/update.ts b/src/server/routes/wallet-credentials/update.ts deleted file mode 100644 index e7a4eb500..000000000 --- a/src/server/routes/wallet-credentials/update.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { updateWalletCredential } from "../../../shared/db/wallet-credentials/update-wallet-credential"; -import { WalletCredentialsError } from "../../../shared/db/wallet-credentials/get-wallet-credential"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const ParamsSchema = Type.Object({ - id: Type.String({ - description: "The ID of the wallet credential to update.", - }), -}); - -const requestBodySchema = Type.Object({ - label: Type.Optional(Type.String()), - isDefault: Type.Optional( - Type.Boolean({ - description: - "Whether this credential should be set as the default for its type. Only one credential can be default per type.", - }), - ), - entitySecret: Type.Optional( - Type.String({ - description: - "32-byte hex string. Consult https://developers.circle.com/w3s/entity-secret-management to create and register an entity secret.", - pattern: "^[0-9a-fA-F]{64}$", - }), - ), -}); - -const responseSchema = Type.Object({ - result: Type.Object({ - id: Type.String(), - type: Type.String(), - label: Type.Union([Type.String(), Type.Null()]), - isDefault: Type.Union([Type.Boolean(), Type.Null()]), - createdAt: Type.String(), - updatedAt: Type.String(), - }), -}); - -responseSchema.example = { - result: { - id: "123e4567-e89b-12d3-a456-426614174000", - type: "circle", - label: "My Updated Circle Credential", - isDefault: true, - createdAt: "2024-01-01T00:00:00.000Z", - updatedAt: "2024-01-01T00:00:00.000Z", - }, -}; - -export async function updateWalletCredentialRoute(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Body: Static; - Reply: Static; - }>({ - method: "PUT", - url: "/wallet-credentials/:id", - schema: { - summary: "Update wallet credential", - description: - "Update a wallet credential's label, default status, and entity secret.", - tags: ["Wallet Credentials"], - operationId: "updateWalletCredential", - params: ParamsSchema, - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseSchema, - }, - }, - handler: async (req, reply) => { - try { - const credential = await updateWalletCredential({ - id: req.params.id, - label: req.body.label, - isDefault: req.body.isDefault, - entitySecret: req.body.entitySecret, - }); - - reply.status(StatusCodes.OK).send({ - result: { - id: credential.id, - type: credential.type, - label: credential.label, - isDefault: credential.isDefault, - createdAt: credential.createdAt.toISOString(), - updatedAt: credential.updatedAt.toISOString(), - }, - }); - } catch (e) { - if (e instanceof WalletCredentialsError) { - throw createCustomError( - e.message, - StatusCodes.NOT_FOUND, - "WALLET_CREDENTIAL_NOT_FOUND", - ); - } - throw e; - } - }, - }); -} diff --git a/src/server/routes/webhooks/create.ts b/src/server/routes/webhooks/create.ts deleted file mode 100644 index a45e66a00..000000000 --- a/src/server/routes/webhooks/create.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { insertWebhook } from "../../../shared/db/webhooks/create-webhook"; -import { WebhooksEventTypes } from "../../../shared/schemas/webhooks"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { WebhookSchema, toWebhookSchema } from "../../schemas/webhook"; -import { isValidWebhookUrl } from "../../utils/validator"; - -const requestBodySchema = Type.Object({ - url: Type.String({ - description: "Webhook URL. Non-HTTPS URLs are not supported.", - examples: ["https://example.com/webhook"], - }), - name: Type.Optional( - Type.String({ - minLength: 3, - }), - ), - eventType: Type.Enum(WebhooksEventTypes), -}); - -requestBodySchema.examples = [ - { - url: "https://example.com/webhook", - name: "Notify of transaction updates", - secret: "...", - eventType: WebhooksEventTypes.ALL_TX, - active: true, - createdAt: "2024-10-02T02:07:27.255Z", - id: 42, - }, -]; - -const responseBodySchema = Type.Object({ - result: WebhookSchema, -}); - -export async function createWebhookRoute(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/webhooks/create", - schema: { - summary: "Create webhook", - description: - "Create a webhook to call when a specific Engine event occurs.", - tags: ["Webhooks"], - operationId: "createWebhook", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { url, name, eventType } = req.body; - - if (!isValidWebhookUrl(url)) { - throw createCustomError( - "Invalid webhook URL. Make sure it starts with 'https://'.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const webhook = await insertWebhook({ - url, - name, - eventType, - }); - - res.status(StatusCodes.OK).send({ - result: toWebhookSchema(webhook), - }); - }, - }); -} diff --git a/src/server/routes/webhooks/events.ts b/src/server/routes/webhooks/events.ts deleted file mode 100644 index 05feda3a1..000000000 --- a/src/server/routes/webhooks/events.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { WebhooksEventTypes } from "../../../shared/schemas/webhooks"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -export const responseBodySchema = Type.Object({ - result: Type.Array(Type.Enum(WebhooksEventTypes)), -}); - -export async function getWebhooksEventTypes(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/webhooks/event-types", - schema: { - summary: "Get webhooks event types", - description: "Get the all the webhooks event types", - tags: ["Webhooks"], - operationId: "getEventTypes", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const eventTypesArray = Object.values(WebhooksEventTypes); - res.status(StatusCodes.OK).send({ - result: eventTypesArray, - }); - }, - }); -} diff --git a/src/server/routes/webhooks/get-all.ts b/src/server/routes/webhooks/get-all.ts deleted file mode 100644 index a77db4c57..000000000 --- a/src/server/routes/webhooks/get-all.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getAllWebhooks } from "../../../shared/db/webhooks/get-all-webhooks"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import { WebhookSchema, toWebhookSchema } from "../../schemas/webhook"; - -const responseBodySchema = Type.Object({ - result: Type.Array(WebhookSchema), -}); - -export async function getAllWebhooksData(fastify: FastifyInstance) { - fastify.route<{ - Reply: Static; - }>({ - method: "GET", - url: "/webhooks/get-all", - schema: { - summary: "Get all webhooks configured", - description: "Get all webhooks configuration data set up on Engine", - tags: ["Webhooks"], - operationId: "listWebhooks", - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (_req, res) => { - const webhooks = await getAllWebhooks(); - - res.status(StatusCodes.OK).send({ - result: webhooks.map(toWebhookSchema), - }); - }, - }); -} diff --git a/src/server/routes/webhooks/revoke.ts b/src/server/routes/webhooks/revoke.ts deleted file mode 100644 index 6e38245de..000000000 --- a/src/server/routes/webhooks/revoke.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getWebhook } from "../../../shared/db/webhooks/get-webhook"; -import { deleteWebhook } from "../../../shared/db/webhooks/revoke-webhook"; -import { createCustomError } from "../../middleware/error"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; - -const requestBodySchema = Type.Object({ - id: Type.Integer({ minimum: 0 }), -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean(), - }), -}); - -export async function revokeWebhook(fastify: FastifyInstance) { - fastify.route<{ - Body: Static; - Reply: Static; - }>({ - method: "POST", - url: "/webhooks/revoke", - schema: { - summary: "Revoke webhook", - description: "Revoke a Webhook", - tags: ["Webhooks"], - operationId: "revoke", - body: requestBodySchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { id } = req.body; - - const webhook = await getWebhook(id); - if (!webhook) { - throw createCustomError( - "Webhook not found.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - await deleteWebhook(id); - - res.status(StatusCodes.OK).send({ - result: { - success: true, - }, - }); - }, - }); -} diff --git a/src/server/routes/webhooks/test.ts b/src/server/routes/webhooks/test.ts deleted file mode 100644 index 868f21ebc..000000000 --- a/src/server/routes/webhooks/test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { FastifyInstance } from "fastify"; -import { StatusCodes } from "http-status-codes"; -import { getWebhook } from "../../../shared/db/webhooks/get-webhook"; -import { sendWebhookRequest } from "../../../shared/utils/webhook"; -import { createCustomError } from "../../middleware/error"; -import { NumberStringSchema } from "../../schemas/number"; -import { standardResponseSchema } from "../../schemas/shared-api-schemas"; -import type { TransactionSchema } from "../../schemas/transaction"; - -const paramsSchema = Type.Object({ - webhookId: NumberStringSchema, -}); - -const responseBodySchema = Type.Object({ - result: Type.Object({ - ok: Type.Boolean(), - status: Type.Number(), - body: Type.String(), - }), -}); - -export async function testWebhookRoute(fastify: FastifyInstance) { - fastify.route<{ - Params: Static; - Reply: Static; - }>({ - method: "POST", - url: "/webhooks/:webhookId/test", - schema: { - summary: "Test webhook", - description: "Send a test payload to a webhook.", - tags: ["Webhooks"], - operationId: "testWebhook", - params: paramsSchema, - response: { - ...standardResponseSchema, - [StatusCodes.OK]: responseBodySchema, - }, - }, - handler: async (req, res) => { - const { webhookId } = req.params; - - const webhook = await getWebhook(Number.parseInt(webhookId)); - if (!webhook) { - throw createCustomError( - "Webhook not found.", - StatusCodes.BAD_REQUEST, - "NOT_FOUND", - ); - } - - const webhookBody: Static = { - // Queue details - queueId: "1411246e-b1c8-4f5d-9a25-8c1f40b54e55", - status: "mined", - onchainStatus: "success", - queuedAt: "2023-09-29T22:01:31.031Z", - sentAt: "2023-09-29T22:01:41.580Z", - minedAt: "2023-09-29T22:01:44.000Z", - errorMessage: null, - cancelledAt: null, - retryCount: 0, - - // Onchain details - chainId: "80002", - fromAddress: "0x3ecdbf3b911d0e9052b64850693888b008e18373", - toAddress: "0x365b83d67d5539c6583b9c0266a548926bf216f4", - data: "0xa9059cbb0000000000000000000000003ecdbf3b911d0e9052b64850693888b008e183730000000000000000000000000000000000000000000000000000000000000064", - value: "0x00", - nonce: 1786, - gasLimit: "39580", - maxFeePerGas: "2063100466", - maxPriorityFeePerGas: "1875545856", - gasPrice: "1875545871", - transactionType: 2, - transactionHash: - "0xc3ffa42dd4734b017d483e1158a2e936c8a97dd1aa4e4ce11df80ac8e81d2c7e", - sentAtBlockNumber: 40660021, - blockNumber: 40660026, - - // User operation (account abstraction) details - signerAddress: null, - accountAddress: null, - accountFactoryAddress: null, - target: null, - sender: null, - initCode: null, - callData: null, - callGasLimit: null, - verificationGasLimit: null, - preVerificationGas: null, - paymasterAndData: null, - userOpHash: null, - accountSalt: null, - batchOperations: null, - - // Off-chain details - functionName: "transfer", - functionArgs: "0x3ecdbf3b911d0e9052b64850693888b008e18373,100", - extension: "none", - deployedContractAddress: null, - deployedContractType: null, - - // Deprecated - retryGasValues: null, - retryMaxFeePerGas: null, - retryMaxPriorityFeePerGas: null, - effectiveGasPrice: null, - cumulativeGasUsed: null, - onChainTxStatus: 1, - }; - - const resp = await sendWebhookRequest(webhook, webhookBody); - - res.status(StatusCodes.OK).send({ - result: resp, - }); - }, - }); -} diff --git a/src/server/schemas/account/index.ts b/src/server/schemas/account/index.ts deleted file mode 100644 index 65e01875a..000000000 --- a/src/server/schemas/account/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { AddressSchema } from "../address"; - -export const sessionSchema = Type.Object({ - signerAddress: AddressSchema, - startDate: Type.String(), - expirationDate: Type.String(), - nativeTokenLimitPerTransaction: Type.String(), - approvedCallTargets: Type.Array(Type.String()), -}); diff --git a/src/server/schemas/address.ts b/src/server/schemas/address.ts deleted file mode 100644 index c7006f999..000000000 --- a/src/server/schemas/address.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Type } from "@sinclair/typebox"; - -/** - * An EVM address schema. Override the description like this: - * - * ```typescript - * to: { - * ...AddressSchema, - * description: "The recipient wallet address.", - * }, - * ``` - */ -export const AddressSchema = Type.RegExp(/^0x[a-fA-F0-9]{40}$/, { - description: "A contract or wallet address", - examples: ["0x000000000000000000000000000000000000dead"], -}); - -export const TransactionHashSchema = Type.RegExp(/^0x[a-fA-F0-9]{64}$/, { - description: "A transaction hash", - examples: [ - "0x1f31b57601a6f90312fd5e57a2924bc8333477de579ee37b197a0681ab438431", - ], -}); - -export const HexSchema = Type.RegExp(/^0x[a-fA-F0-9]*$/, { - description: "A valid hex string", - examples: ["0x68656c6c6f20776f726c64"], -}); diff --git a/src/server/schemas/chain/index.ts b/src/server/schemas/chain/index.ts deleted file mode 100644 index eb4a1fab5..000000000 --- a/src/server/schemas/chain/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Type } from "@sinclair/typebox"; - -export const chainIdOrSlugSchema = Type.RegExp(/^[\w-]{1,50}$/, { - description: `A chain ID ("137") or slug ("polygon-amoy-testnet"). Chain ID is preferred.`, - examples: ["80002"], -}); - -export const chainRequestQuerystringSchema = Type.Object({ - chain: chainIdOrSlugSchema, -}); - -export const chainResponseSchema = Type.Partial( - Type.Object({ - name: Type.String({ - description: "Chain name", - }), - chain: Type.String({ - description: "Chain name", - }), - rpc: Type.Array( - Type.String({ - description: "RPC URL", - }), - ), - nativeCurrency: Type.Object({ - name: Type.String({ - description: "Native currency name", - }), - symbol: Type.String({ - description: "Native currency symbol", - }), - decimals: Type.Number({ - description: "Native currency decimals", - }), - }), - shortName: Type.String({ - description: "Chain short name", - }), - chainId: Type.Integer({ - description: "Chain ID", - }), - testnet: Type.Boolean({ - description: "Is testnet", - }), - slug: Type.String({ - description: "Chain slug", - }), - }), -); diff --git a/src/server/schemas/claim-conditions/index.ts b/src/server/schemas/claim-conditions/index.ts deleted file mode 100644 index 11b867a10..000000000 --- a/src/server/schemas/claim-conditions/index.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { AddressSchema } from "../address"; -import { currencyValueSchema } from "../shared-api-schemas"; - -export const claimConditionInputSchema = Type.Object({ - maxClaimableSupply: Type.Optional( - Type.Union([Type.String(), Type.Integer({ minimum: 0 })]), - ), - startTime: Type.Optional( - Type.Union([ - Type.String({ - format: "date-time", - }), - Type.Integer({ minimum: 0 }), - ]), - ), - price: Type.Optional(Type.Union([Type.Number(), Type.String()])), - currencyAddress: Type.Optional(AddressSchema), - maxClaimablePerWallet: Type.Optional( - Type.Union([Type.Integer({ minimum: 0 }), Type.String()]), - ), - waitInSeconds: Type.Optional( - Type.Union([Type.Integer({ minimum: 0 }), Type.String()]), - ), - merkleRootHash: Type.Optional( - Type.Union([Type.String(), Type.Array(Type.Number())]), - ), - metadata: Type.Optional( - Type.Object({ - name: Type.Optional(Type.String()), - }), - ), - snapshot: Type.Optional( - Type.Union([ - Type.Array(Type.String()), - Type.Array( - Type.Object({ - price: Type.Optional(Type.Union([Type.String(), Type.Number()])), - currencyAddress: Type.Optional(AddressSchema), - address: AddressSchema, - maxClaimable: Type.Optional( - Type.Union([Type.String(), Type.Integer({ minimum: 0 })]), - ), - }), - ), - Type.Null(), - ]), - ), -}); - -export const sanitizedClaimConditionInputSchema = Type.Object({ - ...claimConditionInputSchema.properties, - startTime: Type.Optional( - Type.Union([Type.Date(), Type.Integer({ minimum: 0 })]), - ), -}); - -export const claimConditionOutputSchema = Type.Object({ - maxClaimableSupply: Type.Optional( - Type.Union([Type.String(), Type.Integer({ minimum: 0 })]), - ), - startTime: Type.String({ - format: "date-time", - }), - price: Type.Optional(Type.Union([Type.Number(), Type.String()])), - currencyAddress: Type.Optional(AddressSchema), - maxClaimablePerWallet: Type.Optional( - Type.Union([Type.Integer({ minimum: 0 }), Type.String()]), - ), - waitInSeconds: Type.Optional( - Type.Union([Type.Integer({ minimum: 0 }), Type.String()]), - ), - merkleRootHash: Type.Union([Type.String(), Type.Array(Type.Number())]), - availableSupply: Type.String(), - currentMintSupply: Type.String(), - currencyMetadata: currencyValueSchema, - metadata: Type.Optional( - Type.Object({ - name: Type.Optional(Type.String()), - }), - ), - snapshot: Type.Optional( - Type.Union([ - Type.Null(), - Type.Array(Type.String()), - Type.Array( - Type.Object({ - price: Type.Optional(Type.Union([Type.String(), Type.Number()])), - currencyAddress: Type.Optional(AddressSchema), - address: AddressSchema, - maxClaimable: Type.Optional( - Type.Union([Type.String(), Type.Integer({ minimum: 0 })]), - ), - }), - ), - ]), - ), -}); - -export const claimerProofSchema = Type.Union([ - Type.Null(), - Type.Object({ - price: Type.Optional(Type.String()), - currencyAddress: Type.Optional(AddressSchema), - address: AddressSchema, - maxClaimable: Type.String(), - proof: Type.Array(Type.String()), - }), -]); - -export const setBatchSantiziedClaimConditionsRequestSchema = Type.Object({ - claimConditionsForToken: Type.Array( - Type.Object({ - tokenId: Type.Union([Type.String(), Type.Integer()], { - description: "ID of the token to set the claim conditions for", - }), - claimConditions: Type.Array(sanitizedClaimConditionInputSchema), - }), - ), - resetClaimEligibilityForAll: Type.Optional(Type.Boolean()), -}); diff --git a/src/server/schemas/contract-subscription.ts b/src/server/schemas/contract-subscription.ts deleted file mode 100644 index fc7939f72..000000000 --- a/src/server/schemas/contract-subscription.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { ContractSubscriptions, Webhooks } from "@prisma/client"; -import { Type, type Static } from "@sinclair/typebox"; -import { AddressSchema } from "./address"; -import { WebhookSchema, toWebhookSchema } from "./webhook"; - -export const contractSubscriptionSchema = Type.Object({ - id: Type.String(), - chainId: Type.Integer(), - contractAddress: AddressSchema, - webhook: Type.Optional(WebhookSchema), - processEventLogs: Type.Boolean(), - filterEvents: Type.Array(Type.String()), - processTransactionReceipts: Type.Boolean(), - filterFunctions: Type.Array(Type.String()), - createdAt: Type.Unsafe({ - type: "string", - format: "date", - }), -}); - -export const toContractSubscriptionSchema = ( - contractSubscription: ContractSubscriptions & { webhook: Webhooks | null }, -): Static => ({ - id: contractSubscription.id, - chainId: Number.parseInt(contractSubscription.chainId), - contractAddress: contractSubscription.contractAddress, - webhook: contractSubscription.webhook - ? toWebhookSchema(contractSubscription.webhook) - : undefined, - processEventLogs: contractSubscription.processEventLogs, - filterEvents: contractSubscription.filterEvents, - processTransactionReceipts: contractSubscription.processTransactionReceipts, - filterFunctions: contractSubscription.filterFunctions, - createdAt: contractSubscription.createdAt, -}); diff --git a/src/server/schemas/contract/index.ts b/src/server/schemas/contract/index.ts deleted file mode 100644 index dea203627..000000000 --- a/src/server/schemas/contract/index.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { AddressSchema } from "../address"; -import type { contractSchemaTypes } from "../shared-api-schemas"; - -/** - * Basic schema for all Request Query String - */ -export const readRequestQuerySchema = Type.Object({ - functionName: Type.String({ - description: "Name of the function to call on Contract", - examples: ["balanceOf"], - }), - args: Type.Optional( - Type.String({ - description: "Arguments for the function. Comma Separated", - examples: [""], - }), - ), -}); - -export interface readSchema extends contractSchemaTypes { - Querystring: Static; -} - -const abiTypeSchema = Type.Object({ - type: Type.Optional(Type.String()), - name: Type.Optional(Type.String()), - internalType: Type.Optional(Type.String()), - stateMutability: Type.Optional(Type.String()), - components: Type.Optional( - Type.Array( - Type.Object({ - type: Type.Optional(Type.String()), - name: Type.Optional(Type.String()), - internalType: Type.Optional(Type.String()), - }), - ), - ), -}); - -export const abiFunctionSchema = Type.Object({ - name: Type.String(), - inputs: Type.Array(abiTypeSchema), - outputs: Type.Array(abiTypeSchema), - comment: Type.Optional(Type.String()), - signature: Type.String(), - stateMutability: Type.String(), -}); - -export const abiEventSchema = Type.Object({ - name: Type.String(), - inputs: Type.Array(abiTypeSchema), - outputs: Type.Array(abiTypeSchema), - comment: Type.Optional(Type.String()), -}); - -export const abiSchema = Type.Object({ - type: Type.String(), - name: Type.Optional(Type.String()), - inputs: Type.Optional(Type.Array(abiTypeSchema)), - outputs: Type.Optional(Type.Array(abiTypeSchema)), - stateMutability: Type.Optional(Type.String()), -}); - -export const abiArraySchema = Type.Array(abiSchema); -export type AbiSchemaType = Static; - -export const contractEventSchema = Type.Record(Type.String(), Type.Any()); - -export const rolesResponseSchema = Type.Object({ - admin: Type.Array(Type.String()), - transfer: Type.Array(Type.String()), - minter: Type.Array(Type.String()), - pauser: Type.Array(Type.String()), - lister: Type.Array(Type.String()), - asset: Type.Array(Type.String()), - unwrap: Type.Array(Type.String()), - factory: Type.Array(Type.String()), - signer: Type.Array(Type.String()), -}); - -export const blockNumberOrTagSchema = Type.Union([ - Type.Integer({ minimum: 0 }), - Type.Literal("latest"), - Type.Literal("earliest"), - Type.Literal("pending"), - Type.Literal("safe"), - Type.Literal("finalized"), -]); - -export const eventsQuerystringSchema = Type.Object( - { - fromBlock: Type.Optional({ - ...blockNumberOrTagSchema, - default: "0", - }), - toBlock: Type.Optional({ - ...blockNumberOrTagSchema, - default: "latest", - }), - order: Type.Optional( - Type.Union([Type.Literal("asc"), Type.Literal("desc")], { - default: "desc", - }), - ), - }, - { - description: - "Specify the from and to block numbers to get events for, defaults to all blocks", - }, -); - -export const royaltySchema = Type.Object({ - seller_fee_basis_points: Type.Integer({ - description: "The royalty fee in BPS (basis points). 100 = 1%.", - minimum: 0, - maximum: 10_000, - }), - fee_recipient: { - ...AddressSchema, - description: "The wallet address that will receive the royalty fees.", - }, -}); - -export const contractDeployBasicSchema = Type.Object({ - version: Type.Optional( - Type.String({ - description: "Version of the contract to deploy. Defaults to latest.", - }), - ), - forceDirectDeploy: Type.Optional(Type.Boolean()), - saltForProxyDeploy: Type.Optional(Type.String()), - compilerOptions: Type.Optional( - Type.Object({ - compilerType: Type.Enum(Type.Literal("solc"), Type.Literal("zksolc")), - compilerVersion: Type.Optional(Type.String()), - evmVersion: Type.Optional(Type.String()), - }), - ), -}); diff --git a/src/server/schemas/erc20/index.ts b/src/server/schemas/erc20/index.ts deleted file mode 100644 index 1b8df828d..000000000 --- a/src/server/schemas/erc20/index.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import { AddressSchema } from "../address"; - -export const erc20MetadataSchema = Type.Object({ - name: Type.String(), - symbol: Type.String(), - decimals: Type.String(), - value: Type.String({ - description: "Value in wei", - }), - displayValue: Type.String({ - description: "Value in tokens", - }), -}); - -export const signature20InputSchema = Type.Object({ - to: Type.String({ - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }), - quantity: Type.String({ - description: "The number of tokens this signature can be used to mint.", - }), - primarySaleRecipient: Type.Optional( - Type.String({ - description: - "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - }), - ), - uid: Type.Optional( - Type.String({ - description: `A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - Note that the input value gets hashed in the actual payload that gets generated. - The smart contract enforces on-chain that no uid gets used more than once, - which means you can deterministically generate the uid to prevent specific exploits.`, - }), - ), - currencyAddress: Type.Optional( - Type.String({ - description: - "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - }), - ), - price: Type.Optional( - Type.String({ - description: - "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - }), - ), - mintStartTime: Type.Optional( - Type.Union([ - Type.String({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), - Type.Integer({ minimum: 0 }), - ]), - ), - mintEndTime: Type.Optional( - Type.Union([ - Type.String({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), - Type.Integer({ minimum: 0 }), - ]), - ), -}); - -export const signature20OutputSchema = Type.Object({ - to: Type.String({ - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }), - quantity: Type.String({ - description: "The number of tokens this signature can be used to mint.", - }), - primarySaleRecipient: Type.String({ - description: - "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - }), - uid: Type.String({ - description: `A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - Note that the input value gets hashed in the actual payload that gets generated. - The smart contract enforces on-chain that no uid gets used more than once, - which means you can deterministically generate the uid to prevent specific exploits.`, - }), - currencyAddress: { - ...AddressSchema, - description: - "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - }, - price: Type.String({ - description: - "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - }), - mintStartTime: Type.Integer({ - description: - "The time from which the signature can be used to mint tokens. Defaults to now.", - default: Date.now(), - minimum: 0, - }), - mintEndTime: Type.Integer({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - default: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 10).getTime(), - minimum: 0, - }), -}); - -signature20InputSchema.examples = [ - { - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - quantity: "1", - mintStartTime: "2023-06-07T21:51:33.386Z", - mintEndTime: "2023-07-07T21:51:33.386Z", - }, -]; - -signature20OutputSchema.examples = [ - { - payload: { - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - quantity: "1", - primarySaleRecipient: "0x0000000000000000000000000000000000000000", - uid: "0x3834383133343631326235613434363261623532623264643462336239373634", - currencyAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - price: "0", - mintStartTime: 1686174693, - mintEndTime: 1688766693, - }, - signature: - "0xe16697bf7ede4ff4918f0dbc84953b964a84fed70cb3a0b0afb3ee9a55c9ff4d14e029bce8d8c74e71c1de32889c4eff529a9f7d45402455b8d15c7e6993c1c91b", - }, -]; - -export type erc20ResponseType = Omit< - Omit, "mintStartTime">, - "mintEndTime" -> & { - mintStartTime: number | Date | undefined; - mintEndTime: number | Date | undefined; -}; diff --git a/src/server/schemas/event-log.ts b/src/server/schemas/event-log.ts deleted file mode 100644 index eb30b668d..000000000 --- a/src/server/schemas/event-log.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { ContractEventLogs } from "@prisma/client"; -import { Type, type Static } from "@sinclair/typebox"; -import { AddressSchema, TransactionHashSchema } from "./address"; - -export const eventLogSchema = Type.Object({ - chainId: Type.Integer(), - contractAddress: AddressSchema, - blockNumber: Type.Integer(), - transactionHash: TransactionHashSchema, - topics: Type.Array(Type.String()), - data: Type.String(), - eventName: Type.Optional(Type.String()), - decodedLog: Type.Any(), - timestamp: Type.Integer(), - transactionIndex: Type.Integer(), - logIndex: Type.Integer(), -}); - -export const toEventLogSchema = ( - log: ContractEventLogs, -): Static => { - const topics: string[] = []; - for (const val of [ log.topic0, log.topic1, log.topic2, log.topic3 ]) { - if (val) { - topics.push(val); - } - } - - return { - chainId: Number.parseInt(log.chainId), - contractAddress: log.contractAddress, - blockNumber: log.blockNumber, - transactionHash: log.transactionHash, - topics, - data: log.data, - eventName: log.eventName ?? undefined, - decodedLog: log.decodedLog, - timestamp: log.timestamp.getTime(), - transactionIndex: log.transactionIndex, - logIndex: log.logIndex, - }; -}; diff --git a/src/server/schemas/event.ts b/src/server/schemas/event.ts deleted file mode 100644 index 0860726ea..000000000 --- a/src/server/schemas/event.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { BigNumber } from "ethers"; - -export type ContractEventV4 = { - eventName: string; - data: Record; - transaction: { - blockNumber: number; - blockHash: string; - transactionIndex: number; - removed: boolean; - address: string; - data: string; - topic: string[]; - transactionHash: string; - logIndex: number; - event: string; - eventSignature?: string; - }; -}; - -export type ContractEventV5 = { - eventName: string; - args: Record; - address: string; - topic: string[]; - data: string; - blockNumber: bigint; - transactionHash: string; - transactionIndex: number; - blockHash: string; - logIndex: number; - removed: boolean; -}; - -/** - * Mapping of events v5 response to v4 for backward compatiblity. - * Clients may be using this api and dont want to break things. - */ -export function toContractEventV4Schema( - eventV5: ContractEventV5, -): ContractEventV4 { - const eventName = eventV5.eventName; - - // backwards compatibility of BigInt(v5) to BigNumber(v4) - const data: Record = {}; - for (const key of Object.keys(eventV5.args)) { - let value = eventV5.args[key]; - if (typeof value === "bigint") { - value = BigNumber.from(value.toString()); - } - data[key] = value; - } - - return { - eventName, - data, - transaction: { - blockNumber: Number(eventV5.blockNumber), - blockHash: eventV5.blockHash, - transactionIndex: eventV5.transactionIndex, - removed: eventV5.removed, - address: eventV5.address, - data: eventV5.data, - topic: eventV5.topic, - transactionHash: eventV5.transactionHash, - logIndex: eventV5.logIndex, - event: eventV5.eventName, - // todo: eventV5.eventSignature is not returned so ignoring for now - }, - }; -} diff --git a/src/server/schemas/http-headers/thirdweb-sdk-version.ts b/src/server/schemas/http-headers/thirdweb-sdk-version.ts deleted file mode 100644 index c8ce56c3f..000000000 --- a/src/server/schemas/http-headers/thirdweb-sdk-version.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Type } from "@sinclair/typebox"; - -export const thirdwebSdkVersionSchema = Type.Object({ - "x-thirdweb-sdk-version": Type.Optional( - Type.String({ - description: `Override the thirdweb sdk version used. Example: "5" for v5 SDK compatibility.`, - }), - ), -}); diff --git a/src/server/schemas/marketplace-v3/direct-listing/index.ts b/src/server/schemas/marketplace-v3/direct-listing/index.ts deleted file mode 100644 index bbd2b3f0b..000000000 --- a/src/server/schemas/marketplace-v3/direct-listing/index.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { AddressSchema } from "../../address"; -import { nftMetadataSchema } from "../../nft"; -import { Status, currencyValueSchema } from "../../shared-api-schemas"; - -export const directListingV3InputSchema = Type.Object({ - assetContractAddress: { - ...AddressSchema, - description: "The address of the asset being listed.", - }, - tokenId: Type.String({ - description: "The ID of the token to list.", - }), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The address of the currency to accept for the listing.", - }), - ), - quantity: Type.Optional( - Type.String({ - description: - "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - }), - ), - pricePerToken: Type.String({ - description: "The price to pay per unit of NFTs listed.", - }), - isReservedListing: Type.Optional( - Type.Boolean({ - description: - "Whether the listing is reserved to be bought from a specific set of buyers.", - }), - ), - startTimestamp: Type.Optional( - Type.Integer({ - description: - "The start time of the listing. If not set, defaults to now.", - minimum: 0, - }), - ), - endTimestamp: Type.Optional( - Type.Integer({ - description: - "The end time of the listing. If not set, defaults to 7 days from now.", - minimum: 0, - }), - ), -}); - -export const directListingV3OutputSchema = Type.Object({ - assetContractAddress: { - ...AddressSchema, - description: "The address of the asset being listed.", - }, - tokenId: Type.String({ - description: "The ID of the token to list.", - }), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The address of the currency to accept for the listing.", - }), - ), - quantity: Type.Optional( - Type.String({ - description: - "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - }), - ), - pricePerToken: Type.String({ - description: "The price to pay per unit of NFTs listed.", - }), - isReservedListing: Type.Optional( - Type.Boolean({ - description: - "Whether the listing is reserved to be bought from a specific set of buyers.", - }), - ), - id: Type.String({ - description: "The listing ID.", - }), - currencyValuePerToken: Type.Optional(currencyValueSchema), - asset: Type.Optional(nftMetadataSchema), - status: Type.Optional( - Type.Union([ - Type.Literal(Status.UNSET), - Type.Literal(Status.Created), - Type.Literal(Status.Completed), - Type.Literal(Status.Cancelled), - Type.Literal(Status.Active), - Type.Literal(Status.Expired), - ]), - ), - startTimeInSeconds: Type.Optional( - Type.Integer({ - description: - "The start time of the listing. If not set, defaults to now.", - minimum: 0, - }), - ), - endTimeInSeconds: Type.Optional( - Type.Integer({ - description: - "The end time of the listing. If not set, defaults to 7 days from now.", - minimum: 0, - }), - ), -}); diff --git a/src/server/schemas/marketplace-v3/english-auction/index.ts b/src/server/schemas/marketplace-v3/english-auction/index.ts deleted file mode 100644 index 59263451a..000000000 --- a/src/server/schemas/marketplace-v3/english-auction/index.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { AddressSchema } from "../../address"; -import { nftMetadataSchema } from "../../nft"; -import { Status } from "../../shared-api-schemas"; - -const currencyValueSchema = Type.Object({ - name: Type.Optional(Type.String()), - symbol: Type.Optional(Type.String()), - decimals: Type.Optional(Type.Integer({ minimum: 1 })), - value: Type.Optional(Type.String()), - displayValue: Type.Optional(Type.String()), -}); - -currencyValueSchema.description = - "The `CurrencyValue` of the listing. Useful for displaying the price information."; - -export const englishAuctionInputSchema = Type.Object({ - assetContractAddress: { - ...AddressSchema, - description: "The address of the asset being listed.", - }, - tokenId: Type.String({ - description: "The ID of the token to list.", - }), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The address of the currency to accept for the listing.", - }), - ), - quantity: Type.Optional( - Type.String({ - description: - "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - }), - ), - startTimestamp: Type.Optional( - Type.Integer({ - description: - "The start time of the listing. If not set, defaults to now.", - minimum: 0, - }), - ), - endTimestamp: Type.Optional( - Type.Integer({ - description: - "The end time of the listing. If not set, defaults to 7 days from now.", - minimum: 0, - }), - ), - buyoutBidAmount: Type.String({ - description: "amount to buy the NFT and close the listing.", - }), - minimumBidAmount: Type.String({ - description: "Minimum amount that bids must be to placed", - }), - bidBufferBps: Type.Optional( - Type.String({ - description: - "percentage the next bid must be higher than the current highest bid (default is contract-level bid buffer bps)", - }), - ), - timeBufferInSeconds: Type.Optional( - Type.String({ - description: - "time in seconds that are added to the end time when a bid is placed (default is contract-level time buffer in seconds)", - }), - ), -}); - -export const englishAuctionOutputSchema = Type.Object({ - assetContractAddress: { - ...AddressSchema, - description: "The address of the asset being listed.", - }, - tokenId: Type.String({ - description: "The ID of the token to list.", - }), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The address of the currency to accept for the listing.", - }), - ), - quantity: Type.Optional( - Type.String({ - description: - "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - }), - ), - id: Type.String({ - description: "The listing ID.", - }), - minimumBidAmount: Type.Optional( - Type.String({ - description: - "The minimum price that a bid must be in order to be accepted.", - }), - ), - buyoutBidAmount: Type.String({ - description: "The buyout price of the auction.", - }), - buyoutCurrencyValue: currencyValueSchema, - timeBufferInSeconds: Type.Number({ - description: "This is a buffer e.g. x seconds.", - }), - bidBufferBps: Type.Integer({ - description: - "To be considered as a new winning bid, a bid must be at least x% greater than the previous bid.", - minimum: 0, - maximum: 10_000, - }), - startTimeInSeconds: Type.Integer({ - description: "The start time of the auction.", - minimum: 0, - }), - endTimeInSeconds: Type.Integer({ - description: "The end time of the auction.", - minimum: 0, - }), - asset: Type.Optional(nftMetadataSchema), - status: Type.Optional( - Type.Union([ - Type.Literal(Status.UNSET), - Type.Literal(Status.Created), - Type.Literal(Status.Completed), - Type.Literal(Status.Cancelled), - Type.Literal(Status.Active), - Type.Literal(Status.Expired), - ]), - ), -}); - -export const bidSchema = Type.Object({ - auctionId: Type.Optional( - Type.String({ - description: "The id of the auction.", - }), - ), - bidderAddress: Type.Optional( - Type.String({ - description: "The address of the buyer who made the offer.", - }), - ), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The currency contract address of the offer token.", - }), - ), - bidAmount: Type.Optional( - Type.String({ - description: "The amount of coins offered per token.", - }), - ), - bidAmountCurrencyValue: Type.Optional(currencyValueSchema), -}); diff --git a/src/server/schemas/marketplace-v3/offer/index.ts b/src/server/schemas/marketplace-v3/offer/index.ts deleted file mode 100644 index 0d7a2834a..000000000 --- a/src/server/schemas/marketplace-v3/offer/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { AddressSchema } from "../../address"; -import { nftMetadataSchema } from "../../nft"; -import { Status, currencyValueSchema } from "../../shared-api-schemas"; - -export const OfferV3InputSchema = Type.Object({ - assetContractAddress: { - ...AddressSchema, - description: "The address of the asset being listed.", - }, - tokenId: Type.String({ - description: "The ID of the token to list.", - }), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The address of the currency to accept for the listing.", - }), - ), - quantity: Type.Optional( - Type.String({ - description: - "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - }), - ), - totalPrice: Type.String({ - description: "the price to offer in the currency specified", - }), - endTimestamp: Type.Optional( - Type.Integer({ - description: "Defaults to 10 years from now.", - minimum: 0, - }), - ), -}); - -export const OfferV3OutputSchema = Type.Object({ - assetContractAddress: { - ...AddressSchema, - description: "The address of the asset being listed.", - }, - tokenId: Type.String({ - description: "The ID of the token to list.", - }), - currencyContractAddress: Type.Optional( - Type.String({ - description: "The address of the currency to accept for the listing.", - }), - ), - quantity: Type.Optional( - Type.String({ - description: - "The quantity of tokens to include in the listing. NOTE: For ERC721s, this value should always be 1 (and will be forced internally regardless of what is passed here).", - }), - ), - id: Type.String({ - description: "The id of the offer.", - }), - offerorAddress: { - ...AddressSchema, - description: "The address of the creator of offer.", - }, - currencyValue: Type.Optional(currencyValueSchema), - totalPrice: Type.String({ - description: "The total offer amount for the NFTs.", - }), - asset: Type.Optional(nftMetadataSchema), - endTimeInSeconds: Type.Optional( - Type.Integer({ - description: "The end time of the auction.", - minimum: 0, - }), - ), - status: Type.Optional( - Type.Union([ - Type.Literal(Status.UNSET), - Type.Literal(Status.Created), - Type.Literal(Status.Completed), - Type.Literal(Status.Cancelled), - Type.Literal(Status.Active), - Type.Literal(Status.Expired), - ]), - ), -}); diff --git a/src/server/schemas/nft/index.ts b/src/server/schemas/nft/index.ts deleted file mode 100644 index f1d646bce..000000000 --- a/src/server/schemas/nft/index.ts +++ /dev/null @@ -1,449 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import type { BigNumber } from "ethers"; -import { AddressSchema } from "../address"; -import { NumberStringSchema } from "../number"; - -// NFTInput format compatible with v5 SDK -export const nftInputSchema = Type.Partial( - Type.Object({ - name: Type.String({ - description: "The name of the NFT", - }), - description: Type.String({ - description: "The description of the NFT", - }), - image: Type.String({ - description: "The image of the NFT", - }), - animation_url: Type.String({ - description: "The animation url of the NFT", - }), - external_url: Type.String({ - description: "The external url of the NFT", - }), - background_color: Type.String({ - description: "The background color of the NFT", - }), - // @deprecated - properties: Type.Any({ - description: - '(not recommended - use "attributes") The properties of the NFT.', - }), - attributes: Type.Array( - Type.Object({ - trait_type: Type.String(), - value: Type.String(), - }), - { description: "Arbitrary metadata for this item." }, - ), - }), -); - -export const nftMetadataInputSchema = Type.Object({ - name: Type.Optional({ - description: "The name of the NFT", - ...Type.Union([Type.String(), Type.Number(), Type.Null()]), - }), - description: Type.Optional({ - description: "The description of the NFT", - ...Type.Union([Type.String(), Type.Null()]), - }), - image: Type.Optional({ - ...Type.Union([Type.String(), Type.Null()]), - description: "The image of the NFT", - }), - external_url: Type.Optional({ - ...Type.Union([Type.String(), Type.Null()]), - description: "The external url of the NFT", - }), - animation_url: Type.Optional({ - ...Type.Union([Type.String(), Type.Null()]), - description: "The animation url of the NFT", - }), - properties: Type.Optional({ - ...Type.Any(), - description: "The properties of the NFT", - }), - attributes: Type.Optional({ - ...Type.Any(), - description: "The attributes of the NFT", - }), - background_color: Type.Optional({ - ...Type.Union([Type.String(), Type.Null()]), - description: "The background color of the NFT", - }), -}); - -export const nftMetadataSchema = Type.Object( - { - id: Type.String(), - uri: Type.String(), - name: Type.Optional( - Type.Union([Type.String(), Type.Number(), Type.Null()]), - ), - description: Type.Optional(Type.Union([Type.String(), Type.Null()])), - image: Type.Optional(Type.Union([Type.String(), Type.Null()])), - external_url: Type.Optional(Type.Union([Type.String(), Type.Null()])), - animation_url: Type.Optional(Type.Union([Type.String(), Type.Null()])), - properties: Type.Optional(Type.Any()), - attributes: Type.Optional(Type.Any()), - }, - { - additionalProperties: true, - }, -); - -export const nftOrInputSchema = Type.Union([ - nftMetadataInputSchema, - Type.String(), -]); - -export const nftAndSupplySchema = Type.Object({ - metadata: nftOrInputSchema, - supply: Type.String(), -}); - -export const nftSchema = Type.Object({ - metadata: nftMetadataSchema, - owner: Type.String(), - type: Type.Union([ - Type.Literal("ERC1155"), - Type.Literal("ERC721"), - Type.Literal("metaplex"), - ]), - supply: Type.String(), - quantityOwned: Type.Optional(Type.String()), -}); - -export const signature721InputSchema = Type.Object({ - to: { - ...AddressSchema, - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }, - royaltyRecipient: Type.Optional({ - ...AddressSchema, - description: - "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - }), - quantity: Type.Optional({ - ...NumberStringSchema, - description: "The number of tokens this signature can be used to mint.", - }), - royaltyBps: Type.Optional( - Type.Integer({ - description: - "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - minimum: 0, - maximum: 10_000, - }), - ), - primarySaleRecipient: Type.Optional({ - ...AddressSchema, - description: - "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - }), - uid: Type.Optional( - Type.String({ - description: `A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - Note that the input value gets hashed in the actual payload that gets generated. - The smart contract enforces on-chain that no uid gets used more than once, - which means you can deterministically generate the uid to prevent specific exploits.`, - }), - ), - metadata: Type.Union([nftMetadataInputSchema, Type.String()]), - currencyAddress: Type.Optional({ - ...AddressSchema, - description: - "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - }), - price: Type.Optional( - Type.String({ - description: - "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - }), - ), - mintStartTime: Type.Optional( - Type.Union([ - Type.String({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), - Type.Integer({ minimum: 0 }), - ]), - ), - mintEndTime: Type.Optional( - Type.Union([ - Type.String({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), - Type.Integer({ minimum: 0 }), - ]), - ), -}); - -export const signature721OutputSchema = Type.Object({ - uri: Type.String(), - to: Type.String({ - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }), - royaltyRecipient: { - ...AddressSchema, - description: - "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - }, - quantity: { - ...NumberStringSchema, - description: "The number of tokens this signature can be used to mint.", - }, - royaltyBps: Type.String({ - description: - "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - }), - primarySaleRecipient: { - ...AddressSchema, - description: - "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - }, - uid: Type.String({ - description: `A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - Note that the input value gets hashed in the actual payload that gets generated. - The smart contract enforces on-chain that no uid gets used more than once, - which means you can deterministically generate the uid to prevent specific exploits.`, - }), - metadata: Type.Union([nftMetadataInputSchema, Type.String()]), - currencyAddress: { - ...AddressSchema, - description: - "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - }, - price: Type.Optional( - Type.String({ - description: - "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - }), - ), - mintStartTime: Type.Integer({ - description: - "The time from which the signature can be used to mint tokens. Defaults to now.", - }), - mintEndTime: Type.Integer({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), -}); - -export const signature1155InputSchema = Type.Object({ - to: Type.String({ - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }), - quantity: Type.String({ - description: "The number of tokens this signature can be used to mint.", - }), - metadata: Type.Union([nftMetadataInputSchema, Type.String()]), - royaltyRecipient: Type.Optional( - Type.String({ - description: - "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - }), - ), - royaltyBps: Type.Optional( - Type.Integer({ - description: - "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - minimum: 0, - maximum: 10_000, - }), - ), - primarySaleRecipient: Type.Optional( - Type.String({ - description: - "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - }), - ), - uid: Type.Optional( - Type.String({ - description: `A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - Note that the input value gets hashed in the actual payload that gets generated. - The smart contract enforces on-chain that no uid gets used more than once, - which means you can deterministically generate the uid to prevent specific exploits.`, - }), - ), - currencyAddress: Type.Optional( - Type.String({ - description: - "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - }), - ), - price: Type.Optional( - Type.String({ - description: - "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - }), - ), - mintStartTime: Type.Optional( - Type.Union([ - Type.String({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), - Type.Integer({ minimum: 0 }), - ]), - ), - mintEndTime: Type.Optional( - Type.Union([ - Type.String({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - }), - Type.Integer({ minimum: 0 }), - ]), - ), -}); - -export const signature1155OutputSchema = Type.Object({ - uri: Type.String(), - tokenId: Type.String(), - to: Type.String({ - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }), - royaltyRecipient: Type.String({ - description: - "The address that will receive the royalty fees from secondary sales. Defaults to the royaltyRecipient address of the contract.", - }), - quantity: Type.String({ - description: "The number of tokens this signature can be used to mint.", - }), - royaltyBps: Type.String({ - description: - "The percentage fee you want to charge for secondary sales. Defaults to the royaltyBps of the contract.", - }), - primarySaleRecipient: Type.String({ - description: - "If a price is specified, the funds will be sent to the primarySaleRecipient address. Defaults to the primarySaleRecipient address of the contract.", - }), - uid: Type.String({ - description: `A unique identifier for the payload, used to prevent replay attacks and other types of exploits. - Note that the input value gets hashed in the actual payload that gets generated. - The smart contract enforces on-chain that no uid gets used more than once, - which means you can deterministically generate the uid to prevent specific exploits.`, - }), - metadata: Type.Union([nftMetadataInputSchema, Type.String()]), - currencyAddress: { - ...AddressSchema, - description: - "The address of the currency to pay for minting the tokens (use the price field to specify the price). Defaults to NATIVE_TOKEN_ADDRESS", - }, - price: Type.String({ - description: - "If you want the user to pay for minting the tokens, you can specify the price per token. Defaults to 0.", - default: "0", - }), - mintStartTime: Type.Integer({ - description: - "The time from which the signature can be used to mint tokens. Defaults to now if value not provided.", - minimum: 0, - }), - mintEndTime: Type.Integer({ - description: - "The time until which the signature can be used to mint tokens. Defaults to 10 years from now.", - minimum: 0, - }), -}); - -export type ercNFTResponseType = ( - | Omit< - Omit, "mintStartTime">, - "mintEndTime" - > - | Omit< - Omit, "mintStartTime">, - "mintEndTime" - > -) & { - mintStartTime: number | Date | undefined; - mintEndTime: number | Date | undefined; - quantity: string | number | bigint | BigNumber; -}; - -// Examples - -signature721InputSchema.examples = [ - { - to: "0x...", - quantity: "1", - metadata: { - name: "test tokenII", - description: "test token", - }, - mintStartTime: "2023-06-07T21:51:33.386Z", - mintEndTime: "2023-07-07T21:51:33.386Z", - }, -]; - -signature721OutputSchema.examples = [ - { - payload: { - uri: "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - royaltyRecipient: "0x0000000000000000000000000000000000000000", - quantity: "1", - royaltyBps: "0", - primarySaleRecipient: "0x0000000000000000000000000000000000000000", - uid: "0x3862386334363135326230303461303939626136653361643131343836373563", - metadata: { - name: "test tokenII", - description: "test token", - }, - currencyAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - price: "0", - mintStartTime: 1686169938, - mintEndTime: 2001529938, - }, - signature: - "0xe6f2e29f32f7da65385effa2ed4f39b8d3caf08b025eb0004fd4695b42ee145f2c7afdf2764f0097c9ed5d88b50e97c4c638f91289408fa7d7a0834cd707c4a41b", - }, -]; - -signature1155InputSchema.examples = [ - { - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - quantity: "1", - metadata: { - name: "test tokenII", - description: "test token", - }, - mintStartTime: "2023-06-07T21:51:33.386Z", - mintEndTime: "2023-07-07T21:51:33.386Z", - }, -]; - -signature1155OutputSchema.examples = [ - { - payload: { - uri: "ipfs://QmP1i29T534877ptz8bazU1eYiYLzQ1GRK4cnZWngsz9ud/0", - tokenId: - "115792089237316195423570985008687907853269984665640564039457584007913129639935", - to: "0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473", - royaltyRecipient: "0x0000000000000000000000000000000000000000", - quantity: "1", - royaltyBps: "0", - primarySaleRecipient: "0x0000000000000000000000000000000000000000", - uid: "0x3462396330333131353033363433336439343162303033363933373333396232", - metadata: { - name: "test tokenII", - description: "test token", - }, - currencyAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - price: "0", - mintStartTime: 1686174693, - mintEndTime: 1688766693, - }, - signature: - "0x674414eb46d1be3fb8f703b51049aa857b27c70c72293f054ed211be0efb843841bcd86b1245c321b20e50e2a9bebb555e70246d84778d5e76668db2f102c6401b", - }, -]; diff --git a/src/server/schemas/nft/v5.ts b/src/server/schemas/nft/v5.ts deleted file mode 100644 index 151728c2d..000000000 --- a/src/server/schemas/nft/v5.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { nftInputSchema } from "."; -import { AddressSchema } from "../address"; - -/** - * ERC721 - */ -export const signature721InputSchemaV5 = Type.Object({ - metadata: Type.Union([Type.String(), nftInputSchema]), - to: { - ...AddressSchema, - description: - "The wallet address that can use this signature to mint tokens. This is to prevent another wallet from intercepting the signature and using it to mint tokens for themselves.", - }, - price: Type.Optional( - Type.String({ - description: - 'The amount of the "currency" token this token costs. Example: "0.1"', - }), - ), - priceInWei: Type.Optional( - Type.String({ - description: - 'The amount of the "currency" token this token costs in wei. Remember to use the correct decimals amount for the currency. Example: "100000000000000000" = 0.1 ETH (18 decimals)', - }), - ), - currency: Type.Optional({ - ...AddressSchema, - description: - "The currency address to pay for minting the tokens. Defaults to the chain's native token.", - }), - primarySaleRecipient: Type.Optional({ - ...AddressSchema, - description: - 'If a price is specified, funds will be sent to the "primarySaleRecipient" address. Defaults to the "primarySaleRecipient" address of the contract.', - }), - royaltyRecipient: Type.Optional({ - ...AddressSchema, - description: - 'The address that will receive the royalty fees from secondary sales. Defaults to the "royaltyRecipient" address of the contract.', - }), - royaltyBps: Type.Optional( - Type.Integer({ - description: - 'The percentage fee you want to charge for secondary sales. Defaults to the "royaltyBps" of the contract.', - minimum: 0, - maximum: 10_000, - }), - ), - validityStartTimestamp: Type.Optional( - Type.Integer({ - description: - "The start time (in Unix seconds) when the signature can be used to mint. Default: now", - minimum: 0, - }), - ), - validityEndTimestamp: Type.Optional( - Type.Integer({ - description: - "The end time (in Unix seconds) when the signature can be used to mint. Default: 10 years", - minimum: 0, - }), - ), - uid: Type.Optional( - Type.String({ - description: - "The uid is a unique identifier hashed in the payload to prevent replay attacks, ensuring it's only used once on-chain.", - }), - ), -}); - -export const signature721OutputSchemaV5 = Type.Object({ - uri: Type.String(), - to: Type.String(), - price: Type.String(), - currency: AddressSchema, - primarySaleRecipient: Type.String(), - royaltyRecipient: Type.String(), - royaltyBps: Type.String(), - validityStartTimestamp: Type.Integer(), - validityEndTimestamp: Type.Integer(), - uid: Type.String(), -}); diff --git a/src/server/schemas/number.ts b/src/server/schemas/number.ts deleted file mode 100644 index abea37a7d..000000000 --- a/src/server/schemas/number.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Type } from "@sinclair/typebox"; - -export const TokenAmountStringSchema = Type.RegExp(/^\d+(\.\d+)?$/, { - description: 'An amount in native token (decimals allowed). Example: "0.1"', - examples: ["0.1"], -}); - -export const WeiAmountStringSchema = Type.RegExp(/^\d+$/, { - description: 'An amount in wei (no decimals). Example: "50000000000"', - examples: ["50000000000"], -}); - -export const NumberStringSchema = Type.RegExp(/^\d+$/, { - examples: ["42"], -}); diff --git a/src/server/schemas/pagination.ts b/src/server/schemas/pagination.ts deleted file mode 100644 index 8f51727b7..000000000 --- a/src/server/schemas/pagination.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Type } from "@sinclair/typebox"; - -export const PaginationSchema = Type.Object({ - page: Type.Integer({ - description: "Specify the page number.", - examples: [1], - default: 1, - minimum: 1, - }), - limit: Type.Integer({ - description: "Specify the number of results to return per page.", - examples: [100], - default: 100, - }), -}); diff --git a/src/server/schemas/prebuilts/index.ts b/src/server/schemas/prebuilts/index.ts deleted file mode 100644 index 9162f98d4..000000000 --- a/src/server/schemas/prebuilts/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { constants } from "ethers"; -import { AddressSchema } from "../address"; -import { chainIdOrSlugSchema } from "../chain"; - -export const commonContractSchema = Type.Object({ - name: Type.String(), - description: Type.Optional(Type.String()), - image: Type.Optional(Type.String()), - external_link: Type.Optional(Type.String()), - app_uri: Type.Optional(Type.String()), - defaultAdmin: Type.Optional(Type.String()), -}); - -export const splitRecipientInputSchema = Type.Object({ - address: AddressSchema, - sharesBps: Type.Integer({ - minimum: 0, - maximum: 10_000, - }), -}); - -const percentSchema = Type.Number({ - maximum: 100, - minimum: 0, - default: 0, -}); - -export const commonRoyaltySchema = Type.Object({ - seller_fee_basis_points: Type.Integer({ - maximum: 10_000, - minimum: 0, - default: 0, - }), - - fee_recipient: Type.String({ - default: constants.AddressZero, - }), -}); - -export const merkleSchema = Type.Optional( - Type.Object({ - merkle: Type.Optional(Type.Record(Type.String(), Type.String())), - }), -); - -export const commonSymbolSchema = Type.Object({ - symbol: Type.String({ - default: "", - }), -}); - -export const voteSettingsInputSchema = Type.Object({ - voting_delay_in_blocks: Type.Integer({ - minimum: 0, - default: 0, - }), - voting_period_in_blocks: Type.Integer({ - minimum: 1, - default: 1, - }), - voting_token_address: AddressSchema, - voting_quorum_fraction: percentSchema, - proposal_token_threshold: Type.String({ - default: "0", - }), -}); - -export const commonPrimarySaleSchema = Type.Object({ - primary_sale_recipient: Type.Optional(Type.String()), -}); - -export const commonPlatformFeeSchema = Type.Object({ - platform_fee_basis_points: Type.Integer({ - maximum: 10_000, - minimum: 0, - default: 0, - }), - platform_fee_recipient: Type.String({ - default: constants.AddressZero, - }), -}); - -export const commonTrustedForwarderSchema = Type.Object({ - trusted_forwarders: Type.Array(Type.String(), { default: [] }), -}); - -export const prebuiltDeployContractParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, -}); - -export const prebuiltDeployResponseSchema = Type.Object({ - result: Type.Object({ - queueId: Type.Optional(Type.String()), - deployedAddress: Type.Optional(AddressSchema), - }), -}); diff --git a/src/server/schemas/shared-api-schemas.ts b/src/server/schemas/shared-api-schemas.ts index 61053cb75..f389dcee8 100644 --- a/src/server/schemas/shared-api-schemas.ts +++ b/src/server/schemas/shared-api-schemas.ts @@ -1,321 +1,41 @@ -import { Type, type Static } from "@sinclair/typebox"; -import { PREBUILT_CONTRACTS_MAP } from "@thirdweb-dev/sdk"; -import type { RouteGenericInterface } from "fastify"; -import type { FastifySchema } from "fastify/types/schema"; -import { StatusCodes } from "http-status-codes"; -import { AddressSchema } from "./address"; -import { chainIdOrSlugSchema } from "./chain"; - -export const baseReplyErrorSchema = Type.Object({ - message: Type.Optional(Type.String()), - reason: Type.Optional(Type.Any()), - code: Type.Optional(Type.String()), - stack: Type.Optional(Type.String()), - statusCode: Type.Optional(Type.Integer()), -}); - -/** - * Basic schema for Request Parameters - */ -export const contractParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: { - ...AddressSchema, - description: "Contract address", - }, -}); - -export const requestQuerystringSchema = Type.Object({ - simulateTx: Type.Optional( - Type.Boolean({ - description: - "Simulates the transaction before adding it to the queue, returning an error if it fails simulation. Note: This step is less performant and recommended only for debugging purposes.", - default: false, - }), - ), -}); - -export const prebuiltDeployParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractType: Type.String({ - examples: Object.keys(PREBUILT_CONTRACTS_MAP), - description: "Contract type to deploy", - }), -}); - -export const publishedDeployParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - publisher: Type.String({ - examples: ["deployer.thirdweb.eth"], - description: "Address or ENS of the publisher of the contract", - }), - contractName: Type.String({ - examples: ["AirdropERC20"], - description: "Name of the published contract to deploy", - }), -}); - -/** - * Basic schema for all Response Body - */ -const replyBodySchema = Type.Object({ - result: Type.Optional( - Type.Union([ - Type.Number(), - Type.String(), - Type.Object({}), - Type.Array(Type.Any()), - Type.Boolean(), - Type.Tuple([Type.Any(), Type.Any()]), - ]), - ), -}); - -const replyErrorBodySchema = Type.Object({ - error: Type.Optional(baseReplyErrorSchema), -}); - -export const standardResponseSchema = { - [StatusCodes.OK]: replyBodySchema, - [StatusCodes.BAD_REQUEST]: { - description: "Bad Request", - ...replyErrorBodySchema, - examples: [ - { - error: { - message: "", - code: "BAD_REQUEST", - statusCode: StatusCodes.BAD_REQUEST, - }, - }, - ], - }, - [StatusCodes.NOT_FOUND]: { - description: "Not Found", - ...replyErrorBodySchema, - examples: [ - { - error: { - message: - "Transaction not found with queueId 9eb88b00-f04f-409b-9df7-7dcc9003bc35", - code: "NOT_FOUND", - statusCode: StatusCodes.NOT_FOUND, - }, - }, - ], - }, - [StatusCodes.INTERNAL_SERVER_ERROR]: { - description: "Internal Server Error", - ...replyErrorBodySchema, - examples: [ - { - error: { - message: - "Transaction simulation failed with reason: types/values length mismatch", - code: "INTERNAL_SERVER_ERROR", - statusCode: StatusCodes.INTERNAL_SERVER_ERROR, - }, - }, - ], - }, -}; - -/** - * Basic Fastify Partial schema for request/response - */ -export const partialRouteSchema: FastifySchema = { - params: contractParamSchema, - response: standardResponseSchema, -}; - -export interface contractSchemaTypes extends RouteGenericInterface { - Params: Static; - Reply: Static; -} - -export interface prebuiltDeploySchemaTypes extends RouteGenericInterface { - Params: Static; - Reply: Static; -} - -export interface publishedDeploySchemaTypes extends RouteGenericInterface { - Params: Static; - Reply: Static; +import type { ZodSchema } from "zod"; +import * as z from "zod"; +import type { ExecutionCredentials } from "../../executors/execute/execute"; + +export function wrapResponseSchema(schema: ZodSchema) { + return z.object({ + result: schema, + }); } -export const transactionWritesResponseSchema = Type.Object({ - result: Type.Object({ - queueId: Type.String({ - description: "Queue ID", - }), - }), -}); - -export const simulateResponseSchema = Type.Object({ - result: Type.Object({ - success: Type.Boolean({ - description: "Simulation Success", +export function wrapPaginatedResponseSchema(schema: ZodSchema) { + return z.object({ + result: z.array(schema), + pagination: z.object({ + totalCount: z.number(), + page: z.number(), + limit: z.number(), }), - }), -}); - -transactionWritesResponseSchema.example = { - result: { - queueId: "9eb88b00-f04f-409b-9df7-7dcc9003bc35", - }, -}; - -/** - * Basic schema for ERC721 Contract Request Parameters - */ -export const erc20ContractParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: { - ...AddressSchema, - description: "ERC20 contract address", - }, -}); - -/** - * Basic schema for ERC721 Contract Request Parameters - */ -export const erc1155ContractParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: { - ...AddressSchema, - description: "ERC1155 contract address", - }, -}); - -/** - * Basic schema for ERC721 Contract Request Parameters - */ -export const erc721ContractParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: { - ...AddressSchema, - description: "ERC721 contract address", - }, -}); -export const currencyValueSchema = Type.Object({ - name: Type.String(), - symbol: Type.String(), - decimals: Type.Integer(), - value: Type.String(), - displayValue: Type.String(), -}); - -currencyValueSchema.description = - "The `CurrencyValue` of the listing. Useful for displaying the price information."; - -export enum Status { - UNSET = 0, - Created = 1, - Completed = 2, - Cancelled = 3, - Active = 4, - Expired = 5, + }); } -export const marketplaceV3ContractParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, - contractAddress: { - ...AddressSchema, - description: "Contract address", - }, +export const requestPaginationSchema = z.object({ + page: z.coerce.number().optional().default(1), + limit: z.coerce.number().optional().default(100), }); -export const marketplaceFilterSchema = Type.Object({ - count: Type.Optional( - Type.Integer({ - description: "Number of listings to fetch", - minimum: 1, - }), - ), - offeror: Type.Optional({ - ...AddressSchema, - description: "has offers from this Address", - }), - seller: Type.Optional({ - ...AddressSchema, - description: "Being sold by this Address", +export const executionCredentialsHeadersSchema = z.object({ + "x-vault-access-token": z.string().optional().openapi({ + description: "Vault Access Token used to access your EOA", }), - start: Type.Optional( - Type.Integer({ - description: "Start from this index (pagination)", - minimum: 0, - }), - ), - tokenContract: Type.Optional({ - ...AddressSchema, - description: "Token contract address to show NFTs from", - }), - tokenId: Type.Optional( - Type.String({ - description: "Only show NFTs with this ID", - }), - ), }); -export const walletDetailsSchema = Type.Object({ - address: { - ...AddressSchema, - description: "Wallet Address", - }, - type: Type.String({ - description: "Wallet Type", - }), - label: Type.Union([ - Type.String({ - description: "A label for your wallet", - }), - Type.Null(), - ]), - awsKmsKeyId: Type.Union([ - Type.String({ - description: "AWS KMS Key ID", - }), - Type.Null(), - ]), - awsKmsArn: Type.Union([ - Type.String({ - description: "AWS KMS Key ARN", - }), - Type.Null(), - ]), - gcpKmsKeyId: Type.Union([ - Type.String({ - description: "GCP KMS Key ID", - }), - Type.Null(), - ]), - gcpKmsKeyRingId: Type.Union([ - Type.String({ - description: "GCP KMS Key Ring ID", - }), - Type.Null(), - ]), - gcpKmsLocationId: Type.Union([ - Type.String({ - description: "GCP KMS Location ID", - }), - Type.Null(), - ]), - gcpKmsKeyVersionId: Type.Union([ - Type.String({ - description: "GCP KMS Key Version ID", - }), - Type.Null(), - ]), - gcpKmsResourcePath: Type.Union([ - Type.String({ - description: "GCP KMS Resource Path", - }), - Type.Null(), - ]), -}); +type ExecutionCredentialsHeaders = z.infer< + typeof executionCredentialsHeadersSchema +>; -export const contractSubscriptionConfigurationSchema = Type.Object({ - maxBlocksToIndex: Type.Integer(), - contractSubscriptionsRequeryDelaySeconds: Type.String(), -}); +export function credentialsFromHeaders(headers: ExecutionCredentialsHeaders) { + return { + vaultAccessToken: headers["x-vault-access-token"], + } as ExecutionCredentials; +} diff --git a/src/server/schemas/transaction-receipt.ts b/src/server/schemas/transaction-receipt.ts deleted file mode 100644 index 5d10a8e16..000000000 --- a/src/server/schemas/transaction-receipt.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { ContractTransactionReceipts } from "@prisma/client"; -import { Type, type Static } from "@sinclair/typebox"; -import { AddressSchema, TransactionHashSchema } from "./address"; - -export const transactionReceiptSchema = Type.Object({ - chainId: Type.Integer(), - blockNumber: Type.Integer(), - contractAddress: AddressSchema, - transactionHash: TransactionHashSchema, - blockHash: Type.String(), - timestamp: Type.Integer(), - data: Type.String(), - value: Type.String(), - - to: Type.String(), - from: Type.String(), - transactionIndex: Type.Integer(), - - gasUsed: Type.String(), - effectiveGasPrice: Type.String(), - status: Type.Integer(), -}); - -export const toTransactionReceiptSchema = ( - transactionReceipt: ContractTransactionReceipts, -): Static => ({ - chainId: Number.parseInt(transactionReceipt.chainId), - blockNumber: transactionReceipt.blockNumber, - contractAddress: transactionReceipt.contractAddress, - transactionHash: transactionReceipt.transactionHash, - blockHash: transactionReceipt.blockHash, - timestamp: transactionReceipt.timestamp.getTime(), - data: transactionReceipt.data, - value: transactionReceipt.value, - to: transactionReceipt.to, - from: transactionReceipt.from, - transactionIndex: transactionReceipt.transactionIndex, - gasUsed: transactionReceipt.gasUsed, - effectiveGasPrice: transactionReceipt.effectiveGasPrice, - status: transactionReceipt.status, -}); diff --git a/src/server/schemas/transaction/index.ts b/src/server/schemas/transaction/index.ts deleted file mode 100644 index ff82934fa..000000000 --- a/src/server/schemas/transaction/index.ts +++ /dev/null @@ -1,382 +0,0 @@ -import { Type, type Static } from "@sinclair/typebox"; -import type { Hex } from "thirdweb"; -import { stringify } from "thirdweb/utils"; -import type { AnyTransaction } from "../../../shared/utils/transaction/types"; -import { AddressSchema, TransactionHashSchema } from "../address"; - -export const TransactionSchema = Type.Object({ - queueId: Type.Union([ - Type.String({ - description: "An identifier for an enqueued blockchain write call", - }), - Type.Null(), - ]), - status: Type.Union( - [ - Type.Literal("queued"), - Type.Literal("sent"), - Type.Literal("mined"), - Type.Literal("errored"), - Type.Literal("cancelled"), - ], - { - description: "The current state of the transaction.", - examples: ["queued", "sent", "mined", "errored", "cancelled"], - }, - ), - chainId: Type.Union([ - Type.String({ - description: "The chain ID for the transaction", - }), - Type.Null(), - ]), - fromAddress: Type.Union([ - Type.String({ - description: "The backend wallet submitting the transaction", - }), - Type.Null(), - ]), - toAddress: Type.Union([ - Type.String({ - description: "The contract address to be called", - }), - Type.Null(), - ]), - data: Type.Union([ - Type.String({ - description: "Encoded calldata", - }), - Type.Null(), - ]), - extension: Type.Union([ - Type.String({ - description: "The extension detected by thirdweb", - }), - Type.Null(), - ]), - value: Type.Union([ - Type.String({ - description: "The amount of native currency to send", - }), - Type.Null(), - ]), - nonce: Type.Union([ - Type.Integer({ - description: "The nonce used by the backend wallet for this transaction", - }), - Type.String({ - description: "The nonce used by the backend wallet for this transaction", - }), - Type.Null(), - ]), - gasLimit: Type.Union([ - Type.String({ - description: "The max gas unit limit", - }), - Type.Null(), - ]), - gasPrice: Type.Union([ - Type.String({ - description: "The gas price used", - }), - Type.Null(), - ]), - maxFeePerGas: Type.Union([ - Type.String({ - description: "The max fee per gas (EIP-1559)", - }), - Type.Null(), - ]), - maxPriorityFeePerGas: Type.Union([ - Type.String({ - description: "The max priority fee per gas (EIP-1559)", - }), - Type.Null(), - ]), - transactionType: Type.Union([ - Type.Integer({ - description: "The type of transaction", - }), - Type.Null(), - ]), - transactionHash: Type.Union([TransactionHashSchema, Type.Null()]), - queuedAt: Type.Union([ - Type.String({ - description: "When the transaction is enqueued", - }), - Type.Null(), - ]), - sentAt: Type.Union([ - Type.String({ - description: "When the transaction is submitted to mempool", - }), - Type.Null(), - ]), - minedAt: Type.Union([ - Type.String({ - description: "When the transaction is mined onchain", - }), - Type.Null(), - ]), - cancelledAt: Type.Union([ - Type.String({ - description: "When the transactino is cancelled", - }), - Type.Null(), - ]), - deployedContractAddress: Type.Union([ - Type.String({ - description: "The address for a deployed contract", - }), - Type.Null(), - ]), - deployedContractType: Type.Union([ - Type.String({ - description: "The type of a deployed contract", - }), - Type.Null(), - ]), - errorMessage: Type.Union([ - Type.String({ - description: "The error that occurred", - }), - Type.Null(), - ]), - sentAtBlockNumber: Type.Union([ - Type.Integer({ - description: - "The block number when the transaction is submitted to mempool", - }), - Type.Null(), - ]), - blockNumber: Type.Union([ - Type.Integer({ - description: "The block number when the transaction is mined", - }), - Type.Null(), - ]), - retryCount: Type.Integer({ - description: "The number of retry attempts", - }), - retryGasValues: Type.Union([ - Type.Boolean({ - description: "Whether to replace gas values on the next retry", - }), - Type.Null(), - ]), - retryMaxFeePerGas: Type.Union([ - Type.String({ - description: "The max fee per gas to use on retry", - }), - Type.Null(), - ]), - retryMaxPriorityFeePerGas: Type.Union([ - Type.String({ - description: "The max priority fee per gas to use on retry", - }), - Type.Null(), - ]), - signerAddress: Type.Union([AddressSchema, Type.Null()]), - accountAddress: Type.Union([AddressSchema, Type.Null()]), - accountSalt: Type.Union([Type.String(), Type.Null()]), - accountFactoryAddress: Type.Union([AddressSchema, Type.Null()]), - target: Type.Union([AddressSchema, Type.Null()]), - sender: Type.Union([AddressSchema, Type.Null()]), - initCode: Type.Union([Type.String(), Type.Null()]), - callData: Type.Union([Type.String(), Type.Null()]), - callGasLimit: Type.Union([Type.String(), Type.Null()]), - verificationGasLimit: Type.Union([Type.String(), Type.Null()]), - preVerificationGas: Type.Union([Type.String(), Type.Null()]), - paymasterAndData: Type.Union([Type.String(), Type.Null()]), - userOpHash: Type.Union([TransactionHashSchema, Type.Null()]), - functionName: Type.Union([Type.String(), Type.Null()]), - functionArgs: Type.Union([Type.String(), Type.Null()]), - // @deprecated - onChainTxStatus: Type.Union([Type.Integer(), Type.Null()]), - onchainStatus: Type.Union([ - Type.Literal("success"), - Type.Literal("reverted"), - Type.Null(), - ]), - effectiveGasPrice: Type.Union([ - Type.String({ - description: "Effective Gas Price", - }), - Type.Null(), - ]), - cumulativeGasUsed: Type.Union([ - Type.String({ - description: "Cumulative Gas Used", - }), - Type.Null(), - ]), - batchOperations: Type.Union([ - Type.Array( - Type.Object({ - to: Type.Union([Type.String(), Type.Null()]), - data: Type.Union([Type.String(), Type.Null()]), - value: Type.String(), - }), - ), - Type.Null(), - ]), -}); - -export const toTransactionSchema = ( - transaction: AnyTransaction, -): Static => { - // Helper resolver methods. - const resolveTransactionType = () => { - if (transaction.status === "mined") { - switch (transaction.transactionType) { - case "eip2930": - return 1; - case "eip1559": - return 2; - case "eip4844": - return 3; - default: - return 0; - } - } - return null; - }; - - const resolveOnchainTxStatus = () => { - if (transaction.status === "mined") { - return transaction.onchainStatus === "success" ? 1 : 0; - } - return null; - }; - - const resolveFunctionArgs = () => - transaction.functionArgs ? stringify(transaction.functionArgs) : null; - - const resolveTransactionHash = (): string | null => { - switch (transaction.status) { - case "sent": - if (!transaction.isUserOp) { - return transaction.sentTransactionHashes.at(-1) ?? null; - } - break; - case "mined": - return transaction.transactionHash; - } - return null; - }; - - const resolveBatchOperations = (): Static< - typeof TransactionSchema - >["batchOperations"] => { - if (!transaction.batchOperations) return null; - return transaction.batchOperations.map((op) => ({ - to: op.to ?? null, - data: op.data ?? null, - value: op.value.toString(), - })); - }; - - const resolveGas = (): string | null => { - if (transaction.status === "sent") { - return transaction.gas.toString(); - } - return transaction.overrides?.gas?.toString() ?? null; - }; - - const resolveGasPrice = (): string | null => { - if (transaction.status === "sent") { - return transaction.gasPrice?.toString() ?? null; - } - return transaction.overrides?.gasPrice?.toString() ?? null; - }; - - const resolveMaxFeePerGas = (): string | null => { - if (transaction.status === "sent") { - return transaction.maxFeePerGas?.toString() ?? null; - } - return transaction.overrides?.maxFeePerGas?.toString() ?? null; - }; - - const resolveMaxPriorityFeePerGas = (): string | null => { - if (transaction.status === "sent") { - return transaction.maxPriorityFeePerGas?.toString() ?? null; - } - return transaction.overrides?.maxPriorityFeePerGas?.toString() ?? null; - }; - - return { - queueId: transaction.queueId, - status: transaction.status, - - chainId: transaction.chainId.toString(), - fromAddress: transaction.from, - toAddress: transaction.to ?? null, - data: transaction.data ?? null, - value: transaction.value.toString(), - nonce: - "nonce" in transaction && transaction.nonce !== undefined - ? transaction.nonce - : null, - deployedContractAddress: transaction.deployedContractAddress ?? null, - deployedContractType: transaction.deployedContractType ?? null, - functionName: transaction.functionName ?? null, - functionArgs: resolveFunctionArgs(), - extension: transaction.extension ?? null, - - gasLimit: resolveGas(), - gasPrice: resolveGasPrice(), - maxFeePerGas: resolveMaxFeePerGas(), - maxPriorityFeePerGas: resolveMaxPriorityFeePerGas(), - transactionType: resolveTransactionType(), - transactionHash: resolveTransactionHash(), - queuedAt: transaction.queuedAt.toISOString(), - sentAt: "sentAt" in transaction ? transaction.sentAt.toISOString() : null, - minedAt: - "minedAt" in transaction ? transaction.minedAt.toISOString() : null, - cancelledAt: - "cancelledAt" in transaction - ? transaction.cancelledAt.toISOString() - : null, - errorMessage: - "errorMessage" in transaction ? (transaction.errorMessage ?? null) : null, - sentAtBlockNumber: - "sentAtBlock" in transaction ? Number(transaction.sentAtBlock) : null, - blockNumber: - "minedAtBlock" in transaction ? Number(transaction.minedAtBlock) : null, - retryCount: "retryCount" in transaction ? transaction.resendCount : 0, - onChainTxStatus: resolveOnchainTxStatus(), - onchainStatus: - "onchainStatus" in transaction ? transaction.onchainStatus : null, - effectiveGasPrice: - "effectiveGasPrice" in transaction && transaction.effectiveGasPrice - ? transaction.effectiveGasPrice.toString() - : null, - cumulativeGasUsed: - "cumulativeGasUsed" in transaction && transaction.cumulativeGasUsed - ? transaction.cumulativeGasUsed.toString() - : null, - - // User Operation - signerAddress: transaction.from, - accountAddress: transaction.accountAddress ?? null, - accountSalt: transaction.accountSalt ?? null, - accountFactoryAddress: transaction.accountFactoryAddress ?? null, - target: transaction.target ?? null, - sender: transaction.sender ?? null, - initCode: null, - callData: null, - callGasLimit: null, - verificationGasLimit: null, - preVerificationGas: null, - paymasterAndData: null, - userOpHash: - "userOpHash" in transaction ? (transaction.userOpHash as Hex) : null, - - batchOperations: resolveBatchOperations(), - - // Deprecated - retryGasValues: null, - retryMaxFeePerGas: null, - retryMaxPriorityFeePerGas: null, - }; -}; diff --git a/src/server/schemas/transaction/raw-transaction-parms.ts b/src/server/schemas/transaction/raw-transaction-parms.ts deleted file mode 100644 index fbf64d81a..000000000 --- a/src/server/schemas/transaction/raw-transaction-parms.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { AddressSchema, HexSchema } from "../address"; -import { WeiAmountStringSchema } from "../number"; - -export const RawTransactionParamsSchema = Type.Object({ - toAddress: Type.Optional(AddressSchema), - data: HexSchema, - value: WeiAmountStringSchema, -}); diff --git a/src/server/schemas/tx-overrides.ts b/src/server/schemas/tx-overrides.ts deleted file mode 100644 index cef4a1574..000000000 --- a/src/server/schemas/tx-overrides.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { NumberStringSchema, WeiAmountStringSchema } from "./number"; - -export const txOverridesSchema = Type.Object({ - txOverrides: Type.Optional( - Type.Object({ - gas: Type.Optional({ - ...NumberStringSchema, - examples: ["530000"], - description: "Gas limit for the transaction", - }), - - gasPrice: Type.Optional({ - ...WeiAmountStringSchema, - description: - "Gas price for the transaction. Do not use this if maxFeePerGas is set or if you want to use EIP-1559 type transactions. Only use this if you want to use legacy transactions.", - }), - maxFeePerGas: Type.Optional({ - ...WeiAmountStringSchema, - description: "Maximum fee per gas", - }), - maxPriorityFeePerGas: Type.Optional({ - ...WeiAmountStringSchema, - description: "Maximum priority fee per gas", - }), - timeoutSeconds: Type.Optional( - Type.Integer({ - examples: ["7200"], - description: - "Maximum duration that a transaction is valid. If a transaction cannot be sent before the timeout, the transaction will be set to 'errored'. Default: no timeout", - minimum: 1, - maximum: 7 * 24 * 60 * 60, // 1 week - }), - ), - }), - ), -}); - -export const txOverridesWithValueSchema = Type.Object({ - txOverrides: Type.Optional( - Type.Object({ - ...txOverridesSchema.properties.txOverrides.properties, - value: Type.Optional({ - ...WeiAmountStringSchema, - description: - "Amount of native currency in wei to send with this transaction. Used to transfer funds or pay a contract.", - }), - }), - ), -}); diff --git a/src/server/schemas/wallet/index.ts b/src/server/schemas/wallet/index.ts deleted file mode 100644 index ec1aa8e8a..000000000 --- a/src/server/schemas/wallet/index.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { getAddress, type Address } from "thirdweb"; -import { env } from "../../../shared/utils/env"; -import { badAddressError } from "../../middleware/error"; -import { AddressSchema } from "../address"; -import { chainIdOrSlugSchema } from "../chain"; - -export const walletHeaderSchema = Type.Object({ - "x-backend-wallet-address": { - ...AddressSchema, - description: "Backend wallet address", - }, - "x-idempotency-key": Type.Optional( - Type.String({ - maxLength: 200, - description: `Transactions submitted with the same idempotency key will be de-duplicated. Only the last ${env.TRANSACTION_HISTORY_COUNT} transactions are compared.`, - }), - ), - "x-transaction-mode": Type.Optional( - Type.Union( - [ - Type.Literal("sponsored", { - description: "Attempt to use native AA on ZKSync chains", - }), - ], - { - description: - "Transaction mode to use for EOA transactions. Will be ignored if using a smart wallet. If omitted, defaults to regular EOA transactions.", - }, - ), - ), -}); - -export const walletWithAAHeaderSchema = Type.Object({ - ...walletHeaderSchema.properties, - "x-account-address": Type.Optional({ - ...AddressSchema, - description: "Smart account address", - examples: [], - }), - "x-account-factory-address": Type.Optional({ - ...AddressSchema, - description: - "Smart account factory address. If omitted, Engine will try to resolve it from the contract.", - examples: [], - }), - "x-account-salt": Type.Optional( - Type.String({ - description: - "Smart account salt as string or hex. This is used to predict the smart account address. Useful when creating multiple accounts with the same admin and only needed when deploying the account as part of a userop.", - }), - ), -}); - -/** - * Helper function to parse an address string. - * Returns undefined if the address is undefined. - * - * Throws a custom 422 INVALID_ADDRESS error with variableName if the address is invalid (other than undefined). - */ -export function maybeAddress( - address: string | undefined, - variableName: string, -): Address | undefined { - if (!address) return undefined; - try { - return getAddress(address); - } catch { - throw badAddressError(variableName); - } -} - -/** - * Same as maybeAddress, but throws if the address is undefined. - */ -export function requiredAddress( - address: string | undefined, - variableName: string, -): Address { - const parsedAddress = maybeAddress(address, variableName); - if (!parsedAddress) throw badAddressError(variableName); - return parsedAddress; -} - -export const walletChainParamSchema = Type.Object({ - chain: chainIdOrSlugSchema, -}); - -export const walletWithAddressParamSchema = Type.Object({ - ...walletChainParamSchema.properties, - walletAddress: { - ...AddressSchema, - description: "Backend wallet address", - }, -}); diff --git a/src/server/schemas/webhook.ts b/src/server/schemas/webhook.ts deleted file mode 100644 index 3e7fbc36d..000000000 --- a/src/server/schemas/webhook.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Webhooks } from "@prisma/client"; -import { Type, type Static } from "@sinclair/typebox"; - -export const WebhookSchema = Type.Object({ - id: Type.Integer(), - url: Type.String(), - name: Type.Union([Type.String(), Type.Null()]), - secret: Type.Optional(Type.String()), - eventType: Type.String(), - active: Type.Boolean(), - createdAt: Type.String(), -}); - -export const toWebhookSchema = ( - webhook: Webhooks, -): Static => ({ - url: webhook.url, - name: webhook.name, - eventType: webhook.eventType, - secret: webhook.secret, - createdAt: webhook.createdAt.toISOString(), - active: !webhook.revokedAt, - id: webhook.id, -}); diff --git a/src/server/schemas/websocket/index.ts b/src/server/schemas/websocket/index.ts deleted file mode 100644 index 77b68f082..000000000 --- a/src/server/schemas/websocket/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// types.ts -import type { WebSocket } from "ws"; - -export interface UserSubscription { - socket: WebSocket; - requestId: string; -} - -export const subscriptionsData: UserSubscription[] = []; diff --git a/src/server/utils/abi.ts b/src/server/utils/abi.ts deleted file mode 100644 index cedb50414..000000000 --- a/src/server/utils/abi.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Abi } from "thirdweb/utils"; -import type { AbiSchemaType } from "../schemas/contract"; - -export function sanitizeAbi(abi: AbiSchemaType | undefined): Abi | undefined { - if (!abi) { - return undefined; - } - - return abi.map((item) => { - if (item.type === "function") { - return { - ...item, - // older versions of engine allowed passing in empty inputs/outputs, but necesasry for abi validation - inputs: item.inputs || [], - outputs: item.outputs || [], - }; - } - return item; - }) as Abi; -} - -export const sanitizeFunctionName = (val: string) => - val.includes("(") && !val.startsWith("function ") ? `function ${val}` : val; diff --git a/src/server/utils/chain.ts b/src/server/utils/chain.ts deleted file mode 100644 index b0e5c7d7b..000000000 --- a/src/server/utils/chain.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { getChainBySlugAsync } from "@thirdweb-dev/chains"; -import { getChain } from "../../shared/utils/chain"; -import { badChainError } from "../middleware/error"; - -/** - * Given a valid chain name ('Polygon') or ID ('137'), return the numeric chain ID. - * @throws if the chain is invalid or deprecated. - */ -export const getChainIdFromChain = async (input: string): Promise => { - const chainId = Number.parseInt(input); - if (!Number.isNaN(chainId)) { - return (await getChain(chainId)).id; - } - - try { - const chainV4 = await getChainBySlugAsync(input.toLowerCase()); - if (chainV4.status !== "deprecated") { - return chainV4.chainId; - } - } catch {} - - throw badChainError(input); -}; diff --git a/src/server/utils/convertor.ts b/src/server/utils/convertor.ts deleted file mode 100644 index 5f0334679..000000000 --- a/src/server/utils/convertor.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { BigNumber } from "ethers"; - -const isHexBigNumber = (value: unknown) => { - const isNonNullObject = typeof value === "object" && value !== null; - const hasType = isNonNullObject && "type" in value; - return hasType && value.type === "BigNumber" && "hex" in value -} -export const bigNumberReplacer = (value: unknown): unknown => { - // if we find a BigNumber then make it into a string (since that is safe) - if (BigNumber.isBigNumber(value) || isHexBigNumber(value)) { - return BigNumber.from(value).toString(); - } - - if (Array.isArray(value)) { - return value.map(bigNumberReplacer); - } - - return value; -}; diff --git a/src/server/utils/cors-urls.ts b/src/server/utils/cors-urls.ts deleted file mode 100644 index cb94c87e5..000000000 --- a/src/server/utils/cors-urls.ts +++ /dev/null @@ -1,5 +0,0 @@ -// URLs to check and add if missing -export const mandatoryAllowedCorsUrls = [ - "https://thirdweb.com/", - "https://embed.ipfscdn.io/", -]; diff --git a/src/server/utils/marketplace-v3.ts b/src/server/utils/marketplace-v3.ts deleted file mode 100644 index 9b9560cce..000000000 --- a/src/server/utils/marketplace-v3.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { DirectListingV3, EnglishAuction, OfferV3 } from "@thirdweb-dev/sdk"; - -export const formatDirectListingV3Result = (listing: DirectListingV3) => { - return { - ...listing, - currencyValuePerToken: { - ...listing.currencyValuePerToken, - value: listing.currencyValuePerToken.value.toString(), - }, - }; -}; - -export const formatEnglishAuctionResult = (listing: EnglishAuction) => { - return { - ...listing, - minimumBidCurrencyValue: { - ...listing.minimumBidCurrencyValue, - value: listing.minimumBidCurrencyValue.value.toString(), - }, - buyoutCurrencyValue: { - ...listing.buyoutCurrencyValue, - value: listing.buyoutCurrencyValue.value.toString(), - }, - }; -}; - -export const formatOffersV3Result = (offer: OfferV3) => { - return { - ...offer, - currencyValue: { - ...offer.currencyValue, - value: offer.currencyValue.value.toString(), - }, - }; -}; diff --git a/src/server/utils/openapi.ts b/src/server/utils/openapi.ts deleted file mode 100644 index 3dd14ea76..000000000 --- a/src/server/utils/openapi.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { FastifyInstance } from "fastify"; -import fs from "node:fs"; - -export const writeOpenApiToFile = (server: FastifyInstance) => { - try { - fs.writeFileSync( - "./dist/openapi.json", - JSON.stringify(server.swagger(), undefined, 2), - ); - } catch { - // no-op - } -}; diff --git a/src/server/utils/storage/local-storage.ts b/src/server/utils/storage/local-storage.ts deleted file mode 100644 index 95665f675..000000000 --- a/src/server/utils/storage/local-storage.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { AsyncStorage } from "@thirdweb-dev/wallets"; -import fs from "node:fs"; -import { prisma } from "../../../shared/db/client"; -import { WalletType } from "../../../shared/schemas/wallet"; -import { logger } from "../../../shared/utils/logger"; - -/** - * @deprecated - * Deprecated local file storage implementation for use with v4 sdk - * Use `legacyLocalCrypto` for encryption and decryption instead - */ -export class LocalFileStorage implements AsyncStorage { - label?: string; - - constructor( - private readonly walletAddress: string, - label?: string, - ) { - this.walletAddress = walletAddress.toLowerCase(); - this.label = label; - } - - async getItem(_: string): Promise { - const walletDetails = await prisma.walletDetails.findUnique({ - where: { - address: this.walletAddress, - }, - }); - - if (walletDetails?.encryptedJson) { - return walletDetails.encryptedJson; - } - - // For backwards compatibility, support old local file storage format - const dir = `${process.env.HOME}/.thirdweb`; - const path = `${dir}/localWallet-${this.walletAddress}`; - if (!fs.existsSync(dir) || !fs.existsSync(path)) { - logger({ - service: "server", - level: "error", - message: "No local wallet found!", - }); - return null; - } - - // Save the encrypted json in the database for future access - const encryptedJson = fs.readFileSync(path, "utf8"); - await this.setItem("", encryptedJson); - - return encryptedJson; - } - - async setItem(_: string, value: string): Promise { - await prisma.walletDetails.upsert({ - where: { - address: this.walletAddress, - type: WalletType.local, - }, - create: { - address: this.walletAddress, - type: WalletType.local, - encryptedJson: value, - label: this.label, - }, - update: { - encryptedJson: value, - label: this.label, - }, - }); - } - - async removeItem(_: string): Promise { - await prisma.walletDetails.delete({ - where: { - address: this.walletAddress, - type: WalletType.local, - }, - }); - } -} diff --git a/src/server/utils/transaction-overrides.ts b/src/server/utils/transaction-overrides.ts deleted file mode 100644 index 443758ef0..000000000 --- a/src/server/utils/transaction-overrides.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Static } from "@sinclair/typebox"; -import { maybeBigInt } from "../../shared/utils/primitive-types"; -import type { InsertedTransaction } from "../../shared/utils/transaction/types"; -import type { - txOverridesSchema, - txOverridesWithValueSchema, -} from "../schemas/tx-overrides"; - -export const parseTransactionOverrides = ( - overrides: - | Static["txOverrides"] - | Static["txOverrides"], -): Partial => { - if (!overrides) { - return {}; - } - - return { - overrides: { - gas: maybeBigInt(overrides.gas), - gasPrice: maybeBigInt(overrides.gasPrice), - maxFeePerGas: maybeBigInt(overrides.maxFeePerGas), - maxPriorityFeePerGas: maybeBigInt(overrides.maxPriorityFeePerGas), - }, - timeoutSeconds: overrides.timeoutSeconds, - // `value` may not be in the overrides object. - value: "value" in overrides ? maybeBigInt(overrides.value) : undefined, - }; -}; diff --git a/src/server/utils/validator.ts b/src/server/utils/validator.ts deleted file mode 100644 index a72f4b5da..000000000 --- a/src/server/utils/validator.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { Static } from "@sinclair/typebox"; -import { customDateTimestampError } from "../middleware/error"; -import type { - erc20ResponseType, - signature20InputSchema, -} from "../schemas/erc20"; -import type { - ercNFTResponseType, - signature1155InputSchema, - signature721InputSchema, -} from "../schemas/nft"; - -const timestampValidator = (value: number | string | undefined): boolean => { - let timestamp = value; - if (timestamp === undefined) { - return true; - } - - if (!Number.isNaN(Number(timestamp))) { - timestamp = Number(timestamp); - } - - return new Date(timestamp).getTime() > 0; -}; - -export const checkAndReturnERC20SignaturePayload = < - T extends Static, - U extends erc20ResponseType, ->( - payload: T, -): U => { - if (!timestampValidator(payload.mintStartTime)) { - throw customDateTimestampError("mintStartTime"); - } - - if (!timestampValidator(payload.mintEndTime)) { - throw customDateTimestampError("mintEndTime"); - } - - if (!Number.isNaN(Number(payload.mintEndTime))) { - payload.mintEndTime = Number(payload.mintEndTime); - } - - if (!Number.isNaN(Number(payload.mintStartTime))) { - payload.mintStartTime = Number(payload.mintStartTime); - } - - const updatedPayload: U = payload as unknown as U; - updatedPayload.mintEndTime = payload.mintEndTime - ? new Date(payload.mintEndTime) - : undefined; - updatedPayload.mintStartTime = payload.mintStartTime - ? new Date(payload.mintStartTime) - : undefined; - - return updatedPayload; -}; - -export const checkAndReturnNFTSignaturePayload = < - T extends - | Static - | Static, - U extends ercNFTResponseType, ->( - payload: T, -): U => { - if (!timestampValidator(payload.mintStartTime)) { - throw customDateTimestampError("mintStartTime"); - } - - if (!timestampValidator(payload.mintEndTime)) { - throw customDateTimestampError("mintEndTime"); - } - - if (!Number.isNaN(Number(payload.mintEndTime))) { - payload.mintEndTime = Number(payload.mintEndTime); - } - - if (!Number.isNaN(Number(payload.mintStartTime))) { - payload.mintStartTime = Number(payload.mintStartTime); - } - - const updatedPayload: U = payload as unknown as U; - updatedPayload.mintEndTime = payload.mintEndTime - ? new Date(payload.mintEndTime) - : undefined; - updatedPayload.mintStartTime = payload.mintStartTime - ? new Date(payload.mintStartTime) - : undefined; - - return updatedPayload; -}; - -export const isValidWebhookUrl = (input: string): boolean => { - try { - const url = new URL(input); - return ( - url.protocol === "https:" || - // Allow http for localhost only. - (url.protocol === "http:" && - ["localhost", "0.0.0.0", "127.0.0.1"].includes(url.hostname)) - ); - } catch { - return false; - } -}; - -export const isUnixEpochTimestamp = (timestamp: number): boolean => { - const date = new Date(timestamp); - return date.getFullYear() === 1970; -}; diff --git a/src/server/utils/wallets/aws-kms-arn.ts b/src/server/utils/wallets/aws-kms-arn.ts deleted file mode 100644 index 29f4b32da..000000000 --- a/src/server/utils/wallets/aws-kms-arn.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Split an AWS KMS ARN into its parts. - */ -export function splitAwsKmsArn(arn: string) { - // arn:aws:kms:::key/ - const parts = arn.split(":"); - if (parts.length < 6) { - throw new Error("Invalid AWS KMS ARN"); - } - - const keyId = parts[5].split("/")[1]; - if (!keyId) { - throw new Error("Invalid AWS KMS ARN"); - } - const keyIdExtension = parts.slice(6).join(":"); - - return { - region: parts[3], - accountId: parts[4], - keyId: `${keyId}${keyIdExtension ? `:${keyIdExtension}` : ""}`, - }; -} - -/** - * Get an AWS KMS ARN from its parts. - */ -export function getAwsKmsArn(options: { - region: string; - accountId: string; - keyId: string; -}) { - return `arn:aws:kms:${options.region}:${options.accountId}:key/${options.keyId}`; -} diff --git a/src/server/utils/wallets/circle/index.ts b/src/server/utils/wallets/circle/index.ts deleted file mode 100644 index 5f1759530..000000000 --- a/src/server/utils/wallets/circle/index.ts +++ /dev/null @@ -1,338 +0,0 @@ -import { initiateDeveloperControlledWalletsClient } from "@circle-fin/developer-controlled-wallets"; -import { getConfig } from "../../../../shared/utils/cache/get-config"; -import { getWalletCredential } from "../../../../shared/db/wallet-credentials/get-wallet-credential"; -import { - type Address, - eth_sendRawTransaction, - getRpcClient, - type Hex, - serializeTransaction, - type ThirdwebClient, - toHex, - type toSerializableTransaction, -} from "thirdweb"; -import { getChain } from "../../../../shared/utils/chain"; -import { - parseSignature, - type SignableMessage, - type TypedData, - type TypedDataDefinition, -} from "viem"; -import type { Account } from "thirdweb/wallets"; -import { thirdwebClient } from "../../../../shared/utils/sdk"; -import { prisma } from "../../../../shared/db/client"; -import { getConnectedSmartWallet } from "../create-smart-wallet"; -import { - DEFAULT_ACCOUNT_FACTORY_V0_7, - ENTRYPOINT_ADDRESS_v0_7, -} from "thirdweb/wallets/smart"; -import { stringify } from "thirdweb/utils"; - -export class CircleWalletError extends Error { - constructor(message: string) { - super(message); - this.name = "CircleWalletError"; - } -} - -export async function provisionCircleWallet({ - entitySecret, - apiKey, - walletSetId, - client, - isTestnet, -}: { - entitySecret: string; - apiKey: string; - walletSetId?: string; - client: ThirdwebClient; - isTestnet?: boolean; -}) { - const circleDeveloperSdk = initiateDeveloperControlledWalletsClient({ - apiKey: apiKey, - entitySecret: entitySecret, - }); - - if (!walletSetId) { - const walletSet = await circleDeveloperSdk - .createWalletSet({ - name: `Engine WalletSet ${new Date().toISOString()}`, - }) - .catch((e) => { - throw new CircleWalletError( - `[Circle] Could not create walletset:\n${JSON.stringify( - e?.response?.data, - )}`, - ); - }); - - walletSetId = walletSet.data?.walletSet.id; - if (!walletSetId) - throw new CircleWalletError( - "Did not receive walletSetId, and failed to create one automatically", - ); - } - - const provisionWalletResponse = await circleDeveloperSdk - .createWallets({ - accountType: "EOA", - blockchains: [isTestnet ? "EVM-TESTNET" : "EVM"], - count: 1, - walletSetId: walletSetId, - }) - .catch((e) => { - throw new CircleWalletError( - `[Circle] Could not provision wallet:\n${JSON.stringify( - e?.response?.data, - )}`, - ); - }); - - const provisionedWallet = provisionWalletResponse.data?.wallets?.[0]; - - if (!provisionedWallet) - throw new CircleWalletError("Did not receive provisioned wallet"); - - const circleAccount = await getCircleAccount({ - walletId: provisionedWallet.id, - apiKey: apiKey, - entitySecret: entitySecret, - client, - }); - - return { - walletSetId, - provisionedWallet: provisionedWallet, - account: circleAccount, - }; -} - -type SerializableTransaction = Awaited< - ReturnType ->; - -type SendTransactionOptions = SerializableTransaction & { - chainId: number; -}; - -type SendTransactionResult = { - transactionHash: Hex; -}; - -type CircleAccount = Account; - -export async function getCircleAccount({ - walletId, - apiKey, - entitySecret, - client, -}: { - walletId: string; - apiKey: string; - entitySecret: string; - client: ThirdwebClient; -}) { - const circleDeveloperSdk = initiateDeveloperControlledWalletsClient({ - apiKey, - entitySecret, - }); - - const walletResponse = await circleDeveloperSdk - .getWallet({ id: walletId }) - .catch((e) => { - throw new CircleWalletError( - `[Circle] Could not get wallet with id:${walletId}:\n${JSON.stringify( - e?.response?.data, - )}`, - ); - }); - - if (!walletResponse) { - throw new CircleWalletError( - `Unable to get circle wallet with id:${walletId}`, - ); - } - const wallet = walletResponse.data?.wallet; - const address = wallet?.address as Address; - - async function signTransaction(tx: SerializableTransaction) { - const signature = await circleDeveloperSdk - .signTransaction({ - walletId, - transaction: stringify(tx), - }) - .catch((e) => { - throw new CircleWalletError( - `[Circle] Could not get transaction signature:\n${JSON.stringify( - e?.response?.data, - )}`, - ); - }); - - if (!signature.data?.signature) { - throw new CircleWalletError("Unable to sign transaction"); - } - - return signature.data.signature as Hex; - } - - async function sendTransaction( - tx: SendTransactionOptions, - ): Promise { - const rpcRequest = getRpcClient({ - client: client, - chain: await getChain(tx.chainId), - }); - - const signature = await signTransaction(tx); - const splittedSignature = parseSignature(signature); - - const signedTransaction = serializeTransaction({ - transaction: tx, - signature: splittedSignature, - }); - - const transactionHash = await eth_sendRawTransaction( - rpcRequest, - signedTransaction, - ); - return { transactionHash }; - } - - async function signTypedData< - const typedData extends TypedData | Record, - primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, - >(_typedData: TypedDataDefinition): Promise { - const signatureResponse = await circleDeveloperSdk - .signTypedData({ - data: stringify(_typedData), - walletId, - }) - .catch((e) => { - throw new CircleWalletError( - `[Circle] Could not get signature:\n${JSON.stringify( - e?.response?.data, - )}`, - ); - }); - - if (!signatureResponse.data?.signature) { - throw new CircleWalletError("Could not sign typed data"); - } - - return signatureResponse.data?.signature as Hex; - } - - async function signMessage({ - message, - }: { - message: SignableMessage; - }): Promise { - const isRawMessage = typeof message === "object" && "raw" in message; - let messageToSign = isRawMessage ? message.raw : message; - - if (typeof messageToSign !== "string") { - messageToSign = toHex(messageToSign); - } - - const signatureResponse = await circleDeveloperSdk - .signMessage({ - walletId, - message: messageToSign, - encodedByHex: isRawMessage, - }) - .catch((e) => { - throw new CircleWalletError( - `[Circle] Could not get signature:\n${JSON.stringify( - e?.response?.data, - )}`, - ); - }); - - if (!signatureResponse.data?.signature) - throw new CircleWalletError("Could not get signature"); - return signatureResponse.data?.signature as Hex; - } - - return { - address, - sendTransaction, - signMessage, - signTypedData, - signTransaction, - } as CircleAccount satisfies Account; -} - -export async function createCircleWalletDetails({ - credentialId, - walletSetId, - label, - isSmart, - isTestnet, -}: { - credentialId: string; - walletSetId?: string; - label?: string; - isSmart: boolean; - isTestnet?: boolean; -}) { - const { - walletConfiguration: { circle }, - } = await getConfig(); - - if (!circle) { - throw new CircleWalletError( - "Circle wallet configuration not found. Please check your configuration.", - ); - } - - const credential = await getWalletCredential({ - id: credentialId, - }); - - if (credential.type !== "circle") { - throw new CircleWalletError( - `Invalid Credential: not valid type, expected circle received ${credential.type}`, - ); - } - - const provisionedDetails = await provisionCircleWallet({ - entitySecret: credential.data.entitySecret, - apiKey: circle.apiKey, - client: thirdwebClient, - walletSetId, - isTestnet, - }); - - let address = provisionedDetails.account.address; - - const sbwDetails = { - accountFactoryAddress: DEFAULT_ACCOUNT_FACTORY_V0_7, - entrypointAddress: ENTRYPOINT_ADDRESS_v0_7, - accountSignerAddress: address, - } as const; - - if (isSmart) { - const smartAccount = await getConnectedSmartWallet({ - adminAccount: provisionedDetails.account, - ...sbwDetails, - }); - - address = smartAccount.address; - } - - return await prisma.walletDetails.create({ - data: { - address: address.toLowerCase(), - type: isSmart ? "smart:circle" : "circle", - label: label, - credentialId, - platformIdentifiers: { - circleWalletId: provisionedDetails.provisionedWallet.id, - walletSetId: provisionedDetails.walletSetId, - isTestnet: isTestnet ?? false, - }, - ...(isSmart ? sbwDetails : {}), - }, - }); -} diff --git a/src/server/utils/wallets/create-aws-kms-wallet.ts b/src/server/utils/wallets/create-aws-kms-wallet.ts deleted file mode 100644 index 1398db8c0..000000000 --- a/src/server/utils/wallets/create-aws-kms-wallet.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { CreateKeyCommand, KMSClient } from "@aws-sdk/client-kms"; -import { - FetchAwsKmsWalletParamsError, - fetchAwsKmsWalletParams, - type AwsKmsWalletParams, -} from "./fetch-aws-kms-wallet-params"; -import { importAwsKmsWallet } from "./import-aws-kms-wallet"; - -export type CreateAwsKmsWalletParams = { - label?: string; -} & Partial; - -export class CreateAwsKmsWalletError extends Error {} - -/** - * Create an AWS KMS wallet, and store it into the database - * All optional parameters are overrides for the configuration in the database - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - * Credentials (awsAccessKeyId and awsSecretAccessKey) are explicitly stored separately from the global configuration - */ -export const createAwsKmsWalletDetails = async ({ - label, - ...overrides -}: CreateAwsKmsWalletParams): Promise => { - const { awsKmsArn, params } = await createAwsKmsKey(overrides); - - return importAwsKmsWallet({ - awsKmsArn, - label, - crendentials: { - accessKeyId: params.awsAccessKeyId, - secretAccessKey: params.awsSecretAccessKey, - }, - }); -}; - -/** - * Creates an AWS KMS wallet and returns the AWS KMS ARN - * All optional parameters are overrides for the configuration in the database - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - */ -export const createAwsKmsKey = async ( - partialParams: Partial, -) => { - let params: AwsKmsWalletParams; - try { - params = await fetchAwsKmsWalletParams(partialParams); - } catch (e) { - if (e instanceof FetchAwsKmsWalletParamsError) { - throw new CreateAwsKmsWalletError(e.message); - } - throw e; - } - - const client = new KMSClient({ - region: params.awsRegion, - credentials: { - accessKeyId: params.awsAccessKeyId, - secretAccessKey: params.awsSecretAccessKey, - }, - }); - - const res = await client.send( - new CreateKeyCommand({ - Description: "thirdweb Engine AWS KMS Backend Wallet", - KeyUsage: "SIGN_VERIFY", - KeySpec: "ECC_SECG_P256K1", - MultiRegion: false, - }), - ); - - if (!res.KeyMetadata?.Arn) { - throw new Error("Failed to create AWS KMS key"); - } - - const awsKmsArn = res.KeyMetadata.Arn; - - return { - awsKmsArn, - params: params, - }; -}; diff --git a/src/server/utils/wallets/create-gcp-kms-wallet.ts b/src/server/utils/wallets/create-gcp-kms-wallet.ts deleted file mode 100644 index 7a040f760..000000000 --- a/src/server/utils/wallets/create-gcp-kms-wallet.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { KeyManagementServiceClient } from "@google-cloud/kms"; -import { createWalletDetails } from "../../../shared/db/wallets/create-wallet-details"; -import { WalletType } from "../../../shared/schemas/wallet"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { - FetchGcpKmsWalletParamsError, - fetchGcpKmsWalletParams, - type GcpKmsWalletParams, -} from "./fetch-gcp-kms-wallet-params"; -import { getGcpKmsResourcePath } from "./gcp-kms-resource-path"; -import { getGcpKmsAccount } from "./get-gcp-kms-account"; - -export type CreateGcpKmsWalletParams = { - label?: string; -} & Partial; - -export class CreateGcpKmsWalletError extends Error {} - -/** - * Create a GCP KMS wallet, and store it into the database - * All optional parameters are overrides for the configuration in the database - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - * Credentials (gcpApplicationCredentialEmail and gcpApplicationCredentialPrivateKey) are stored separately from the global configuration - */ -export const createGcpKmsWalletDetails = async ({ - label, - ...overrides -}: CreateGcpKmsWalletParams): Promise => { - const { walletAddress, resourcePath, params } = - await createGcpKmsKey(overrides); - - await createWalletDetails({ - type: WalletType.gcpKms, - address: walletAddress, - label, - gcpKmsResourcePath: resourcePath, - - gcpApplicationCredentialEmail: params.gcpApplicationCredentialEmail, - gcpApplicationCredentialPrivateKey: - params.gcpApplicationCredentialPrivateKey, - }); - - return walletAddress; -}; - -/** - * Creates a GCP KMS wallet and returns the GCP KMS resource path. DOES NOT store the wallet in the database. - * All optional parameters are overrides for the configuration in the database - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - */ -export const createGcpKmsKey = async ( - partialParams: Partial, -) => { - let params: GcpKmsWalletParams; - try { - params = await fetchGcpKmsWalletParams(partialParams); - } catch (e) { - if (e instanceof FetchGcpKmsWalletParamsError) { - throw new CreateGcpKmsWalletError(e.message); - } - throw e; - } - - const client = new KeyManagementServiceClient({ - credentials: { - client_email: params.gcpApplicationCredentialEmail, - private_key: params.gcpApplicationCredentialPrivateKey - .split(String.raw`\n`) - .join("\n"), - }, - projectId: params.gcpApplicationProjectId, - }); - - // TODO: What should we set this to? - const cryptoKeyId = `ec-web3api-${new Date().getTime()}`; - const [key] = await client.createCryptoKey({ - parent: client.keyRingPath( - params.gcpApplicationProjectId, - params.gcpKmsLocationId, - params.gcpKmsKeyRingId, - ), - cryptoKeyId, - cryptoKey: { - purpose: "ASYMMETRIC_SIGN", - versionTemplate: { - algorithm: "EC_SIGN_SECP256K1_SHA256", - protectionLevel: "HSM", - }, - }, - }); - - await client.close(); - - const resourcePath = getGcpKmsResourcePath({ - projectId: params.gcpApplicationProjectId, - locationId: params.gcpKmsLocationId, - keyRingId: params.gcpKmsKeyRingId, - cryptoKeyId: cryptoKeyId, - versionId: "1", - }); - - if (`${key.name}/cryptoKeyVersions/1` !== resourcePath) { - throw new CreateGcpKmsWalletError( - `Expected created key resource path to be ${resourcePath}, but got ${key.name}`, - ); - } - - const account = await getGcpKmsAccount({ - client: thirdwebClient, - name: resourcePath, - clientOptions: { - credentials: { - client_email: params.gcpApplicationCredentialEmail, - private_key: params.gcpApplicationCredentialPrivateKey, - }, - }, - }); - - const walletAddress = account.address; - - return { - walletAddress, - resourcePath, - params, - }; -}; diff --git a/src/server/utils/wallets/create-local-wallet.ts b/src/server/utils/wallets/create-local-wallet.ts deleted file mode 100644 index 2a1d3d7bd..000000000 --- a/src/server/utils/wallets/create-local-wallet.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { encryptKeystore } from "@ethersproject/json-wallets"; -import { privateKeyToAccount } from "thirdweb/wallets"; -import { generatePrivateKey } from "viem/accounts"; -import { createWalletDetails } from "../../../shared/db/wallets/create-wallet-details"; -import { env } from "../../../shared/utils/env"; -import { thirdwebClient } from "../../../shared/utils/sdk"; - -interface CreateLocalWallet { - label?: string; -} - -/** - * Create a local wallet with a random private key - * Does not store the wallet in the database - */ -export const generateLocalWallet = async () => { - const pk = generatePrivateKey(); - const account = privateKeyToAccount({ - client: thirdwebClient, - privateKey: pk, - }); - - const encryptedJsonData = await encryptKeystore( - { - address: account.address, - privateKey: pk, - }, - env.ENCRYPTION_PASSWORD, - ); - - return { - account, - // these exact values are stored for backwards compatibility - // only the encryptedJson is used for loading the wallet - encryptedJson: JSON.stringify({ - data: encryptedJsonData, - address: account.address, - strategy: "encryptedJson", - isEncrypted: true, - }), - }; -}; - -/** - * Creates a local wallet and stores it in the database - */ -export const createLocalWalletDetails = async ({ - label, -}: CreateLocalWallet): Promise => { - const { account, encryptedJson } = await generateLocalWallet(); - - await createWalletDetails({ - type: "local", - address: account.address, - label, - encryptedJson, - }); - - return account.address; -}; diff --git a/src/server/utils/wallets/create-smart-wallet.ts b/src/server/utils/wallets/create-smart-wallet.ts deleted file mode 100644 index 555f6e70f..000000000 --- a/src/server/utils/wallets/create-smart-wallet.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { defineChain, type Address, type Chain } from "thirdweb"; -import { smartWallet, type Account } from "thirdweb/wallets"; -import { createWalletDetails } from "../../../shared/db/wallets/create-wallet-details"; -import { WalletType } from "../../../shared/schemas/wallet"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { splitAwsKmsArn } from "./aws-kms-arn"; -import { - createAwsKmsKey, - type CreateAwsKmsWalletParams, -} from "./create-aws-kms-wallet"; -import { - createGcpKmsKey, - type CreateGcpKmsWalletParams, -} from "./create-gcp-kms-wallet"; -import { generateLocalWallet } from "./create-local-wallet"; -import { getAwsKmsAccount } from "./get-aws-kms-account"; -import { getGcpKmsAccount } from "./get-gcp-kms-account"; - -/** - * Get a smart wallet address for a given admin account - * Optionally specify the account factory address, and entrypoint address - * If no network is specified, it will default to ethereum mainnet - */ -export const getConnectedSmartWallet = async ({ - adminAccount, - accountFactoryAddress, - entrypointAddress, - chain, -}: { - adminAccount: Account; - accountFactoryAddress?: Address; - entrypointAddress?: Address; - chain?: Chain; -}) => { - const smartAccount = smartWallet({ - chain: chain ?? defineChain(1), - sponsorGas: true, - factoryAddress: accountFactoryAddress, - overrides: { - entrypointAddress, - }, - }); - - return await smartAccount.connect({ - client: thirdwebClient, - personalAccount: adminAccount, - }); -}; - -export type CreateSmartAwsWalletParams = CreateAwsKmsWalletParams & { - accountFactoryAddress?: Address; - entrypointAddress?: Address; -}; - -export const createSmartAwsWalletDetails = async ({ - label, - accountFactoryAddress, - entrypointAddress, - ...awsKmsWalletParams -}: CreateSmartAwsWalletParams) => { - const awsKmsWallet = await createAwsKmsKey(awsKmsWalletParams); - - const { keyId } = splitAwsKmsArn(awsKmsWallet.awsKmsArn); - - const adminAccount = await getAwsKmsAccount({ - client: thirdwebClient, - keyId, - config: { - region: awsKmsWallet.params.awsRegion, - credentials: { - accessKeyId: awsKmsWallet.params.awsAccessKeyId, - secretAccessKey: awsKmsWallet.params.awsSecretAccessKey, - }, - }, - }); - - const smartWallet = await getConnectedSmartWallet({ - adminAccount, - accountFactoryAddress, - entrypointAddress, - }); - - return await createWalletDetails({ - type: WalletType.smartAwsKms, - - address: smartWallet.address, - accountFactoryAddress, - entrypointAddress, - accountSignerAddress: adminAccount.address as Address, - - awsKmsArn: awsKmsWallet.awsKmsArn, - awsKmsAccessKeyId: awsKmsWallet.params.awsAccessKeyId, - awsKmsSecretAccessKey: awsKmsWallet.params.awsSecretAccessKey, - label: label, - }); -}; - -export type CreateSmartGcpWalletParams = CreateGcpKmsWalletParams & { - accountFactoryAddress?: Address; - entrypointAddress?: Address; -}; - -export const createSmartGcpWalletDetails = async ({ - label, - accountFactoryAddress, - entrypointAddress, - ...gcpKmsWalletParams -}: CreateSmartGcpWalletParams) => { - const gcpKmsWallet = await createGcpKmsKey(gcpKmsWalletParams); - - const adminAccount = await getGcpKmsAccount({ - client: thirdwebClient, - name: gcpKmsWallet.resourcePath, - clientOptions: { - credentials: { - private_key: gcpKmsWallet.params.gcpApplicationCredentialPrivateKey, - client_email: gcpKmsWallet.params.gcpApplicationCredentialEmail, - }, - }, - }); - - const smartWallet = await getConnectedSmartWallet({ - adminAccount, - accountFactoryAddress, - entrypointAddress, - }); - - return await createWalletDetails({ - type: WalletType.smartGcpKms, - address: smartWallet.address, - accountSignerAddress: adminAccount.address as Address, - accountFactoryAddress, - entrypointAddress, - gcpKmsResourcePath: gcpKmsWallet.resourcePath, - gcpApplicationCredentialEmail: - gcpKmsWallet.params.gcpApplicationCredentialEmail, - gcpApplicationCredentialPrivateKey: - gcpKmsWallet.params.gcpApplicationCredentialPrivateKey, - label: label, - }); -}; - -export type CreateSmartLocalWalletParams = { - label?: string; - accountFactoryAddress?: Address; - entrypointAddress?: Address; -}; - -export const createSmartLocalWalletDetails = async ({ - label, - accountFactoryAddress, - entrypointAddress, -}: CreateSmartLocalWalletParams) => { - const { account, encryptedJson } = await generateLocalWallet(); - - const wallet = await getConnectedSmartWallet({ - adminAccount: account, - accountFactoryAddress, - entrypointAddress, - }); - - return await createWalletDetails({ - type: WalletType.smartLocal, - address: wallet.address, - accountSignerAddress: account.address as Address, - accountFactoryAddress, - entrypointAddress, - encryptedJson, - label: label, - }); -}; diff --git a/src/server/utils/wallets/fetch-aws-kms-wallet-params.ts b/src/server/utils/wallets/fetch-aws-kms-wallet-params.ts deleted file mode 100644 index 0b0f46ef5..000000000 --- a/src/server/utils/wallets/fetch-aws-kms-wallet-params.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { getConfig } from "../../../shared/utils/cache/get-config"; - -export type AwsKmsWalletParams = { - awsAccessKeyId: string; - awsSecretAccessKey: string; - - awsRegion: string; -}; - -export class FetchAwsKmsWalletParamsError extends Error {} - -/** - * Fetches the AWS KMS wallet creation parameters from the configuration or overrides. - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - */ -export async function fetchAwsKmsWalletParams( - overrides: Partial, -): Promise { - const config = await getConfig(); - - const awsAccessKeyId = - overrides.awsAccessKeyId ?? config.walletConfiguration.aws?.awsAccessKeyId; - - if (!awsAccessKeyId) { - throw new FetchAwsKmsWalletParamsError( - "AWS access key ID is required for this wallet type. Could not find in configuration or params.", - ); - } - - const awsSecretAccessKey = - overrides.awsSecretAccessKey ?? - config.walletConfiguration.aws?.awsSecretAccessKey; - - if (!awsSecretAccessKey) { - throw new FetchAwsKmsWalletParamsError( - "AWS secretAccessKey is required for this wallet type. Could not find in configuration or params.", - ); - } - - const awsRegion = - overrides.awsRegion ?? config.walletConfiguration.aws?.defaultAwsRegion; - - if (!awsRegion) { - throw new FetchAwsKmsWalletParamsError( - "AWS region is required for this wallet type. Could not find in configuration or params.", - ); - } - - return { - awsAccessKeyId, - awsSecretAccessKey, - awsRegion, - }; -} diff --git a/src/server/utils/wallets/fetch-gcp-kms-wallet-params.ts b/src/server/utils/wallets/fetch-gcp-kms-wallet-params.ts deleted file mode 100644 index 4d2fc84da..000000000 --- a/src/server/utils/wallets/fetch-gcp-kms-wallet-params.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { getConfig } from "../../../shared/utils/cache/get-config"; - -export type GcpKmsWalletParams = { - gcpApplicationCredentialEmail: string; - gcpApplicationCredentialPrivateKey: string; - - gcpApplicationProjectId: string; - gcpKmsKeyRingId: string; - gcpKmsLocationId: string; -}; - -export class FetchGcpKmsWalletParamsError extends Error {} - -/** - * Fetches the GCP KMS wallet creation parameters from the configuration or overrides. - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - */ -export async function fetchGcpKmsWalletParams( - overrides: Partial, -) { - const config = await getConfig(); - - const gcpApplicationCredentialEmail = - overrides.gcpApplicationCredentialEmail ?? - config.walletConfiguration.gcp?.gcpApplicationCredentialEmail; - - if (!gcpApplicationCredentialEmail) { - throw new FetchGcpKmsWalletParamsError( - "GCP application credential email is required for this wallet type. Could not find in configuration or params.", - ); - } - - const gcpApplicationCredentialPrivateKey = - overrides.gcpApplicationCredentialPrivateKey ?? - config.walletConfiguration.gcp?.gcpApplicationCredentialPrivateKey; - - if (!gcpApplicationCredentialPrivateKey) { - throw new FetchGcpKmsWalletParamsError( - "GCP application credential private key is required for this wallet type. Could not find in configuration or params.", - ); - } - - const gcpApplicationProjectId = - overrides.gcpApplicationProjectId ?? - config.walletConfiguration.gcp?.defaultGcpApplicationProjectId; - - if (!gcpApplicationProjectId) { - throw new FetchGcpKmsWalletParamsError( - "GCP application project ID is required for this wallet type. Could not find in configuration or params.", - ); - } - - const gcpKmsKeyRingId = - overrides.gcpKmsKeyRingId ?? - config.walletConfiguration.gcp?.defaultGcpKmsKeyRingId; - - if (!gcpKmsKeyRingId) { - throw new FetchGcpKmsWalletParamsError( - "GCP KMS key ring ID is required for this wallet type. Could not find in configuration or params.", - ); - } - - const gcpKmsLocationId = - overrides.gcpKmsLocationId ?? - config.walletConfiguration.gcp?.defaultGcpKmsLocationId; - - if (!gcpKmsLocationId) { - throw new FetchGcpKmsWalletParamsError( - "GCP KMS location ID is required for this wallet type. Could not find in configuration or params.", - ); - } - - return { - gcpApplicationCredentialEmail, - gcpApplicationCredentialPrivateKey, - gcpApplicationProjectId, - gcpKmsKeyRingId, - gcpKmsLocationId, - }; -} diff --git a/src/server/utils/wallets/gcp-kms-resource-path.ts b/src/server/utils/wallets/gcp-kms-resource-path.ts deleted file mode 100644 index 160fb1640..000000000 --- a/src/server/utils/wallets/gcp-kms-resource-path.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Split a GCP KMS resource path into its parts. - */ -export function splitGcpKmsResourcePath(resourcePath: string) { - const parts = resourcePath.split("/"); - - if (parts.length < 9) { - throw new Error("Invalid GCP KMS resource path"); - } - - return { - projectId: parts[1], - locationId: parts[3], - keyRingId: parts[5], - cryptoKeyId: parts[7], - versionId: parts[9], - }; -} - -/** - * Get a GCP KMS resource path from its parts. - */ -export function getGcpKmsResourcePath(options: { - locationId: string; - keyRingId: string; - cryptoKeyId: string; - versionId: string; - projectId: string; -}) { - return `projects/${options.projectId}/locations/${options.locationId}/keyRings/${options.keyRingId}/cryptoKeys/${options.cryptoKeyId}/cryptoKeyVersions/${options.versionId}`; -} diff --git a/src/server/utils/wallets/get-aws-kms-account.ts b/src/server/utils/wallets/get-aws-kms-account.ts deleted file mode 100644 index 69590e8ab..000000000 --- a/src/server/utils/wallets/get-aws-kms-account.ts +++ /dev/null @@ -1,120 +0,0 @@ -import type { KMSClientConfig } from "@aws-sdk/client-kms"; -import { KmsSigner } from "aws-kms-signer"; -import type { Hex, ThirdwebClient, toSerializableTransaction } from "thirdweb"; -import { - eth_sendRawTransaction, - getRpcClient, - keccak256, - type Address, -} from "thirdweb"; -import { serializeTransaction } from "thirdweb/transaction"; -import { hashMessage } from "thirdweb/utils"; -import type { Account } from "thirdweb/wallets"; -import type { SignableMessage, TypedData, TypedDataDefinition } from "viem"; -import { hashTypedData } from "viem"; -import { getChain } from "../../../shared/utils/chain"; - -type SendTransactionResult = { - transactionHash: Hex; -}; - -type SerializableTransaction = Awaited< - ReturnType ->; - -type SendTransactionOption = SerializableTransaction & { - chainId: number; -}; - -type AwsKmsAccountOptions = { - keyId: string; - config?: KMSClientConfig; - client: ThirdwebClient; -}; - -type AwsKmsAccount = Account; - -export async function getAwsKmsAccount( - options: AwsKmsAccountOptions, -): Promise { - const { keyId, config, client } = options; - const signer = new KmsSigner(keyId, config); - - // Populate address immediately - const addressUnprefixed = await signer.getAddress(); - const address = `0x${addressUnprefixed}` as Address; - - async function signTransaction(tx: SerializableTransaction): Promise { - const serializedTx = serializeTransaction({ transaction: tx }); - const txHash = keccak256(serializedTx); - const signature = await signer.sign(Buffer.from(txHash.slice(2), "hex")); - - const r = `0x${signature.r.toString("hex")}` as Hex; - const s = `0x${signature.s.toString("hex")}` as Hex; - const v = BigInt(signature.v); - - const yParity: 0 | 1 = signature.v % 2 === 0 ? 1 : 0; - - const signedTx = serializeTransaction({ - transaction: tx, - signature: { - r, - s, - v, - yParity, - }, - }); - - return signedTx; - } - - /** - * Sign a message with the account's private key. - * If the message is a string, it will be prefixed with the Ethereum message prefix. - * If the message is an object with a `raw` property, it will be signed as-is. - */ - async function signMessage({ - message, - }: { - message: SignableMessage; - }): Promise { - const messageHash = hashMessage(message); - const signature = await signer.sign( - Buffer.from(messageHash.slice(2), "hex"), - ); - return `0x${signature.toString()}`; - } - - async function signTypedData< - const typedData extends TypedData | Record, - primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, - >(_typedData: TypedDataDefinition): Promise { - const typedDataHash = hashTypedData(_typedData); - const signature = await signer.sign( - Buffer.from(typedDataHash.slice(2), "hex"), - ); - return `0x${signature.toString()}`; - } - - async function sendTransaction( - tx: SendTransactionOption, - ): Promise { - const rpcRequest = getRpcClient({ - client: client, - chain: await getChain(tx.chainId), - }); - - const signedTx = await signTransaction(tx); - - const transactionHash = await eth_sendRawTransaction(rpcRequest, signedTx); - return { transactionHash }; - } - - return { - address, - sendTransaction, - signMessage, - signTypedData, - signTransaction, - } as AwsKmsAccount satisfies Account; -} diff --git a/src/server/utils/wallets/get-gcp-kms-account.ts b/src/server/utils/wallets/get-gcp-kms-account.ts deleted file mode 100644 index d6dde252b..000000000 --- a/src/server/utils/wallets/get-gcp-kms-account.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { CloudKmsSigner } from "@cloud-cryptographic-wallet/cloud-kms-signer"; -import { Bytes } from "@cloud-cryptographic-wallet/signer"; -import type { Hex, ThirdwebClient, toSerializableTransaction } from "thirdweb"; -import { - eth_sendRawTransaction, - getAddress, - getRpcClient, - keccak256, -} from "thirdweb"; -import { serializeTransaction } from "thirdweb/transaction"; -import { hashMessage } from "thirdweb/utils"; -import type { Account } from "thirdweb/wallets"; -import type { SignableMessage, TypedData, TypedDataDefinition } from "viem"; -import { hashTypedData } from "viem"; -import { getChain } from "../../../shared/utils/chain"; // Adjust import path as needed - -type SendTransactionResult = { - transactionHash: Hex; -}; - -type SerializableTransaction = Awaited< - ReturnType ->; - -type SendTransactionOption = SerializableTransaction & { - chainId: number; -}; - -type GcpKmsAccountOptions = { - name: string; // GCP KMS key name - clientOptions?: ConstructorParameters[1]; - client: ThirdwebClient; -}; - -type GcpKmsAccount = Account; - -export async function getGcpKmsAccount( - options: GcpKmsAccountOptions, -): Promise { - const { name: unprocessedName, clientOptions, client } = options; - - if (clientOptions?.credentials) { - if ( - "private_key" in clientOptions.credentials && - clientOptions.credentials.private_key - ) { - // https://stackoverflow.com/questions/74131595/error-error1e08010cdecoder-routinesunsupported-with-google-auth-library - // new keys are stored correctly with newlines, but older keys need this sanitization for backwards compatibility - clientOptions.credentials.private_key = - clientOptions.credentials.private_key.split(String.raw`\n`).join("\n"); - } - } - - // we had a bug previously where we previously called it "cryptoKeysVersion" instead of "cryptoKeyVersions" - // if we detect that, we'll fix it here - // TODO: remove this as a breaking change - const name = unprocessedName.includes("cryptoKeyVersions") - ? unprocessedName - : unprocessedName.replace("cryptoKeysVersion", "cryptoKeyVersions"); - - const signer = new CloudKmsSigner(name, clientOptions); - - // Populate address immediately - const publicKey = await signer.getPublicKey(); - const address = getAddress(publicKey.toAddress().toString()); - - async function signTransaction(tx: SerializableTransaction): Promise { - const serializedTx = serializeTransaction({ transaction: tx }); - const txHash = keccak256(serializedTx); - const signature = await signer.sign(Bytes.fromString(txHash.slice(2))); - - const r = signature.r.toString() as Hex; - const s = signature.s.toString() as Hex; - const v = BigInt(signature.v); - - const yParity: 0 | 1 = signature.v % 2 === 0 ? 1 : 0; - - const signedTx = serializeTransaction({ - transaction: tx, - signature: { - r, - s, - v, - yParity, - }, - }); - - return signedTx; - } - - /** - * Sign a message with the account's private key. - * If the message is a string, it will be prefixed with the Ethereum message prefix. - * If the message is an object with a `raw` property, it will be signed as-is. - */ - async function signMessage({ - message, - }: { - message: SignableMessage; - }): Promise { - const messageHash = hashMessage(message); - const signature = await signer.sign(Bytes.fromString(messageHash)); - return signature.bytes.toString() as Hex; - } - - async function signTypedData< - const typedData extends TypedData | Record, - primaryType extends keyof typedData | "EIP712Domain" = keyof typedData, - >(_typedData: TypedDataDefinition): Promise { - const typedDataHash = hashTypedData(_typedData); - const signature = await signer.sign(Bytes.fromString(typedDataHash)); - return signature.bytes.toString() as Hex; - } - - async function sendTransaction( - tx: SendTransactionOption, - ): Promise { - const rpcRequest = getRpcClient({ - client: client, - chain: await getChain(tx.chainId), - }); - - const signedTx = await signTransaction(tx); - - const transactionHash = await eth_sendRawTransaction(rpcRequest, signedTx); - return { transactionHash }; - } - - return { - address, - sendTransaction, - signMessage, - signTypedData, - signTransaction, - } as GcpKmsAccount satisfies Account; -} diff --git a/src/server/utils/wallets/get-local-wallet.ts b/src/server/utils/wallets/get-local-wallet.ts deleted file mode 100644 index 1a9d4e040..000000000 --- a/src/server/utils/wallets/get-local-wallet.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { LocalWallet } from "@thirdweb-dev/wallets"; -import { Wallet } from "ethers"; -import type { Address } from "thirdweb"; -import { getChainMetadata } from "thirdweb/chains"; -import { privateKeyToAccount, type Account } from "thirdweb/wallets"; -import { getWalletDetails } from "../../../shared/db/wallets/get-wallet-details"; -import { getChain } from "../../../shared/utils/chain"; -import { env } from "../../../shared/utils/env"; -import { logger } from "../../../shared/utils/logger"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { badChainError } from "../../middleware/error"; -import { LocalFileStorage } from "../storage/local-storage"; - -interface GetLocalWalletParams { - chainId: number; - walletAddress: string; -} - -/** - * @deprecated - * DEPRECATED: Use getLocalWalletAccount instead - */ -export const getLocalWallet = async ({ - chainId, - walletAddress, -}: GetLocalWalletParams) => { - const chainV5 = await getChain(chainId); - const chain = await getChainMetadata(chainV5); - if (!chain) { - throw badChainError(chainId); - } - - const wallet = new LocalWallet({ chain }); - - // TODO: Remove this with next breaking change - try { - // First, try to load the wallet using the encryption password - await wallet.load({ - strategy: "encryptedJson", - password: env.ENCRYPTION_PASSWORD, - storage: new LocalFileStorage(walletAddress), - }); - } catch { - // If that fails, try the thirdweb api secret key for backwards compatibility - await wallet.load({ - strategy: "encryptedJson", - password: env.THIRDWEB_API_SECRET_KEY, - storage: new LocalFileStorage(walletAddress), - }); - - // If that works, save the wallet using the encryption password for the future - const walletDetails = await getWalletDetails({ address: walletAddress }); - - logger({ - service: "worker", - level: "info", - message: `[Encryption] Updating local wallet ${walletAddress} to use ENCRYPTION_PASSWORD`, - }); - - await wallet.save({ - strategy: "encryptedJson", - password: env.ENCRYPTION_PASSWORD, - storage: new LocalFileStorage( - walletAddress, - walletDetails.label ?? undefined, - ), - }); - } - - return wallet; -}; - -export const getLocalWalletAccount = async ( - walletAddress: Address, -): Promise => { - const walletDetails = await getWalletDetails({ address: walletAddress }); - - if (walletDetails.type !== "local") { - throw new Error(`Local Wallet not found for address ${walletAddress}`); - } - - return encryptedJsonToAccount(walletDetails.encryptedJson); -}; - -export const encryptedJsonToAccount = async (json: string) => { - const wallet = await Wallet.fromEncryptedJson( - JSON.parse(json).data, - env.ENCRYPTION_PASSWORD, - ); - - return privateKeyToAccount({ - client: thirdwebClient, - privateKey: wallet.privateKey, - }); -}; diff --git a/src/server/utils/wallets/get-smart-wallet.ts b/src/server/utils/wallets/get-smart-wallet.ts deleted file mode 100644 index 1b512361d..000000000 --- a/src/server/utils/wallets/get-smart-wallet.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { SmartWallet, type EVMWallet } from "@thirdweb-dev/wallets"; -import { getContract } from "../../../shared/utils/cache/get-contract"; -import { env } from "../../../shared/utils/env"; -import { redis } from "../../../shared/utils/redis/redis"; - -interface GetSmartWalletParams { - chainId: number; - backendWallet: EVMWallet; - accountAddress: string; - factoryAddress?: string; - entrypointAddress?: string; -} - -/** - * @deprecated - * DEPRECATED: Use `getSmartWalletV5` instead - */ -export const getSmartWallet = async ({ - chainId, - backendWallet, - accountAddress, - factoryAddress, - entrypointAddress, -}: GetSmartWalletParams) => { - let resolvedFactoryAddress: string | undefined = factoryAddress; - - if (!resolvedFactoryAddress) { - try { - // Note: This is a temporary solution to use cached deployed address's factory address from create-account - // This is needed due to a potential race condition of submitting a transaction immediately after creating an account that is not yet mined onchain - resolvedFactoryAddress = - (await redis.get(`account-factory:${accountAddress.toLowerCase()}`)) ?? - undefined; - } catch {} - } - - if (!resolvedFactoryAddress) { - try { - const contract = await getContract({ - chainId, - contractAddress: accountAddress, - }); - resolvedFactoryAddress = await contract.call("factory"); - } catch {} - } - - if (!resolvedFactoryAddress) { - throw new Error( - `Failed to find factory address for account '${accountAddress}' on chain '${chainId}'`, - ); - } - - const smartWallet = new SmartWallet({ - chain: chainId, - factoryAddress: resolvedFactoryAddress, - entryPointAddress: entrypointAddress, - secretKey: env.THIRDWEB_API_SECRET_KEY, - gasless: true, - }); - - await smartWallet.connect({ - personalWallet: backendWallet, - accountAddress, - }); - - return smartWallet; -}; diff --git a/src/server/utils/wallets/import-aws-kms-wallet.ts b/src/server/utils/wallets/import-aws-kms-wallet.ts deleted file mode 100644 index 364a2c0af..000000000 --- a/src/server/utils/wallets/import-aws-kms-wallet.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { createWalletDetails } from "../../../shared/db/wallets/create-wallet-details"; -import { WalletType } from "../../../shared/schemas/wallet"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { splitAwsKmsArn } from "./aws-kms-arn"; -import { getAwsKmsAccount } from "./get-aws-kms-account"; - -interface ImportAwsKmsWalletParams { - awsKmsArn: string; - crendentials: { - accessKeyId: string; - secretAccessKey: string; - }; - label?: string; -} - -/** - * Import an AWS KMS wallet, and store it into the database - */ -export const importAwsKmsWallet = async ({ - crendentials, - awsKmsArn, - label, -}: ImportAwsKmsWalletParams) => { - const { keyId, region } = splitAwsKmsArn(awsKmsArn); - const account = await getAwsKmsAccount({ - client: thirdwebClient, - keyId, - config: { - region, - credentials: { - accessKeyId: crendentials.accessKeyId, - secretAccessKey: crendentials.secretAccessKey, - }, - }, - }); - - const walletAddress = account.address; - - await createWalletDetails({ - type: WalletType.awsKms, - address: walletAddress, - awsKmsArn, - label, - - awsKmsAccessKeyId: crendentials.accessKeyId, - awsKmsSecretAccessKey: crendentials.secretAccessKey, - }); - - return walletAddress; -}; diff --git a/src/server/utils/wallets/import-gcp-kms-wallet.ts b/src/server/utils/wallets/import-gcp-kms-wallet.ts deleted file mode 100644 index 5925ba503..000000000 --- a/src/server/utils/wallets/import-gcp-kms-wallet.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { createWalletDetails } from "../../../shared/db/wallets/create-wallet-details"; -import { WalletType } from "../../../shared/schemas/wallet"; -import { thirdwebClient } from "../../../shared/utils/sdk"; -import { getGcpKmsAccount } from "./get-gcp-kms-account"; - -interface ImportGcpKmsWalletParams { - gcpKmsResourcePath: string; - label?: string; - credentials: { - email: string; - privateKey: string; - }; -} - -/** - * Import a GCP KMS wallet, and store it into the database - * - * If credentials.shouldStore is true, the GCP application credential email and private key will be stored - * along with the wallet details, separately from the global configuration - */ -export const importGcpKmsWallet = async ({ - label, - gcpKmsResourcePath, - credentials, -}: ImportGcpKmsWalletParams) => { - const account = await getGcpKmsAccount({ - client: thirdwebClient, - name: gcpKmsResourcePath, - clientOptions: { - credentials: { - client_email: credentials.email, - private_key: credentials.privateKey, - }, - }, - }); - - const walletAddress = account.address; - - await createWalletDetails({ - type: WalletType.gcpKms, - address: walletAddress, - label, - gcpKmsResourcePath, - - gcpApplicationCredentialEmail: credentials.email, - gcpApplicationCredentialPrivateKey: credentials.privateKey, - }); - - return walletAddress; -}; diff --git a/src/server/utils/wallets/import-local-wallet.ts b/src/server/utils/wallets/import-local-wallet.ts deleted file mode 100644 index 38762f559..000000000 --- a/src/server/utils/wallets/import-local-wallet.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { LocalWallet } from "@thirdweb-dev/wallets"; -import { env } from "../../../shared/utils/env"; -import { LocalFileStorage } from "../storage/local-storage"; - -type ImportLocalWalletParams = - | { - method: "privateKey"; - privateKey: string; - label?: string; - } - | { - method: "mnemonic"; - mnemonic: string; - label?: string; - } - | { - method: "encryptedJson"; - encryptedJson: string; - password: string; - label?: string; - }; - -export const importLocalWallet = async ( - options: ImportLocalWalletParams, -): Promise => { - const wallet = new LocalWallet(); - - // TODO: Is there a case where we should enable encryption: true? - let walletAddress: string; - switch (options.method) { - case "privateKey": - walletAddress = await wallet.import({ - privateKey: options.privateKey, - encryption: false, - }); - break; - case "mnemonic": - walletAddress = await wallet.import({ - mnemonic: options.mnemonic, - encryption: false, - }); - break; - case "encryptedJson": - walletAddress = await wallet.import({ - encryptedJson: options.encryptedJson, - password: options.password, - }); - break; - } - - // Creating wallet details gets handled by LocalFileStorage - await wallet.save({ - strategy: "encryptedJson", - password: env.ENCRYPTION_PASSWORD, - storage: new LocalFileStorage(walletAddress, options.label), - }); - - return walletAddress; -}; diff --git a/src/server/utils/websocket.ts b/src/server/utils/websocket.ts deleted file mode 100644 index e01f00715..000000000 --- a/src/server/utils/websocket.ts +++ /dev/null @@ -1,169 +0,0 @@ -import type { SocketStream } from "@fastify/websocket"; -import type { Static } from "@sinclair/typebox"; -import type { FastifyRequest } from "fastify"; -import { logger } from "../../shared/utils/logger"; -import type { TransactionSchema } from "../schemas/transaction"; -import { type UserSubscription, subscriptionsData } from "../schemas/websocket"; - -// websocket timeout, i.e., ws connection closed after 10 seconds -const timeoutDuration = 10 * 60 * 1000; - -export const findWSConnectionInSharedState = async ( - connection: SocketStream, - _request: FastifyRequest, -): Promise => { - const index = subscriptionsData.findIndex( - (sub) => sub.socket === connection.socket, - ); - return index; -}; - -export const removeWSFromSharedState = async ( - connection: SocketStream, - request: FastifyRequest, -): Promise => { - const index = await findWSConnectionInSharedState(connection, request); - if (index === -1) { - return -1; - } - subscriptionsData.splice(index, 1); - return index; -}; - -export const onError = async ( - error: Error, - connection: SocketStream, - request: FastifyRequest, -): Promise => { - logger({ - service: "server", - level: "error", - message: "Websocket error", - error, - }); - - const index = await findWSConnectionInSharedState(connection, request); - if (index === -1) { - return; - } - - const userSubscription = subscriptionsData[index]; - subscriptionsData.splice(index, 1); - userSubscription.socket.send( - JSON.stringify({ - result: null, - requestId: userSubscription.requestId, - status: "error", - message: error.message, - }), - ); - - connection.socket.close(); -}; - -export const onMessage = async ( - connection: SocketStream, - request: FastifyRequest, -): Promise => { - const index = await findWSConnectionInSharedState(connection, request); - const userSubscription = subscriptionsData[index]; - subscriptionsData.splice(index, 1); - userSubscription.socket.send( - JSON.stringify({ - result: null, - requestId: userSubscription.requestId, - status: "error", - message: "Do not send any message. Closing Socket... Reconnect again.", - }), - ); - userSubscription.socket.close(); -}; - -export const onClose = async ( - connection: SocketStream, - request: FastifyRequest, -): Promise => { - const index = await findWSConnectionInSharedState(connection, request); - if (index === -1) { - return; - } - subscriptionsData.splice(index, 1); -}; - -export const wsTimeout = async ( - connection: SocketStream, - queueId: string, - request: FastifyRequest, -): Promise => { - return setTimeout(() => { - connection.socket.send("Timeout exceeded. Closing connection..."); - removeWSFromSharedState(connection, request); - connection.socket.close(1000, "Session timeout"); // 1000 is a normal closure status code - - logger({ - service: "server", - level: "info", - message: `Websocket connection for ${queueId} closed due to timeout.`, - }); - }, timeoutDuration); -}; - -export const findOrAddWSConnectionInSharedState = async ( - connection: SocketStream, - queueId: string, - request: FastifyRequest, -) => { - let userSubscription: UserSubscription | undefined = undefined; - const index = await findWSConnectionInSharedState(connection, request); - if (index > -1) { - userSubscription = subscriptionsData[index]; - } else { - userSubscription = { - socket: connection.socket, - requestId: queueId, - }; - - subscriptionsData.push(userSubscription); - } -}; - -type CustomStatusAndConnectionType = { - message: string; - closeConnection: boolean; -}; - -export const getStatusMessageAndConnectionStatus = async ( - data: Static | null, -): Promise => { - let message = - "Request is queued. Waiting for transaction to be picked up by worker."; - let closeConnection = false; - - if (!data) { - message = "Transaction not found. Make sure the provided ID is correct."; - closeConnection = true; - } else if (data.status === "mined") { - message = "Transaction mined. Closing connection."; - closeConnection = true; - } else if (data.status === "errored") { - message = data.errorMessage || "Transaction errored. Closing connection."; - closeConnection = true; - } else if (data.status === "sent") { - message = - "Transaction submitted to blockchain. Waiting for transaction to be mined..."; - } - - return { message, closeConnection }; -}; - -export const formatSocketMessage = async ( - data: Static | null, - message: string, -): Promise => { - const returnData = JSON.stringify({ - result: data ? JSON.stringify(data) : undefined, - queueId: data?.queueId, - message, - }); - return returnData; -}; diff --git a/src/shared/db/chain-indexers/get-chain-indexer.ts b/src/shared/db/chain-indexers/get-chain-indexer.ts deleted file mode 100644 index ae7f3e7e8..000000000 --- a/src/shared/db/chain-indexers/get-chain-indexer.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Prisma } from "@prisma/client"; -import type { PrismaTransaction } from "../../schemas/prisma"; -import { getPrismaWithPostgresTx } from "../client"; - -interface GetLastIndexedBlockParams { - chainId: number; - pgtx?: PrismaTransaction; -} - -export const getLastIndexedBlock = async ({ - chainId, - pgtx, -}: GetLastIndexedBlockParams) => { - const prisma = getPrismaWithPostgresTx(pgtx); - - const indexedChain = await prisma.chainIndexers.findUnique({ - where: { - chainId: chainId.toString(), - }, - }); - - if (indexedChain) { - return indexedChain.lastIndexedBlock; - } -}; - -interface GetBlockForIndexingParams { - chainId: number; - pgtx?: PrismaTransaction; -} - -export const getBlockForIndexing = async ({ - chainId, - pgtx, -}: GetBlockForIndexingParams) => { - const prisma = getPrismaWithPostgresTx(pgtx); - - const lastIndexedBlock = await prisma.$queryRaw< - { lastIndexedBlock: number }[] - >` - SELECT - "lastIndexedBlock" - FROM - "chain_indexers" - WHERE - "chainId"=${Prisma.sql`${chainId.toString()}`} - FOR UPDATE NOWAIT - `; - return lastIndexedBlock[0].lastIndexedBlock; -}; diff --git a/src/shared/db/chain-indexers/upsert-chain-indexer.ts b/src/shared/db/chain-indexers/upsert-chain-indexer.ts deleted file mode 100644 index 744a12a81..000000000 --- a/src/shared/db/chain-indexers/upsert-chain-indexer.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { PrismaTransaction } from "../../schemas/prisma"; -import { getPrismaWithPostgresTx } from "../client"; - -interface UpsertChainIndexerParams { - chainId: number; - currentBlockNumber: number; - pgtx?: PrismaTransaction; -} - -export const upsertChainIndexer = async ({ - chainId, - currentBlockNumber, - pgtx, -}: UpsertChainIndexerParams) => { - const prisma = getPrismaWithPostgresTx(pgtx); - return prisma.chainIndexers.upsert({ - where: { - chainId: chainId.toString(), - }, - update: { - chainId: chainId.toString(), - lastIndexedBlock: currentBlockNumber, - }, - create: { - chainId: chainId.toString(), - lastIndexedBlock: currentBlockNumber, - }, - }); -}; diff --git a/src/shared/db/client.ts b/src/shared/db/client.ts deleted file mode 100644 index 9c57b1417..000000000 --- a/src/shared/db/client.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { PrismaClient } from "@prisma/client"; -import pg, { type Knex } from "knex"; -import type { PrismaTransaction } from "../schemas/prisma"; -import { env } from "../utils/env"; - -export const prisma = new PrismaClient({ - log: ["info"], -}); - -export const getPrismaWithPostgresTx = (pgtx?: PrismaTransaction) => { - return pgtx || prisma; -}; - -export const knex = pg({ - client: "pg", - connection: { - connectionString: env.POSTGRES_CONNECTION_URL, - ssl: { - rejectUnauthorized: false, - }, - }, - acquireConnectionTimeout: 30000, -} as Knex.Config); - -export const isDatabaseReachable = async () => { - try { - await prisma.walletDetails.findFirst(); - return true; - } catch { - return false; - } -}; diff --git a/src/shared/db/configuration/get-configuration.ts b/src/shared/db/configuration/get-configuration.ts deleted file mode 100644 index d765fafbc..000000000 --- a/src/shared/db/configuration/get-configuration.ts +++ /dev/null @@ -1,288 +0,0 @@ -import type { Configuration } from "@prisma/client"; -import type { Static } from "@sinclair/typebox"; -import { LocalWallet } from "@thirdweb-dev/wallets"; -import { ethers } from "ethers"; -import type { Chain } from "thirdweb"; -import type { - AwsWalletConfiguration, - CircleWalletConfiguration, - GcpWalletConfiguration, - ParsedConfig, -} from "../../schemas/config"; -import { WalletType } from "../../schemas/wallet"; -import { mandatoryAllowedCorsUrls } from "../../../server/utils/cors-urls"; -import type { networkResponseSchema } from "../../utils/cache/get-sdk"; -import { decrypt } from "../../utils/crypto"; -import { env } from "../../utils/env"; -import { logger } from "../../utils/logger"; -import { prisma } from "../client"; -import { updateConfiguration } from "./update-configuration"; -import * as z from "zod"; - -export const walletProviderConfigsSchema = z.object({ - circle: z - .object({ - apiKey: z.string(), - }) - .optional(), -}); - -const toParsedConfig = async (config: Configuration): Promise => { - // We destructure the config to omit wallet related fields to prevent direct access - const { - awsAccessKeyId, - awsSecretAccessKey, - awsRegion, - gcpApplicationProjectId, - gcpKmsLocationId, - gcpKmsKeyRingId, - gcpApplicationCredentialEmail, - gcpApplicationCredentialPrivateKey, - contractSubscriptionsRetryDelaySeconds, - walletProviderConfigs, - ...restConfig - } = config; - - // Parse "chainOverrides" JSON to an array of Chain[] items. - let chainOverridesParsed: Chain[] = []; - if (config.chainOverrides) { - try { - const parsed: Static[] = JSON.parse( - config.chainOverrides, - ); - chainOverridesParsed = parsed.map( - (chain): Chain => ({ - id: chain.chainId, - name: chain.name, - rpc: chain.rpc[0], - nativeCurrency: chain.nativeCurrency, - testnet: chain.testnet ? true : undefined, - }), - ); - } catch (e) { - logger({ - service: "server", - level: "error", - message: `Failed parsing chainOverrides: ${e}`, - }); - } - } - - // LEGACY COMPATIBILITY - // legacy behaviour was to check for these in order: - // 1. AWS KMS Configuration - if found, wallet type is AWS KMS - // 2. GCP KMS Configuration - if found, wallet type is GCP KMS - // 3. If neither are found, wallet type is Local - // to maintain compatibility where users expect to call create new backend wallet endpoint without an explicit wallet type - // we need to preserve the wallet type in the configuration but only as the "default" wallet type - let legacyWalletType_removeInNextBreakingChange: WalletType = - WalletType.local; - - let awsWalletConfiguration: AwsWalletConfiguration | null = null; - - // TODO: Remove backwards compatibility with next breaking change - if (awsAccessKeyId && awsSecretAccessKey && awsRegion) { - // First try to load the aws secret using the encryption password - let decryptedSecretAccessKey = decrypt( - awsSecretAccessKey, - env.ENCRYPTION_PASSWORD, - ); - - // If that fails, try to load the aws secret using the thirdweb api secret key - if (!awsSecretAccessKey) { - decryptedSecretAccessKey = decrypt( - awsSecretAccessKey, - env.THIRDWEB_API_SECRET_KEY, - ); - - // If that succeeds, update the configuration with the encryption password instead - if (decryptedSecretAccessKey) { - logger({ - service: "worker", - level: "info", - message: - "[Encryption] Updating awsSecretAccessKey to use ENCRYPTION_PASSWORD", - }); - - await updateConfiguration({ - awsSecretAccessKey: decryptedSecretAccessKey, - }); - } - } - - // Renaming contractSubscriptionsRetryDelaySeconds - // to contractSubscriptionsRequeryDelaySeconds to reflect its purpose - // as we are requerying (& not retrying) with different delays - awsWalletConfiguration = { - awsAccessKeyId, - awsSecretAccessKey: decryptedSecretAccessKey, - defaultAwsRegion: awsRegion, - }; - - legacyWalletType_removeInNextBreakingChange = WalletType.awsKms; - } - - let gcpWalletConfiguration: GcpWalletConfiguration | null = null; - // TODO: Remove backwards compatibility with next breaking change - if (gcpApplicationCredentialEmail && gcpApplicationCredentialPrivateKey) { - // First try to load the gcp secret using the encryption password - let decryptedGcpKey = decrypt( - gcpApplicationCredentialPrivateKey, - env.ENCRYPTION_PASSWORD, - ); - - // If that fails, try to load the gcp secret using the thirdweb api secret key - if (!gcpApplicationCredentialPrivateKey) { - decryptedGcpKey = decrypt( - gcpApplicationCredentialPrivateKey, - env.THIRDWEB_API_SECRET_KEY, - ); - - // If that succeeds, update the configuration with the encryption password instead - if (decryptedGcpKey) { - logger({ - service: "worker", - level: "info", - message: - "[Encryption] Updating gcpApplicationCredentialPrivateKey to use ENCRYPTION_PASSWORD", - }); - - await updateConfiguration({ - gcpApplicationCredentialPrivateKey: decryptedGcpKey, - }); - } - } - - if (!gcpKmsLocationId || !gcpKmsKeyRingId || !gcpApplicationProjectId) { - throw new Error( - "GCP KMS location ID, project ID, and key ring ID are required configuration for this wallet type", - ); - } - - gcpWalletConfiguration = { - gcpApplicationCredentialEmail, - gcpApplicationCredentialPrivateKey: decryptedGcpKey, - - // TODO: Remove these with the next breaking change - // These are used because import endpoint does not yet support GCP KMS resource path - defaultGcpKmsLocationId: gcpKmsLocationId, - defaultGcpKmsKeyRingId: gcpKmsKeyRingId, - defaultGcpApplicationProjectId: gcpApplicationProjectId, - }; - - legacyWalletType_removeInNextBreakingChange = WalletType.gcpKms; - } - - let circleWalletConfiguration: CircleWalletConfiguration | null = null; - - const { - data: parsedWalletProviderConfigs, - success, - error: walletProviderConfigsParseError, - } = walletProviderConfigsSchema.safeParse(walletProviderConfigs?.valueOf()); - - // TODO: fail loudly if walletProviderConfigs is not valid - if (!success) { - logger({ - level: "error", - message: "Invalid wallet provider configs", - service: "server", - error: walletProviderConfigsParseError, - }); - } - - if (parsedWalletProviderConfigs?.circle) { - circleWalletConfiguration = { - apiKey: decrypt( - parsedWalletProviderConfigs.circle.apiKey, - env.ENCRYPTION_PASSWORD, - ), - }; - } - - return { - ...restConfig, - contractSubscriptionsRequeryDelaySeconds: - contractSubscriptionsRetryDelaySeconds, - chainOverridesParsed, - walletConfiguration: { - aws: awsWalletConfiguration, - gcp: gcpWalletConfiguration, - circle: circleWalletConfiguration, - legacyWalletType_removeInNextBreakingChange, - }, - mtlsCertificate: config.mtlsCertificateEncrypted - ? decrypt(config.mtlsCertificateEncrypted, env.ENCRYPTION_PASSWORD) - : null, - mtlsPrivateKey: config.mtlsPrivateKeyEncrypted - ? decrypt(config.mtlsPrivateKeyEncrypted, env.ENCRYPTION_PASSWORD) - : null, - }; -}; - -const createAuthWalletEncryptedJson = async () => { - const wallet = new LocalWallet(); - await wallet.generate(); - return wallet.export({ - strategy: "encryptedJson", - password: env.ENCRYPTION_PASSWORD, - }); -}; - -export const getConfiguration = async (): Promise => { - let config = await prisma.configuration.findUnique({ - where: { - id: "default", - }, - }); - - if (!config) { - // Here we set all our defaults when first creating the configuration - config = await prisma.configuration.upsert({ - where: { - id: "default", - }, - create: { - minTxsToProcess: 1, - maxTxsToProcess: 30, - minedTxListenerCronSchedule: "*/5 * * * * *", - maxTxsToUpdate: 50, - retryTxListenerCronSchedule: "*/15 * * * * *", - indexerListenerCronSchedule: "*/5 * * * * *", - maxBlocksToIndex: 25, - cursorDelaySeconds: 2, - minEllapsedBlocksBeforeRetry: 12, - maxFeePerGasForRetries: ethers.utils - .parseUnits("10000", "gwei") - .toString(), - maxPriorityFeePerGasForRetries: ethers.utils - .parseUnits("10000", "gwei") - .toString(), - maxRetriesPerTx: 3, - authDomain: "thirdweb.com", - authWalletEncryptedJson: await createAuthWalletEncryptedJson(), - minWalletBalance: "20000000000000000", - accessControlAllowOrigin: mandatoryAllowedCorsUrls.join(","), - clearCacheCronSchedule: "*/30 * * * * *", - }, - update: {}, - }); - } else if (!config.authDomain && !config.authWalletEncryptedJson) { - // TODO: Use a more generic method to fill missing fields - config = await updateConfiguration({ - authDomain: "thirdweb.com", - authWalletEncryptedJson: await createAuthWalletEncryptedJson(), - }); - } else if (!config.accessControlAllowOrigin) { - config = await updateConfiguration({ - accessControlAllowOrigin: mandatoryAllowedCorsUrls.join(","), - }); - } else if (!config.indexerListenerCronSchedule) { - config = await updateConfiguration({ - indexerListenerCronSchedule: "*/5 * * * * *", - }); - } - - const result = await toParsedConfig(config); - return result; -}; diff --git a/src/shared/db/configuration/update-configuration.ts b/src/shared/db/configuration/update-configuration.ts deleted file mode 100644 index 41e49df01..000000000 --- a/src/shared/db/configuration/update-configuration.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { Prisma } from "@prisma/client"; -import { encrypt } from "../../utils/crypto"; -import { prisma } from "../client"; -import { walletProviderConfigsSchema } from "./get-configuration"; -import { logger } from "../../utils/logger"; - -export const updateConfiguration = async ( - data: Prisma.ConfigurationUpdateInput, -) => { - if (typeof data.awsSecretAccessKey === "string") { - data.awsSecretAccessKey = encrypt(data.awsSecretAccessKey); - } - - if (typeof data.gcpApplicationCredentialPrivateKey === "string") { - data.gcpApplicationCredentialPrivateKey = encrypt( - data.gcpApplicationCredentialPrivateKey, - ); - } - - // allow undefined (for no updates to field), but do not allow any other values than object - if (typeof data.walletProviderConfigs === "object") { - const { data: parsedWalletProviderConfigs, error } = - walletProviderConfigsSchema.safeParse(data.walletProviderConfigs); - - if (error) { - logger({ - level: "error", - message: "Invalid walletProviderConfigs", - error: error, - service: "server", - }); - // it's okay to throw a raw error here, any HTTP call that uses this should validate the input - throw new Error("Invalid walletProviderConfigs"); - } - - if (parsedWalletProviderConfigs?.circle?.apiKey) { - parsedWalletProviderConfigs.circle.apiKey = encrypt( - parsedWalletProviderConfigs.circle.apiKey, - ); - } - - data.walletProviderConfigs = parsedWalletProviderConfigs; - } else if (typeof data.walletProviderConfigs !== "undefined") { - throw new Error("Invalid walletProviderConfigs"); - } - - return prisma.configuration.update({ - where: { - id: "default", - }, - data, - }); -}; diff --git a/src/shared/db/contract-event-logs/create-contract-event-logs.ts b/src/shared/db/contract-event-logs/create-contract-event-logs.ts deleted file mode 100644 index 5b4c94e13..000000000 --- a/src/shared/db/contract-event-logs/create-contract-event-logs.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { ContractEventLogs, Prisma } from "@prisma/client"; -import type { PrismaTransaction } from "../../schemas/prisma"; -import { getPrismaWithPostgresTx } from "../client"; - -export interface BulkInsertContractLogsParams { - pgtx?: PrismaTransaction; - logs: Prisma.ContractEventLogsCreateInput[]; -} - -export const bulkInsertContractEventLogs = async ({ - pgtx, - logs, -}: BulkInsertContractLogsParams): Promise => { - const prisma = getPrismaWithPostgresTx(pgtx); - return await prisma.contractEventLogs.createManyAndReturn({ - data: logs, - skipDuplicates: true, - }); -}; diff --git a/src/shared/db/contract-event-logs/delete-contract-event-logs.ts b/src/shared/db/contract-event-logs/delete-contract-event-logs.ts deleted file mode 100644 index 4a859d2b3..000000000 --- a/src/shared/db/contract-event-logs/delete-contract-event-logs.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { prisma } from "../client"; - -interface DeleteContractEventLogsParams { - chainId: number; - contractAddress: string; -} - -export const deleteContractEventLogs = async ({ - chainId, - contractAddress, -}: DeleteContractEventLogsParams) => { - return prisma.contractEventLogs.deleteMany({ - where: { - chainId: chainId.toString(), - contractAddress, - }, - }); -}; diff --git a/src/shared/db/contract-event-logs/get-contract-event-logs.ts b/src/shared/db/contract-event-logs/get-contract-event-logs.ts deleted file mode 100644 index ab27bfade..000000000 --- a/src/shared/db/contract-event-logs/get-contract-event-logs.ts +++ /dev/null @@ -1,254 +0,0 @@ -import base64 from "base-64"; -import { z } from "zod"; -import { prisma } from "../client"; - -interface GetContractLogsParams { - chainId: number; - contractAddress: string; - fromBlock: number; - toBlock?: number; - topics?: string[]; -} - -export const getContractEventLogsByBlockAndTopics = async ({ - chainId, - contractAddress, - fromBlock, - toBlock, - topics, -}: GetContractLogsParams) => { - const whereClause = { - chainId: chainId.toString(), - contractAddress, - blockNumber: { - gte: fromBlock, - ...(toBlock ? { lte: toBlock } : {}), - }, - ...(topics && topics.length > 0 - ? { - OR: [ - { topic0: { in: topics } }, - { topic1: { in: topics } }, - { topic2: { in: topics } }, - { topic3: { in: topics } }, - ], - } - : {}), - }; - - return await prisma.contractEventLogs.findMany({ - where: whereClause, - }); -}; - -interface GetEventLogsByBlockTimestampParams { - fromBlockTimestamp: number; - toBlockTimestamp?: number; - contractAddresses?: string[]; - topics?: string[]; -} - -export const getEventLogsByBlockTimestamp = async ({ - fromBlockTimestamp, - toBlockTimestamp, - contractAddresses, - topics, -}: GetEventLogsByBlockTimestampParams) => { - const fromBlockDate = new Date(fromBlockTimestamp); - const toBlockDate = toBlockTimestamp ? new Date(toBlockTimestamp) : undefined; - - const whereClause = { - timestamp: { - gte: fromBlockDate, - ...(toBlockDate && { lte: toBlockDate }), - }, - ...(contractAddresses && contractAddresses.length > 0 - ? { contractAddress: { in: contractAddresses } } - : {}), - ...(topics && topics.length > 0 - ? { - OR: [ - { topic0: { in: topics } }, - { topic1: { in: topics } }, - { topic2: { in: topics } }, - { topic3: { in: topics } }, - ], - } - : {}), - }; - - return await prisma.contractEventLogs.findMany({ - where: whereClause, - }); -}; - -interface GetEventLogsByCursorParams { - cursor?: string; - limit?: number; - contractAddresses?: string[]; - topics?: string[]; - maxCreatedAt?: Date; -} - -/* - cursor?: { - createdAt: Date; - chainId: number; - blockNumber: number; - transactionIndex: number; - logIndex: number; - }; - */ - -const CursorSchema = z.object({ - createdAt: z.number().transform((s) => new Date(s)), - chainId: z.number(), - blockNumber: z.number(), - transactionIndex: z.number(), - logIndex: z.number(), -}); - -export const getEventLogsByCursor = async ({ - cursor, - limit = 100, - contractAddresses, - topics, - maxCreatedAt, -}: GetEventLogsByCursorParams) => { - let cursorObj: z.infer | null = null; - if (cursor) { - const decodedCursor = base64.decode(cursor); - const parsedCursor = decodedCursor - .split("-") - .map((val) => Number.parseInt(val)); - const [createdAt, chainId, blockNumber, transactionIndex, logIndex] = - parsedCursor; - const validationResult = CursorSchema.safeParse({ - createdAt, - chainId, - blockNumber, - transactionIndex, - logIndex, - }); - - if (!validationResult.success) { - throw new Error("Invalid cursor format"); - } - - cursorObj = validationResult.data; - } - - const whereClause = { - AND: [ - ...(contractAddresses && contractAddresses.length > 0 - ? [{ contractAddress: { in: contractAddresses } }] - : []), - ...(cursorObj - ? [ - { - OR: [ - { createdAt: { gt: cursorObj.createdAt } }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { gt: cursorObj.chainId.toString() }, - }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { equals: cursorObj.chainId.toString() }, - blockNumber: { gt: cursorObj.blockNumber }, - }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { equals: cursorObj.chainId.toString() }, - blockNumber: { equals: cursorObj.blockNumber }, - transactionIndex: { gt: cursorObj.transactionIndex }, - }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { equals: cursorObj.chainId.toString() }, - blockNumber: { equals: cursorObj.blockNumber }, - transactionIndex: { equals: cursorObj.transactionIndex }, - logIndex: { gt: cursorObj.logIndex }, - }, - ], - }, - ] - : []), - ...(maxCreatedAt - ? [ - { - createdAt: { - lte: maxCreatedAt, - }, - }, - ] - : []), - ], - ...(topics && topics.length > 0 - ? { - OR: [ - { topic0: { in: topics } }, - { topic1: { in: topics } }, - { topic2: { in: topics } }, - { topic3: { in: topics } }, - ], - } - : {}), - }; - - const logs = await prisma.contractEventLogs.findMany({ - where: whereClause, - orderBy: [ - { createdAt: "asc" }, - { chainId: "asc" }, - { blockNumber: "asc" }, - { transactionIndex: "asc" }, - { logIndex: "asc" }, - ], - take: limit, - }); - - /* cursor rules */ - // if new logs returned, return new cursor - // if no new logs and no cursor return null (original cursor) - // if no new logs and cursor return original cursor - let newCursor = cursor; - if (logs.length > 0) { - const lastLog = logs[logs.length - 1]; - const cursorString = `${lastLog.createdAt.getTime()}-${lastLog.chainId}-${ - lastLog.blockNumber - }-${lastLog.transactionIndex}-${lastLog.logIndex}`; - - newCursor = base64.encode(cursorString); - } - - return { cursor: newCursor, logs }; -}; - -export interface GetContractEventLogsIndexedBlockRangeParams { - chainId: number; - contractAddress: string; -} - -export const getContractEventLogsIndexedBlockRange = async ({ - chainId, - contractAddress, -}: GetContractEventLogsIndexedBlockRangeParams) => { - const result = await prisma.contractEventLogs.aggregate({ - where: { - chainId: chainId.toString(), - contractAddress, - }, - _min: { - blockNumber: true, - }, - _max: { - blockNumber: true, - }, - }); - - return { - fromBlock: result._min.blockNumber, - toBlock: result._max.blockNumber, - }; -}; diff --git a/src/shared/db/contract-subscriptions/create-contract-subscription.ts b/src/shared/db/contract-subscriptions/create-contract-subscription.ts deleted file mode 100644 index 73cfb25cf..000000000 --- a/src/shared/db/contract-subscriptions/create-contract-subscription.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { prisma } from "../client"; - -interface CreateContractSubscriptionParams { - chainId: number; - contractAddress: string; - webhookId?: number; - processEventLogs: boolean; - filterEvents: string[]; - processTransactionReceipts: boolean; - filterFunctions: string[]; -} - -export const createContractSubscription = async ({ - chainId, - contractAddress, - webhookId, - processEventLogs, - filterEvents, - processTransactionReceipts, - filterFunctions, -}: CreateContractSubscriptionParams) => { - return prisma.contractSubscriptions.create({ - data: { - chainId: chainId.toString(), - contractAddress, - webhookId, - processEventLogs, - filterEvents, - processTransactionReceipts, - filterFunctions, - }, - include: { - webhook: true, - }, - }); -}; diff --git a/src/shared/db/contract-subscriptions/delete-contract-subscription.ts b/src/shared/db/contract-subscriptions/delete-contract-subscription.ts deleted file mode 100644 index 40c7a2602..000000000 --- a/src/shared/db/contract-subscriptions/delete-contract-subscription.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { prisma } from "../client"; - -export const deleteContractSubscription = async (id: string) => { - return prisma.contractSubscriptions.update({ - where: { id }, - data: { - deletedAt: new Date(), - }, - }); -}; diff --git a/src/shared/db/contract-subscriptions/get-contract-subscriptions.ts b/src/shared/db/contract-subscriptions/get-contract-subscriptions.ts deleted file mode 100644 index 21d8d8fef..000000000 --- a/src/shared/db/contract-subscriptions/get-contract-subscriptions.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { prisma } from "../client"; - -export interface GetContractSubscriptionsParams { - chainId: number; - contractAddress: string; -} - -export const isContractSubscribed = async ({ - chainId, - contractAddress, -}: GetContractSubscriptionsParams) => { - const contractSubscription = await prisma.contractSubscriptions.findFirst({ - where: { - chainId: chainId.toString(), - contractAddress, - deletedAt: null, - }, - }); - return contractSubscription !== null; -}; - -export const getContractSubscriptionsByChainId = async ( - chainId: number, - includeWebhook = false, -) => { - return await prisma.contractSubscriptions.findMany({ - where: { - chainId: chainId.toString(), - deletedAt: null, - }, - include: { - webhook: includeWebhook, - }, - }); -}; - -export const getAllContractSubscriptions = async () => { - return await prisma.contractSubscriptions.findMany({ - where: { - deletedAt: null, - }, - include: { - webhook: true, - }, - }); -}; - -export const getContractSubscriptionsUniqueChainIds = async () => { - const uniqueChainIds = await prisma.contractSubscriptions.findMany({ - distinct: ["chainId"], - select: { - chainId: true, - }, - where: { - deletedAt: null, - }, - }); - - return uniqueChainIds.map((contract) => Number.parseInt(contract.chainId)); -}; diff --git a/src/shared/db/contract-transaction-receipts/create-contract-transaction-receipts.ts b/src/shared/db/contract-transaction-receipts/create-contract-transaction-receipts.ts deleted file mode 100644 index a8843b0fc..000000000 --- a/src/shared/db/contract-transaction-receipts/create-contract-transaction-receipts.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { ContractTransactionReceipts, Prisma } from "@prisma/client"; -import type { PrismaTransaction } from "../../schemas/prisma"; -import { getPrismaWithPostgresTx } from "../client"; - -export interface BulkInsertContractLogsParams { - pgtx?: PrismaTransaction; - receipts: Prisma.ContractTransactionReceiptsCreateInput[]; -} - -export const bulkInsertContractTransactionReceipts = async ({ - pgtx, - receipts, -}: BulkInsertContractLogsParams): Promise => { - const prisma = getPrismaWithPostgresTx(pgtx); - return await prisma.contractTransactionReceipts.createManyAndReturn({ - data: receipts, - skipDuplicates: true, - }); -}; diff --git a/src/shared/db/contract-transaction-receipts/delete-contract-transaction-receipts.ts b/src/shared/db/contract-transaction-receipts/delete-contract-transaction-receipts.ts deleted file mode 100644 index c4c262aee..000000000 --- a/src/shared/db/contract-transaction-receipts/delete-contract-transaction-receipts.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { prisma } from "../client"; - -interface DeleteContractTransactionReceiptsParams { - chainId: number; - contractAddress: string; -} - -export const deleteContractTransactionReceipts = async ({ - chainId, - contractAddress, -}: DeleteContractTransactionReceiptsParams) => { - return prisma.contractTransactionReceipts.deleteMany({ - where: { - chainId: chainId.toString(), - contractAddress, - }, - }); -}; diff --git a/src/shared/db/contract-transaction-receipts/get-contract-transaction-receipts.ts b/src/shared/db/contract-transaction-receipts/get-contract-transaction-receipts.ts deleted file mode 100644 index a027085f7..000000000 --- a/src/shared/db/contract-transaction-receipts/get-contract-transaction-receipts.ts +++ /dev/null @@ -1,179 +0,0 @@ -import base64 from "base-64"; -import { z } from "zod"; -import { prisma } from "../client"; - -interface GetContractTransactionReceiptsParams { - chainId: number; - contractAddress: string; - fromBlock: number; - toBlock?: number; -} - -export const getContractTransactionReceiptsByBlock = async ({ - chainId, - contractAddress, - fromBlock, - toBlock, -}: GetContractTransactionReceiptsParams) => { - const whereClause = { - chainId: chainId.toString(), - contractAddress, - blockNumber: { - gte: fromBlock, - ...(toBlock ? { lte: toBlock } : {}), - }, - }; - - return await prisma.contractTransactionReceipts.findMany({ - where: whereClause, - }); -}; - -interface GetContractTransactionReceiptsByBlockTimestampParams { - fromBlockTimestamp: number; - toBlockTimestamp?: number; - contractAddresses?: string[]; -} - -export const getTransactionReceiptsByBlockTimestamp = async ({ - fromBlockTimestamp, - toBlockTimestamp, - contractAddresses, -}: GetContractTransactionReceiptsByBlockTimestampParams) => { - const fromBlockDate = new Date(fromBlockTimestamp); - const toBlockDate = toBlockTimestamp ? new Date(toBlockTimestamp) : undefined; - - const whereClause = { - timestamp: { - gte: fromBlockDate, - ...(toBlockDate && { lte: toBlockDate }), - }, - ...(contractAddresses && contractAddresses.length > 0 - ? { contractAddress: { in: contractAddresses } } - : {}), - }; - - return await prisma.contractTransactionReceipts.findMany({ - where: whereClause, - }); -}; - -interface GetContractTransactionReceiptsByCursorParams { - cursor?: string; - limit?: number; - contractAddresses?: string[]; - maxCreatedAt?: Date; -} - -/* - cursor?: { - createdAt: Date; - chainId: number; - blockNumber: number; - transactionIndex: number; - }; -*/ - -const CursorSchema = z.object({ - createdAt: z.number().transform((s) => new Date(s)), - chainId: z.number(), - blockNumber: z.number(), - transactionIndex: z.number(), -}); - -export const getTransactionReceiptsByCursor = async ({ - cursor, - limit = 100, - contractAddresses, - maxCreatedAt, -}: GetContractTransactionReceiptsByCursorParams) => { - let cursorObj: z.infer | null = null; - if (cursor) { - const decodedCursor = base64.decode(cursor); - const parsedCursor = decodedCursor - .split("-") - .map((val) => Number.parseInt(val)); - const [createdAt, chainId, blockNumber, transactionIndex] = parsedCursor; - const validationResult = CursorSchema.safeParse({ - createdAt, - chainId, - blockNumber, - transactionIndex, - }); - - if (!validationResult.success) { - throw new Error("Invalid cursor format"); - } - - cursorObj = validationResult.data; - } - - const whereClause = { - AND: [ - ...(contractAddresses && contractAddresses.length > 0 - ? [{ contractAddress: { in: contractAddresses } }] - : []), - ...(cursorObj - ? [ - { - OR: [ - { createdAt: { gt: cursorObj.createdAt } }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { gt: cursorObj.chainId.toString() }, - }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { equals: cursorObj.chainId.toString() }, - blockNumber: { gt: cursorObj.blockNumber }, - }, - { - createdAt: { equals: cursorObj.createdAt }, - chainId: { equals: cursorObj.chainId.toString() }, - blockNumber: { gt: cursorObj.blockNumber }, - transactionIndex: { gt: cursorObj.transactionIndex }, - }, - ], - }, - ] - : []), - ...(maxCreatedAt - ? [ - { - createdAt: { - lte: maxCreatedAt, - }, - }, - ] - : []), - ], - }; - - const transactionReceipts = await prisma.contractTransactionReceipts.findMany( - { - where: whereClause, - orderBy: [ - { createdAt: "asc" }, - { chainId: "asc" }, - { blockNumber: "asc" }, - { transactionIndex: "asc" }, - ], - take: limit, - }, - ); - - /* cursor rules */ - // if new logs returned, return new cursor - // if no new logs and no cursor return null (original cursor) - // if no new logs and cursor return original cursor - let newCursor = cursor; - if (transactionReceipts.length > 0) { - const lastReceipt = transactionReceipts[transactionReceipts.length - 1]; - const cursorString = `${lastReceipt.createdAt.getTime()}-${ - lastReceipt.chainId - }-${lastReceipt.blockNumber}-${lastReceipt.transactionIndex}`; - newCursor = base64.encode(cursorString); - } - - return { cursor: newCursor, transactionReceipts }; -}; diff --git a/src/shared/db/keypair/delete.ts b/src/shared/db/keypair/delete.ts deleted file mode 100644 index f731594fb..000000000 --- a/src/shared/db/keypair/delete.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Keypairs } from "@prisma/client"; -import { prisma } from "../client"; - -export const deleteKeypair = async ({ - hash, -}: { - hash: string; -}): Promise => { - return prisma.keypairs.delete({ - where: { hash }, - }); -}; diff --git a/src/shared/db/keypair/get.ts b/src/shared/db/keypair/get.ts deleted file mode 100644 index bc4b4997a..000000000 --- a/src/shared/db/keypair/get.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Keypairs } from "@prisma/client"; -import { createHash } from "crypto"; -import { prisma } from "../client"; - -export const getKeypairByHash = async ( - hash: string, -): Promise => { - return prisma.keypairs.findUnique({ - where: { hash }, - }); -}; - -export const getKeypairByPublicKey = async ( - publicKey: string, -): Promise => { - const hash = createHash("sha256").update(publicKey).digest("hex"); - return getKeypairByHash(hash); -}; diff --git a/src/shared/db/keypair/insert.ts b/src/shared/db/keypair/insert.ts deleted file mode 100644 index 77f1ada59..000000000 --- a/src/shared/db/keypair/insert.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Keypairs } from "@prisma/client"; -import { createHash } from "node:crypto"; -import type { KeypairAlgorithm } from "../../schemas/keypair"; -import { prisma } from "../client"; - -export const insertKeypair = async ({ - publicKey, - algorithm, - label, -}: { - publicKey: string; - algorithm: KeypairAlgorithm; - label?: string; -}): Promise => { - const hash = createHash("sha256").update(publicKey).digest("hex"); - - return prisma.keypairs.create({ - data: { - hash, - publicKey, - algorithm, - label, - }, - }); -}; diff --git a/src/shared/db/keypair/list.ts b/src/shared/db/keypair/list.ts deleted file mode 100644 index 0bf1dc494..000000000 --- a/src/shared/db/keypair/list.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { Keypairs } from "@prisma/client"; -import { prisma } from "../client"; - -export const listKeypairs = async (): Promise => { - return prisma.keypairs.findMany(); -}; diff --git a/src/shared/db/permissions/delete-permissions.ts b/src/shared/db/permissions/delete-permissions.ts deleted file mode 100644 index e8f3aaacc..000000000 --- a/src/shared/db/permissions/delete-permissions.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { prisma } from "../client"; - -interface DeletePermissionsParams { - walletAddress: string; -} - -export const deletePermissions = async ({ - walletAddress, -}: DeletePermissionsParams) => { - return prisma.permissions.delete({ - where: { - walletAddress: walletAddress.toLowerCase(), - }, - }); -}; diff --git a/src/shared/db/permissions/get-permissions.ts b/src/shared/db/permissions/get-permissions.ts deleted file mode 100644 index 7017ae12e..000000000 --- a/src/shared/db/permissions/get-permissions.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Permission } from "../../schemas/auth"; -import { env } from "../../utils/env"; -import { prisma } from "../client"; - -interface GetPermissionsParams { - walletAddress: string; -} - -export const getPermissions = async ({ - walletAddress, -}: GetPermissionsParams) => { - const permissions = await prisma.permissions.findUnique({ - where: { - walletAddress: walletAddress.toLowerCase(), - }, - }); - - // If the admin wallet isn't in the permissions table yet, add it - if ( - !permissions && - walletAddress.toLowerCase() === env.ADMIN_WALLET_ADDRESS.toLowerCase() - ) { - return prisma.permissions.create({ - data: { - walletAddress: walletAddress.toLowerCase(), - permissions: Permission.Admin, - }, - }); - } - - return permissions; -}; diff --git a/src/shared/db/permissions/update-permissions.ts b/src/shared/db/permissions/update-permissions.ts deleted file mode 100644 index 3c50ccbc4..000000000 --- a/src/shared/db/permissions/update-permissions.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { prisma } from "../client"; - -interface CreatePermissionsParams { - walletAddress: string; - permissions: string; - label?: string; -} - -export const updatePermissions = async ({ - walletAddress, - permissions, - label, -}: CreatePermissionsParams) => { - return prisma.permissions.upsert({ - where: { - walletAddress: walletAddress.toLowerCase(), - }, - create: { - walletAddress: walletAddress.toLowerCase(), - permissions, - label, - }, - update: { - permissions, - label, - }, - }); -}; diff --git a/src/shared/db/relayer/get-relayer-by-id.ts b/src/shared/db/relayer/get-relayer-by-id.ts deleted file mode 100644 index 9216e5c5f..000000000 --- a/src/shared/db/relayer/get-relayer-by-id.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { prisma } from "../client"; - -interface GetRelayerByIdParams { - id: string; -} - -export const getRelayerById = async ({ id }: GetRelayerByIdParams) => { - const relayer = await prisma.relayers.findUnique({ - where: { - id, - }, - }); - - if (!relayer) { - return null; - } - - return { - ...relayer, - chainId: Number.parseInt(relayer.chainId), - allowedContracts: relayer.allowedContracts - ? (JSON.parse(relayer.allowedContracts).map((contractAddress: string) => - contractAddress.toLowerCase(), - ) as string[]) - : null, - }; -}; diff --git a/src/shared/db/tokens/create-token.ts b/src/shared/db/tokens/create-token.ts deleted file mode 100644 index 41c973155..000000000 --- a/src/shared/db/tokens/create-token.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { parseJWT } from "@thirdweb-dev/auth"; -import { prisma } from "../client"; - -interface CreateTokenParams { - jwt: string; - isAccessToken: boolean; - label?: string; -} - -export const createToken = async ({ - jwt, - isAccessToken, - label, -}: CreateTokenParams) => { - const { payload } = parseJWT(jwt); - return prisma.tokens.create({ - data: { - id: payload.jti, - tokenMask: `${jwt.slice(0, 10)}...${jwt.slice(-10)}`, - walletAddress: payload.sub, - expiresAt: new Date(payload.exp * 1000), - isAccessToken, - label, - }, - }); -}; diff --git a/src/shared/db/tokens/get-access-tokens.ts b/src/shared/db/tokens/get-access-tokens.ts deleted file mode 100644 index 1ebbaeee2..000000000 --- a/src/shared/db/tokens/get-access-tokens.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { prisma } from "../client"; - -export const getAccessTokens = async () => { - return prisma.tokens.findMany({ - where: { - isAccessToken: true, - revokedAt: null, - }, - }); -}; diff --git a/src/shared/db/tokens/get-token.ts b/src/shared/db/tokens/get-token.ts deleted file mode 100644 index 4eb92380a..000000000 --- a/src/shared/db/tokens/get-token.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { parseJWT } from "@thirdweb-dev/auth"; -import { prisma } from "../client"; - -export const getToken = async (jwt: string) => { - const { payload } = parseJWT(jwt); - if (payload.jti) { - return prisma.tokens.findUnique({ - where: { - id: payload.jti, - }, - }); - } - return null; -}; diff --git a/src/shared/db/tokens/revoke-token.ts b/src/shared/db/tokens/revoke-token.ts deleted file mode 100644 index 582fd6d7d..000000000 --- a/src/shared/db/tokens/revoke-token.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { prisma } from "../client"; - -interface RevokeTokenParams { - id: string; -} - -export const revokeToken = async ({ id }: RevokeTokenParams) => { - await prisma.tokens.update({ - where: { - id, - }, - data: { - revokedAt: new Date(), - }, - }); -}; diff --git a/src/shared/db/tokens/update-token.ts b/src/shared/db/tokens/update-token.ts deleted file mode 100644 index 3079e31b1..000000000 --- a/src/shared/db/tokens/update-token.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { prisma } from "../client"; - -interface UpdateTokenParams { - id: string; - label?: string; -} - -export const updateToken = async ({ id, label }: UpdateTokenParams) => { - await prisma.tokens.update({ - where: { - id, - }, - data: { - label, - }, - }); -}; diff --git a/src/shared/db/transactions/db.ts b/src/shared/db/transactions/db.ts deleted file mode 100644 index 3250e5cb2..000000000 --- a/src/shared/db/transactions/db.ts +++ /dev/null @@ -1,213 +0,0 @@ -import superjson from "superjson"; -import { MAX_REDIS_BATCH_SIZE, redis } from "../../utils/redis/redis"; -import type { AnyTransaction } from "../../utils/transaction/types"; - -/** - * Schemas - * - * Transaction details - * key: `transaction:` - * value: JSON - * - * Queued transactions - * key: `transactions:queued` - * score: timestamp in unix seconds - * member: queueId - * - * Mined transactions - * key: `transactions:mined` - * score: timestamp in unix seconds - * member: queueId - * - * Cancelled transactions - * key: `transactions:cancelled` - * score: timestamp in unix seconds - * member: queueId - * - * Errored transactions - * key: `transactions:errored` - * score: timestamp in unix seconds - * member: queueId - */ - -export class TransactionDB { - private static transactionDetailsKey = (queueId: string) => - `transaction:${queueId}`; - private static queuedTransactionsKey = "transaction:queued"; - private static minedTransactionsKey = "transaction:mined"; - private static cancelledTransactionsKey = "transaction:cancelled"; - private static erroredTransactionsKey = "transaction:errored"; - - /** - * Inserts or replaces a transaction details. - * Also adds to the appropriate "status" sorted set. - * @param transaction - */ - static set = async (transaction: AnyTransaction) => { - const pipeline = redis - .pipeline() - .set( - this.transactionDetailsKey(transaction.queueId), - superjson.stringify(transaction), - ); - - switch (transaction.status) { - case "queued": - pipeline.zadd( - this.queuedTransactionsKey, - toSeconds(transaction.queuedAt), - transaction.queueId, - ); - break; - - case "mined": - pipeline.zadd( - this.minedTransactionsKey, - toSeconds(transaction.minedAt), - transaction.queueId, - ); - break; - - case "cancelled": - pipeline.zadd( - this.cancelledTransactionsKey, - toSeconds(transaction.cancelledAt), - transaction.queueId, - ); - break; - - case "errored": - pipeline.zadd( - this.erroredTransactionsKey, - toSeconds(new Date()), - transaction.queueId, - ); - break; - } - - await pipeline.exec(); - }; - - /** - * Gets transaction details by queueId. - * @param queueId - * @returns AnyTransaction, or null if not found. - */ - static get = async (queueId: string): Promise => { - const val = await redis.get(this.transactionDetailsKey(queueId)); - return val ? superjson.parse(val) : null; - }; - - /** - * Gets multiple transaction details by a list of queueIds. - * Skips any queueIds that aren't found. - * @param queueIds - * @returns AnyTransaction[] - */ - static bulkGet = async (queueIds: string[]): Promise => { - if (queueIds.length === 0) { - return []; - } - - const result: AnyTransaction[] = []; - for (let i = 0; i < queueIds.length; i += MAX_REDIS_BATCH_SIZE) { - const keys = queueIds - .slice(i, i + MAX_REDIS_BATCH_SIZE) - .map(this.transactionDetailsKey); - const vals = await redis.mget(...keys); - - for (const val of vals) { - if (val) { - result.push(superjson.parse(val)); - } - } - } - return result; - }; - - /** - * Deletes multiple transaction details by a list of queueIds. - * @param queueIds - * @returns number - The number of transaction details deleted. - */ - static bulkDelete = async (queueIds: string[]) => { - if (queueIds.length === 0) { - return 0; - } - - let numDeleted = 0; - for (let i = 0; i < queueIds.length; i += MAX_REDIS_BATCH_SIZE) { - const keys = queueIds - .slice(i, i + MAX_REDIS_BATCH_SIZE) - .map(this.transactionDetailsKey); - numDeleted += await redis.unlink(...keys); - } - return numDeleted; - }; - - /** - * Check if a transaction exists. - * @param queueId - * @returns true if the transaction exists, else false. - */ - static exists = async (queueId: string): Promise => - (await redis.exists(this.transactionDetailsKey(queueId))) > 0; - - /** - * Lists all transaction details by status. - * Returns results paginated in descending order. - * @param status "queued" | "mined" | "cancelled" | "errored" - * @param page - * @param limit - * @returns - */ - static getTransactionListByStatus = async (args: { - status: "queued" | "mined" | "cancelled" | "errored"; - page: number; - limit: number; - }): Promise<{ transactions: AnyTransaction[]; totalCount: number }> => { - const { status, page, limit } = args; - const start = (page - 1) * limit; - const end = start + limit - 1; - - const key = - status === "mined" - ? this.minedTransactionsKey - : status === "cancelled" - ? this.cancelledTransactionsKey - : status === "errored" - ? this.erroredTransactionsKey - : this.queuedTransactionsKey; - - const queueIds = await redis.zrevrange(key, start, end); - const transactions = await this.bulkGet(queueIds); - const totalCount = await redis.zcard(key); - - return { transactions, totalCount }; - }; - - /** - * Prunes transaction details and lists, keeping the latest `keep` amount/ - * @param keep number - The max recent transactions to not prune. - * @returns number - The number of transactions pruned. - */ - static pruneTransactionDetailsAndLists = async (keep: number) => { - // Delete up to `keep - 1` index, inclusive. - const stop = -keep - 1; - - const queueIds = await redis.zrange(this.queuedTransactionsKey, 0, stop); - const numPruned = await this.bulkDelete(queueIds); - - await redis - .pipeline() - .zremrangebyrank(this.queuedTransactionsKey, 0, stop) - .zremrangebyrank(this.minedTransactionsKey, 0, stop) - .zremrangebyrank(this.cancelledTransactionsKey, 0, stop) - .zremrangebyrank(this.erroredTransactionsKey, 0, stop) - .exec(); - - return numPruned; - }; -} - -const toSeconds = (timestamp: Date) => timestamp.getTime() / 1000; diff --git a/src/shared/db/transactions/queue-tx.ts b/src/shared/db/transactions/queue-tx.ts deleted file mode 100644 index 508e5207e..000000000 --- a/src/shared/db/transactions/queue-tx.ts +++ /dev/null @@ -1,105 +0,0 @@ -import type { DeployTransaction, Transaction } from "@thirdweb-dev/sdk"; -import type { ERC4337EthersSigner } from "@thirdweb-dev/wallets/dist/declarations/src/evm/connectors/smart-wallet/lib/erc4337-signer"; -import { ZERO_ADDRESS, type Address } from "thirdweb"; -import type { ContractExtension } from "../../schemas/extension"; -import { maybeBigInt, normalizeAddress } from "../../utils/primitive-types"; -import { insertTransaction } from "../../utils/transaction/insert-transaction"; -import type { AnyTransaction, InsertedTransaction } from "../../utils/transaction/types"; -import { parseTransactionOverrides } from "../../../server/utils/transaction-overrides"; - -interface QueueTxParams { - // we should move away from Transaction type (v4 SDK) - tx: Transaction | DeployTransaction; - chainId: number; - extension: ContractExtension; - // TODO: These shouldn't be in here - deployedContractAddress?: Address; - deployedContractType?: string; - simulateTx?: boolean; - idempotencyKey?: string; - accountFactoryAddress?: Address; - transactionMode?: AnyTransaction["transactionMode"]; - txOverrides?: { - gas?: string; - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - value?: string; - }; -} - -export const queueTx = async ({ - tx, - chainId, - extension, - deployedContractAddress, - deployedContractType, - simulateTx, - idempotencyKey, - txOverrides, - accountFactoryAddress, - transactionMode -}: QueueTxParams) => { - // Transaction Details - const functionName = tx.getMethod(); - const encodedData = tx.encode(); - const value = maybeBigInt( - txOverrides?.value ?? (await tx.getValue().toString()), - ); - const functionArgs = tx.getArgs(); - const baseTransaction = { - chainId, - value, - data: encodedData as unknown as `0x${string}`, - functionName, - functionArgs, - extension, - ...parseTransactionOverrides(txOverrides), - } satisfies Partial; - - // TODO: We need a much safer way of detecting if the transaction should be a user operation - const isUserOp = !!(tx.getSigner as ERC4337EthersSigner).erc4337provider; - - if (isUserOp) { - const signer = (tx.getSigner as ERC4337EthersSigner).originalSigner; - const signerAddress = normalizeAddress(await signer.getAddress()); - - return await insertTransaction({ - insertedTransaction: { - ...baseTransaction, - isUserOp: true, - deployedContractAddress, - deployedContractType, - from: signerAddress, - signerAddress, - accountAddress: normalizeAddress(await tx.getSignerAddress()), - target: normalizeAddress(tx.getTarget()), - accountFactoryAddress, - transactionMode: undefined, - }, - idempotencyKey, - shouldSimulate: simulateTx, - }); - } - - const isPublishedContractDeploy = - tx.getTarget() === ZERO_ADDRESS && - functionName === "deploy" && - extension === "deploy-published"; - - return await insertTransaction({ - insertedTransaction: { - ...baseTransaction, - isUserOp: false, - // NOTE: v4 endpoints don't all support sponsored mode - transactionMode, - deployedContractAddress, - deployedContractType, - from: normalizeAddress(await tx.getSignerAddress()), - to: normalizeAddress( - isPublishedContractDeploy ? undefined : tx.getTarget(), - ), - }, - idempotencyKey, - shouldSimulate: simulateTx, - }); -}; diff --git a/src/shared/db/wallet-credentials/create-wallet-credential.ts b/src/shared/db/wallet-credentials/create-wallet-credential.ts deleted file mode 100644 index 51b9cae76..000000000 --- a/src/shared/db/wallet-credentials/create-wallet-credential.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { encrypt } from "../../utils/crypto"; -import { prisma } from "../client"; -import { getConfig } from "../../utils/cache/get-config"; -import { WalletCredentialsError } from "./get-wallet-credential"; - -// will be expanded to be a discriminated union of all supported wallet types -export type CreateWalletCredentialsParams = { - type: "circle"; - label: string; - entitySecret: string; - isDefault?: boolean; -}; - -export const createWalletCredential = async ({ - type, - label, - entitySecret, - isDefault, -}: CreateWalletCredentialsParams) => { - const { walletConfiguration } = await getConfig(); - switch (type) { - case "circle": { - const circleApiKey = walletConfiguration.circle?.apiKey; - if (!circleApiKey) { - throw new WalletCredentialsError("No Circle API Key Configured"); - } - // Create the wallet credentials - const walletCredentials = await prisma.walletCredentials.create({ - data: { - type, - label, - isDefault: isDefault || null, - data: { - entitySecret: encrypt(entitySecret), - }, - }, - }); - return walletCredentials; - } - } -}; diff --git a/src/shared/db/wallet-credentials/get-all-wallet-credentials.ts b/src/shared/db/wallet-credentials/get-all-wallet-credentials.ts deleted file mode 100644 index 828cbdb6a..000000000 --- a/src/shared/db/wallet-credentials/get-all-wallet-credentials.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { prisma } from "../client"; -import type { PrismaTransaction } from "../../schemas/prisma"; - -interface GetAllWalletCredentialsParams { - pgtx?: PrismaTransaction; - page?: number; - limit?: number; -} - -export const getAllWalletCredentials = async ({ - page = 1, - limit = 10, -}: GetAllWalletCredentialsParams) => { - const credentials = await prisma.walletCredentials.findMany({ - where: { - deletedAt: null, - }, - skip: (page - 1) * limit, - take: limit, - select: { - id: true, - type: true, - label: true, - isDefault: true, - createdAt: true, - updatedAt: true, - }, - orderBy: { - createdAt: "desc", - }, - }); - - return credentials; -}; diff --git a/src/shared/db/wallet-credentials/get-wallet-credential.ts b/src/shared/db/wallet-credentials/get-wallet-credential.ts deleted file mode 100644 index f1cf5107f..000000000 --- a/src/shared/db/wallet-credentials/get-wallet-credential.ts +++ /dev/null @@ -1,81 +0,0 @@ -import LRUMap from "mnemonist/lru-map"; -import { z } from "zod"; -import { decrypt } from "../../utils/crypto"; -import { env } from "../../utils/env"; -import { prisma } from "../client"; - -export class WalletCredentialsError extends Error { - constructor(message: string) { - super(message); - this.name = "WalletCredentialsError"; - } -} - -const walletCredentialsSchema = z.object({ - id: z.string(), - type: z.literal("circle"), - label: z.string().nullable(), - data: z.object({ - entitySecret: z.string(), - }), - isDefault: z.boolean().nullable(), - createdAt: z.date(), - updatedAt: z.date(), - deletedAt: z.date().nullable(), -}); - -export type ParsedWalletCredential = z.infer; - -export const walletCredentialsCache = new LRUMap< - string, - ParsedWalletCredential ->(2048); - -interface GetWalletCredentialParams { - id: string; -} - -/** - * Return the wallet credentials for the given id. - * The entitySecret will be decrypted. - * If the credentials are not found, an error is thrown. - */ -export const getWalletCredential = async ({ - id, -}: GetWalletCredentialParams) => { - const cachedCredentials = walletCredentialsCache.get(id); - if (cachedCredentials) { - return cachedCredentials; - } - - const credential = await prisma.walletCredentials.findUnique({ - where: { - id, - }, - }); - - if (!credential) { - throw new WalletCredentialsError( - `No wallet credentials found for id ${id}`, - ); - } - - const { data: parsedCredential, error: parseError } = - walletCredentialsSchema.safeParse(credential); - - if (parseError) { - throw new WalletCredentialsError( - `Invalid Credential found for ${id}:\n${parseError.errors - .map((error) => error.message) - .join(", ")}`, - ); - } - - parsedCredential.data.entitySecret = decrypt( - parsedCredential.data.entitySecret, - env.ENCRYPTION_PASSWORD, - ); - - walletCredentialsCache.set(id, parsedCredential); - return parsedCredential; -}; diff --git a/src/shared/db/wallet-credentials/update-wallet-credential.ts b/src/shared/db/wallet-credentials/update-wallet-credential.ts deleted file mode 100644 index 018eb5627..000000000 --- a/src/shared/db/wallet-credentials/update-wallet-credential.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { getWalletCredential } from "./get-wallet-credential"; -import { encrypt } from "../../utils/crypto"; -import { prisma } from "../client"; -import { cirlceEntitySecretZodSchema } from "../../schemas/wallet"; - -interface UpdateWalletCredentialParams { - id: string; - label?: string; - isDefault?: boolean; - entitySecret?: string; -} - -type UpdateData = { - label?: string; - isDefault: boolean | null; - data?: { - entitySecret: string; - }; -}; - -export const updateWalletCredential = async ({ - id, - label, - isDefault, - entitySecret, -}: UpdateWalletCredentialParams) => { - // First check if credential exists - await getWalletCredential({ id }); - - // If entitySecret is provided, validate and encrypt it - const data: UpdateData = { - label, - isDefault: isDefault || null, - }; - - if (entitySecret) { - // Validate the entity secret - cirlceEntitySecretZodSchema.parse(entitySecret); - - // Only update data field if entitySecret is provided - data.data = { - entitySecret: encrypt(entitySecret), - }; - } - - // Update the credential - const updatedCredential = await prisma.walletCredentials.update({ - where: { - id, - }, - data, - }); - - return updatedCredential; -}; diff --git a/src/shared/db/wallets/create-wallet-details.ts b/src/shared/db/wallets/create-wallet-details.ts deleted file mode 100644 index 6655e086d..000000000 --- a/src/shared/db/wallets/create-wallet-details.ts +++ /dev/null @@ -1,170 +0,0 @@ -import type { Address } from "thirdweb"; -import type { PrismaTransaction } from "../../schemas/prisma"; -import { encrypt } from "../../utils/crypto"; -import { getPrismaWithPostgresTx } from "../client"; - -// TODO: Case on types by wallet type -type CreateWalletDetailsParams = { - pgtx?: PrismaTransaction; - address: string; - label?: string; -} & ( - | { - type: "local"; - encryptedJson: string; // ENCRYPTION IS NOT HANDLED HERE, process privatekey with legacyLocalCrytpo before passing to this function - } - | { - type: "aws-kms"; - awsKmsKeyId?: string; // deprecated and unused, todo: remove with next breaking change - awsKmsArn: string; - - awsKmsSecretAccessKey: string; // will be encrypted and stored, pass plaintext to this function - awsKmsAccessKeyId: string; - } - | { - type: "gcp-kms"; - gcpKmsResourcePath: string; - gcpKmsKeyRingId?: string; // deprecated and unused, todo: remove with next breaking change - gcpKmsKeyId?: string; // deprecated and unused, todo: remove with next breaking change - gcpKmsKeyVersionId?: string; // deprecated and unused, todo: remove with next breaking change - gcpKmsLocationId?: string; // deprecated and unused, todo: remove with next breaking change - - gcpApplicationCredentialPrivateKey: string; // will be encrypted and stored, pass plaintext to this function - gcpApplicationCredentialEmail: string; - } - | { - type: "smart:aws-kms"; - awsKmsArn: string; - awsKmsSecretAccessKey: string; // will be encrypted and stored, pass plaintext to this function - awsKmsAccessKeyId: string; - accountSignerAddress: Address; - - accountFactoryAddress: Address | undefined; - entrypointAddress: Address | undefined; - } - | { - type: "smart:gcp-kms"; - gcpKmsResourcePath: string; - gcpApplicationCredentialPrivateKey: string; // will be encrypted and stored, pass plaintext to this function - gcpApplicationCredentialEmail: string; - accountSignerAddress: Address; - - accountFactoryAddress: Address | undefined; - entrypointAddress: Address | undefined; - } - | { - type: "smart:local"; - encryptedJson: string; // ENCRYPTION IS NOT HANDLED HERE, process privatekey with legacyLocalCrytpo before passing to this function - accountSignerAddress: Address; - - accountFactoryAddress: Address | undefined; - entrypointAddress: Address | undefined; - } -); - -/** - * Create a new WalletDetails row in DB - */ -export const createWalletDetails = async ({ - pgtx, - ...walletDetails -}: CreateWalletDetailsParams) => { - const prisma = getPrismaWithPostgresTx(pgtx); - - const wallet = await prisma.walletDetails.findUnique({ - where: { - address: walletDetails.address.toLowerCase(), - }, - }); - - if (wallet) { - throw new Error( - `Wallet with address ${walletDetails.address} has already been added!`, - ); - } - - if (walletDetails.type === "local") { - return prisma.walletDetails.create({ - data: { - ...walletDetails, - address: walletDetails.address.toLowerCase(), - encryptedJson: walletDetails.encryptedJson, - }, - }); - } - - if (walletDetails.type === "aws-kms") { - return prisma.walletDetails.create({ - data: { - ...walletDetails, - address: walletDetails.address.toLowerCase(), - - awsKmsSecretAccessKey: encrypt(walletDetails.awsKmsSecretAccessKey), - }, - }); - } - - if (walletDetails.type === "gcp-kms") { - return prisma.walletDetails.create({ - data: { - ...walletDetails, - address: walletDetails.address.toLowerCase(), - - gcpApplicationCredentialPrivateKey: encrypt( - walletDetails.gcpApplicationCredentialPrivateKey, - ), - }, - }); - } - - if (walletDetails.type === "smart:aws-kms") { - return prisma.walletDetails.create({ - data: { - ...walletDetails, - - address: walletDetails.address.toLowerCase(), - awsKmsSecretAccessKey: encrypt(walletDetails.awsKmsSecretAccessKey), - accountSignerAddress: walletDetails.accountSignerAddress.toLowerCase(), - - accountFactoryAddress: - walletDetails.accountFactoryAddress?.toLowerCase(), - entrypointAddress: walletDetails.entrypointAddress?.toLowerCase(), - }, - }); - } - - if (walletDetails.type === "smart:gcp-kms") { - return prisma.walletDetails.create({ - data: { - ...walletDetails, - - address: walletDetails.address.toLowerCase(), - accountSignerAddress: walletDetails.accountSignerAddress.toLowerCase(), - - gcpApplicationCredentialPrivateKey: encrypt( - walletDetails.gcpApplicationCredentialPrivateKey, - ), - - accountFactoryAddress: - walletDetails.accountFactoryAddress?.toLowerCase(), - entrypointAddress: walletDetails.entrypointAddress?.toLowerCase(), - }, - }); - } - - if (walletDetails.type === "smart:local") { - return prisma.walletDetails.create({ - data: { - ...walletDetails, - address: walletDetails.address.toLowerCase(), - accountSignerAddress: walletDetails.accountSignerAddress.toLowerCase(), - - accountFactoryAddress: - walletDetails.accountFactoryAddress?.toLowerCase(), - entrypointAddress: walletDetails.entrypointAddress?.toLowerCase(), - }, - }); - } - - throw new Error("Unsupported wallet type"); -}; diff --git a/src/shared/db/wallets/delete-wallet-details.ts b/src/shared/db/wallets/delete-wallet-details.ts deleted file mode 100644 index 96aeb3860..000000000 --- a/src/shared/db/wallets/delete-wallet-details.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Address } from "thirdweb"; -import { prisma } from "../client"; - -export const deleteWalletDetails = async (walletAddress: Address) => { - return prisma.walletDetails.delete({ - where: { - address: walletAddress.toLowerCase(), - }, - }); -}; diff --git a/src/shared/db/wallets/get-all-wallets.ts b/src/shared/db/wallets/get-all-wallets.ts deleted file mode 100644 index 249ea2c1c..000000000 --- a/src/shared/db/wallets/get-all-wallets.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { PrismaTransaction } from "../../schemas/prisma"; -import { getPrismaWithPostgresTx } from "../client"; - -interface GetAllWalletsParams { - pgtx?: PrismaTransaction; - page: number; - limit: number; -} - -export const getAllWallets = async ({ - pgtx, - page, - limit, -}: GetAllWalletsParams) => { - const prisma = getPrismaWithPostgresTx(pgtx); - - return prisma.walletDetails.findMany({ - skip: (page - 1) * limit, - take: limit, - }); -}; diff --git a/src/shared/db/wallets/get-wallet-details.ts b/src/shared/db/wallets/get-wallet-details.ts deleted file mode 100644 index 0258feb79..000000000 --- a/src/shared/db/wallets/get-wallet-details.ts +++ /dev/null @@ -1,258 +0,0 @@ -import LRUMap from "mnemonist/lru-map"; -import { getAddress } from "thirdweb"; -import { z } from "zod"; -import type { PrismaTransaction } from "../../schemas/prisma"; -import { getConfig } from "../../utils/cache/get-config"; -import { decrypt } from "../../utils/crypto"; -import { env } from "../../utils/env"; -import { getPrismaWithPostgresTx } from "../client"; - -interface GetWalletDetailsParams { - pgtx?: PrismaTransaction; - address: string; -} - -export class WalletDetailsError extends Error { - constructor(message: string) { - super(message); - this.name = "WalletDetailsError"; - } -} - -/** - * Use the Zod schema to validate the EVM address. - * Uses getAddress from thirdweb/utils to validate the address. - */ -const zodEvmAddressSchema = z.string().transform((address, ctx) => { - try { - return getAddress(address); - } catch { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: "Invalid EVM address format", - }); - return z.NEVER; - } -}); - -const baseWalletPartialSchema = z.object({ - address: zodEvmAddressSchema, - label: z.string().nullable(), -}); - -const smartWalletPartialSchema = z.object({ - accountSignerAddress: zodEvmAddressSchema, - accountFactoryAddress: zodEvmAddressSchema.nullable(), - entrypointAddress: zodEvmAddressSchema.nullable(), -}); - -const localWalletSchema = z - .object({ - type: z.literal("local"), - encryptedJson: z.string(), - }) - .merge(baseWalletPartialSchema); - -const smartLocalWalletSchema = localWalletSchema - .extend({ - type: z.literal("smart:local"), - }) - .merge(smartWalletPartialSchema); - -const awsKmsWalletSchema = z - .object({ - type: z.literal("aws-kms"), - awsKmsArn: z.string(), - awsKmsSecretAccessKey: z.string(), - awsKmsAccessKeyId: z.string(), - }) - .merge(baseWalletPartialSchema); - -const smartAwsKmsWalletSchema = awsKmsWalletSchema - .extend({ - type: z.literal("smart:aws-kms"), - }) - .merge(smartWalletPartialSchema); - -const gcpKmsWalletSchema = z - .object({ - type: z.literal("gcp-kms"), - gcpKmsResourcePath: z.string(), - gcpApplicationCredentialPrivateKey: z.string(), - gcpApplicationCredentialEmail: z.string(), - }) - .merge(baseWalletPartialSchema); - -const smartGcpKmsWalletSchema = gcpKmsWalletSchema - .extend({ - type: z.literal("smart:gcp-kms"), - }) - .merge(smartWalletPartialSchema); - -const circleWalletSchema = z - .object({ - type: z.literal("circle"), - platformIdentifiers: z.object({ - circleWalletId: z.string(), - walletSetId: z.string(), - isTestnet: z.boolean(), - }), - credentialId: z.string(), - }) - .merge(baseWalletPartialSchema); - -const smartCircleWalletSchema = circleWalletSchema - .extend({ - type: z.literal("smart:circle"), - }) - .merge(smartWalletPartialSchema); - -const walletDetailsSchema = z.discriminatedUnion("type", [ - localWalletSchema, - smartLocalWalletSchema, - awsKmsWalletSchema, - smartAwsKmsWalletSchema, - gcpKmsWalletSchema, - smartGcpKmsWalletSchema, - circleWalletSchema, - smartCircleWalletSchema, -]); - -export type SmartBackendWalletDetails = - | z.infer - | z.infer - | z.infer - | z.infer; - -export function isSmartBackendWallet( - wallet: ParsedWalletDetails, -): wallet is SmartBackendWalletDetails { - return SmartBackendWalletTypes.includes( - wallet.type as SmartBackendWalletType, - ); -} - -export const SmartBackendWalletTypes = [ - "smart:local", - "smart:aws-kms", - "smart:gcp-kms", - "smart:circle", -] as const; - -export const BackendWalletTypes = [ - "local", - "aws-kms", - "gcp-kms", - "circle", - ...SmartBackendWalletTypes, -] as const; - -export type SmartBackendWalletType = (typeof SmartBackendWalletTypes)[number]; -export type BackendWalletType = (typeof BackendWalletTypes)[number]; -export type ParsedWalletDetails = z.infer; - -export const walletDetailsCache = new LRUMap(2048); -/** - * Return the wallet details for the given address. - * - * If the wallet is an AWS KMS wallet, the AWS KMS secret access key is decrypted. - * - * If the wallet is a GCP KMS wallet, the GCP KMS application credential private key is decrypted. - * - * If any required parameter cannot be resolved from either the configuration or the overrides, an error is thrown. - * - * If the wallet is not found, an error is thrown. - */ -export const getWalletDetails = async ({ - pgtx, - address: _walletAddress, -}: GetWalletDetailsParams) => { - const walletAddress = _walletAddress.toLowerCase(); - const cachedDetails = walletDetailsCache.get(walletAddress); - if (cachedDetails) { - return cachedDetails; - } - - const prisma = getPrismaWithPostgresTx(pgtx); - const config = await getConfig(); - - const walletDetails = await prisma.walletDetails.findUnique({ - where: { - address: walletAddress.toLowerCase(), - }, - }); - - if (!walletDetails) { - throw new WalletDetailsError( - `No wallet details found for address ${walletAddress}`, - ); - } - - // handle AWS KMS wallets - if ( - walletDetails.type === "aws-kms" || - walletDetails.type === "smart:aws-kms" - ) { - if (!walletDetails.awsKmsArn) { - throw new WalletDetailsError( - `AWS KMS ARN is missing for the wallet with address ${walletAddress}`, - ); - } - - walletDetails.awsKmsSecretAccessKey = walletDetails.awsKmsSecretAccessKey - ? decrypt(walletDetails.awsKmsSecretAccessKey, env.ENCRYPTION_PASSWORD) - : config.walletConfiguration.aws?.awsSecretAccessKey ?? null; - - walletDetails.awsKmsAccessKeyId = - walletDetails.awsKmsAccessKeyId ?? - config.walletConfiguration.aws?.awsAccessKeyId ?? - null; - } - - // handle GCP KMS wallets - if ( - walletDetails.type === "gcp-kms" || - walletDetails.type === "smart:gcp-kms" - ) { - if (!walletDetails.gcpKmsResourcePath) { - throw new WalletDetailsError( - `GCP KMS resource path is missing for the wallet with address ${walletAddress}`, - ); - } - - walletDetails.gcpApplicationCredentialPrivateKey = - walletDetails.gcpApplicationCredentialPrivateKey - ? decrypt( - walletDetails.gcpApplicationCredentialPrivateKey, - env.ENCRYPTION_PASSWORD, - ) - : config.walletConfiguration.gcp?.gcpApplicationCredentialPrivateKey ?? - null; - - walletDetails.gcpApplicationCredentialEmail = - walletDetails.gcpApplicationCredentialEmail ?? - config.walletConfiguration.gcp?.gcpApplicationCredentialEmail ?? - null; - } - - // zod schema can validate all necessary fields are populated after decryption - try { - const result = walletDetailsSchema.parse(walletDetails, { - errorMap: (issue) => { - const fieldName = issue.path.join("."); - return { - message: `${fieldName} is necessary for wallet ${walletAddress} of type ${walletDetails.type}, but not found in wallet details or configuration`, - }; - }, - }); - walletDetailsCache.set(walletAddress, result); - return result; - } catch (e) { - if (e instanceof z.ZodError) { - throw new WalletDetailsError( - e.errors.map((error) => error.message).join(", "), - ); - } - throw e; - } -}; diff --git a/src/shared/db/wallets/nonce-map.ts b/src/shared/db/wallets/nonce-map.ts deleted file mode 100644 index 587a0529b..000000000 --- a/src/shared/db/wallets/nonce-map.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { Address } from "thirdweb"; -import { env } from "../../utils/env"; -import { normalizeAddress } from "../../utils/primitive-types"; -import { redis } from "../../utils/redis/redis"; - -/** - * The "nonce map" sorted set stores the queue ID that acquired each nonce. - * It is pruned to the latest 10k per wallet. - * - * Example: - * { - * "10": "e0fa731e-a947-4587-a48a-c56c02f8e7a8" - * "11": "d111435a-1c0c-4308-ba40-59bad0868ee6" - * } - */ -const nonceMapKey = (chainId: number, walletAddress: Address) => - `nonce-map:${chainId}:${normalizeAddress(walletAddress)}`; - -export const updateNonceMap = async (args: { - chainId: number; - walletAddress: Address; - nonce: number; - queueId: string; -}) => { - const { chainId, walletAddress, nonce, queueId } = args; - const key = nonceMapKey(chainId, walletAddress); - await redis.zadd(key, nonce, queueId); -}; - -/** - * Returns (nonce, queueId) pairs sorted by ascending nonce for the - * given wallet between the specified range. - */ -export const getNonceMap = async (args: { - chainId: number; - walletAddress: Address; - fromNonce: number; - toNonce?: number; -}): Promise<{ nonce: number; queueId: string }[]> => { - const { chainId, walletAddress, fromNonce, toNonce } = args; - const key = nonceMapKey(chainId, walletAddress); - - // Returns [ queueId1, nonce1, queueId2, nonce2, ... ] - const elementsWithScores = await redis.zrangebyscore( - key, - fromNonce, - // If toNonce is not provided, do not set an upper bound on the score. - toNonce ?? "+inf", - "WITHSCORES", - ); - - const result: { nonce: number; queueId: string }[] = []; - for (let i = 0; i < elementsWithScores.length; i += 2) { - result.push({ - queueId: elementsWithScores[i], - nonce: Number.parseInt(elementsWithScores[i + 1]), - }); - } - return result; -}; - -export const pruneNonceMaps = async () => { - const pipeline = redis.pipeline(); - const keys = await redis.keys("nonce-map:*"); - for (const key of keys) { - pipeline.zremrangebyrank(key, 0, -env.NONCE_MAP_COUNT); - } - const results = await pipeline.exec(); - if (!results) { - return 0; - } - - let numDeleted = 0; - for (const [error, result] of results) { - if (!error) { - numDeleted += Number.parseInt(result as string); - } - } - return numDeleted; -}; diff --git a/src/shared/db/wallets/update-wallet-details.ts b/src/shared/db/wallets/update-wallet-details.ts deleted file mode 100644 index 570c28e60..000000000 --- a/src/shared/db/wallets/update-wallet-details.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { prisma } from "../client"; - -interface UpdateWalletDetailsParams { - address: string; - label?: string; -} - -export const updateWalletDetails = async ({ - address, - label, -}: UpdateWalletDetailsParams) => { - await prisma.walletDetails.update({ - where: { - address: address.toLowerCase(), - }, - data: { - label, - }, - }); -}; diff --git a/src/shared/db/wallets/wallet-nonce.ts b/src/shared/db/wallets/wallet-nonce.ts deleted file mode 100644 index c7c0ea148..000000000 --- a/src/shared/db/wallets/wallet-nonce.ts +++ /dev/null @@ -1,302 +0,0 @@ -import { - eth_getTransactionCount, - getAddress, - getRpcClient, - type Address, -} from "thirdweb"; -import { getChain } from "../../utils/chain"; -import { logger } from "../../utils/logger"; -import { normalizeAddress } from "../../utils/primitive-types"; -import { redis } from "../../utils/redis/redis"; -import { thirdwebClient } from "../../utils/sdk"; -import { updateNonceMap } from "./nonce-map"; -import { nonceHistoryKey } from "../../../worker/tasks/nonce-health-check-worker"; - -/** - * Get all used backend wallets. - * Filters by chainId and walletAddress if provided. - * Reads all the keys in the format `nonce:${chainId}:${walletAddress}` in the Redis DB. - * - * @example - * getUsedBackendWallets() - * // [ { chainId: 80001, walletAddress: "0x1234...5678" } ] - */ -export const getUsedBackendWallets = async ( - chainId?: number, - walletAddress?: Address, -): Promise< - { - chainId: number; - walletAddress: Address; - }[] -> => { - const keys = await redis.keys( - `nonce:${chainId ?? "*"}:${ - walletAddress ? normalizeAddress(walletAddress) : "*" - }`, - ); - return keys.map((key) => { - const tokens = key.split(":"); - return { - chainId: Number.parseInt(tokens[1]), - walletAddress: getAddress(tokens[2]), - }; - }); -}; - -/** - * The "last used nonce" stores the last nonce submitted onchain. - * Example: 25 -> nonce 25 is onchain, nonce 26 is unused or inflight. - */ -export const lastUsedNonceKey = (chainId: number, walletAddress: Address) => - `nonce:${chainId}:${normalizeAddress(walletAddress)}`; - -/** - * Split the last used nonce key into chainId and walletAddress. - * @param key - * @returns { chainId: number, walletAddress: Address } - * @example - * splitLastUsedNonceKey("nonce:80001:0x1234...5678") - * // { chainId: 80001, walletAddress: "0x1234...5678" } - */ -export const splitLastUsedNonceKey = (key: string) => { - const _splittedKeys = key.split(":"); - const walletAddress = normalizeAddress(_splittedKeys[2]); - const chainId = Number.parseInt(_splittedKeys[1]); - return { walletAddress, chainId }; -}; - -/** - * The "recycled nonces" set stores unsorted nonces to be reused or cancelled. - * Example: [ "25", "23", "24" ] - */ -export const recycledNoncesKey = (chainId: number, walletAddress: Address) => - `nonce-recycled:${chainId}:${normalizeAddress(walletAddress)}`; - -/** - * The "sent nonces" set stores nonces that have been sent on chain but not yet mined. - * - * Example: [ "25", "23", "24" ] - * - * The `nonceResyncWorker` periodically fetches the onchain transaction count for each wallet (a), - * compares it to the last nonce sent (b), and for every nonce between b and a, - * it recycles the nonce if the nonce is not in this set. - */ -export const sentNoncesKey = (chainId: number, walletAddress: Address) => - `nonce-sent:${chainId}:${normalizeAddress(walletAddress)}`; - -export const splitSentNoncesKey = (key: string) => { - const _splittedKeys = key.split(":"); - const walletAddress = normalizeAddress(_splittedKeys[2]); - const chainId = Number.parseInt(_splittedKeys[1]); - return { walletAddress, chainId }; -}; - -/** - * Adds a nonce to the sent nonces set (`nonce-sent:${chainId}:${walletAddress}`). - */ -export const addSentNonce = async ( - chainId: number, - walletAddress: Address, - nonce: number, -) => { - const key = sentNoncesKey(chainId, walletAddress); - await redis.sadd(key, nonce.toString()); -}; - -/** - * Removes a nonce from the sent nonces set (`nonce-sent:${chainId}:${walletAddress}`). - */ -export const removeSentNonce = async ( - chainId: number, - walletAddress: Address, - nonce: number, -) => { - const key = sentNoncesKey(chainId, walletAddress); - const removed = await redis.srem(key, nonce.toString()); - return removed === 1; -}; - -/** - * Check if a nonce is in the sent nonces set. - */ -export const isSentNonce = async ( - chainId: number, - walletAddress: Address, - nonce: number, -) => { - const key = sentNoncesKey(chainId, walletAddress); - return !!(await redis.sismember(key, nonce.toString())); -}; - -/** - * Acquire an unused nonce to send an EOA transaction for the given backend wallet. - * @param chainId - * @param walletAddress - * @returns number - */ -export const acquireNonce = async (args: { - queueId: string; - chainId: number; - walletAddress: Address; -}): Promise<{ nonce: number; isRecycledNonce: boolean }> => { - const { queueId, chainId, walletAddress } = args; - - let isRecycledNonce = false; - - // Try to acquire the lowest recycled nonce first - let nonce = await _acquireRecycledNonce(chainId, walletAddress); - if (nonce !== null) { - isRecycledNonce = true; - } else { - // Else increment the last used nonce. - const key = lastUsedNonceKey(chainId, walletAddress); - nonce = await redis.incr(key); - if (nonce === 1) { - // If INCR returned 1, the nonce was not set. - // This may be a newly imported wallet. - // Sync the onchain value and increment again. - await syncLatestNonceFromOnchain(chainId, walletAddress); - nonce = await redis.incr(key); - } - } - - await updateNonceMap({ - chainId, - walletAddress, - nonce, - queueId, - }); - return { nonce, isRecycledNonce }; -}; - -/** - * Recycles a nonce to be used by a future transaction. - * This should be used if the current transaction that acquired this nonce is not valid. - * @param chainId - * @param walletAddress - * @param nonce - */ -export const recycleNonce = async ( - chainId: number, - walletAddress: Address, - nonce: number, -) => { - if (Number.isNaN(nonce)) { - logger({ - level: "warn", - message: `[recycleNonce] Invalid nonce: ${nonce}`, - service: "worker", - }); - return; - } - - const key = recycledNoncesKey(chainId, walletAddress); - await redis.zadd(key, nonce, nonce.toString()); -}; - -/** - * Acquires the lowest recycled nonce that is unused. - * @param chainId - * @param walletAddress - * @returns - */ -const _acquireRecycledNonce = async ( - chainId: number, - walletAddress: Address, -): Promise => { - const key = recycledNoncesKey(chainId, walletAddress); - const result = await redis.zpopmin(key); - if (result.length === 0) { - return null; - } - return Number.parseInt(result[0]); -}; - -/** - * Resync the nonce to the onchain nonce. - * @TODO: Redis lock this to make this method safe to call concurrently. - */ -export const syncLatestNonceFromOnchain = async ( - chainId: number, - walletAddress: Address, -) => { - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - - // The next unused nonce = transactionCount. - const transactionCount = await eth_getTransactionCount(rpcRequest, { - address: walletAddress, - blockTag: "latest", - }); - - const key = lastUsedNonceKey(chainId, walletAddress); - await redis.set(key, transactionCount - 1); -}; - -/** - * Returns the last used nonce. - * This function should be used to inspect nonce values only. - * Use `acquireNonce` to fetch a nonce for sending a transaction. - * @param chainId - * @param walletAddress - * @returns number - */ -export const inspectNonce = async (chainId: number, walletAddress: Address) => { - const key = lastUsedNonceKey(chainId, walletAddress); - const nonce = await redis.get(key); - return nonce ? Number.parseInt(nonce) : 0; -}; - -/** - * Delete nonce state for the provided wallets. - * @param backendWallets - */ -export async function deleteNoncesForBackendWallets( - backendWallets: { chainId: number; walletAddress: Address }[], -) { - const keys = backendWallets.flatMap(({ chainId, walletAddress }) => [ - lastUsedNonceKey(chainId, walletAddress), - recycledNoncesKey(chainId, walletAddress), - sentNoncesKey(chainId, walletAddress), - nonceHistoryKey(chainId, walletAddress), - ]); - await redis.del(keys); -} - -/** - * Resync the nonce to the higher of (db nonce, onchain nonce). - */ -export const syncLatestNonceFromOnchainIfHigher = async ( - chainId: number, - walletAddress: Address, -) => { - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - - // The next unused nonce = transactionCount. - const transactionCount = await eth_getTransactionCount(rpcRequest, { - address: walletAddress, - blockTag: "latest", - }); - - // Lua script to update the DB nonce only if the onchain nonce is higher. - const script = ` - local transactionCount = tonumber(ARGV[1]) - local lastUsedNonce = tonumber(redis.call('get', KEYS[1])) or 0 - local nextNonce = math.max(transactionCount-1, lastUsedNonce) - redis.call('set', KEYS[1], nextNonce) - return nextNonce - `; - const lastUsedNonce = await redis.eval( - script, - 1, - lastUsedNonceKey(chainId, normalizeAddress(walletAddress)), - transactionCount.toString(), - ); - return lastUsedNonce; -}; diff --git a/src/shared/db/webhooks/create-webhook.ts b/src/shared/db/webhooks/create-webhook.ts deleted file mode 100644 index ee07d770f..000000000 --- a/src/shared/db/webhooks/create-webhook.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { Webhooks } from "@prisma/client"; -import { createHash, randomBytes } from "node:crypto"; -import type { WebhooksEventTypes } from "../../schemas/webhooks"; -import { prisma } from "../client"; - -interface CreateWebhooksParams { - url: string; - name?: string; - eventType: WebhooksEventTypes; -} - -export const insertWebhook = async ({ - url, - name, - eventType, -}: CreateWebhooksParams): Promise => { - // generate random bytes - const bytes = randomBytes(4096); - // hash the bytes to create the secret (this will not be stored by itself) - const secret = createHash("sha512").update(bytes).digest("base64url"); - - return prisma.webhooks.create({ - data: { - url, - name, - eventType, - secret, - }, - }); -}; diff --git a/src/shared/db/webhooks/get-all-webhooks.ts b/src/shared/db/webhooks/get-all-webhooks.ts deleted file mode 100644 index 1f76e76c8..000000000 --- a/src/shared/db/webhooks/get-all-webhooks.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Webhooks } from "@prisma/client"; -import { prisma } from "../client"; - -export const getAllWebhooks = async (): Promise => { - return await prisma.webhooks.findMany({ - where: { - revokedAt: null, - }, - orderBy: { - id: "asc", - }, - }); -}; diff --git a/src/shared/db/webhooks/get-webhook.ts b/src/shared/db/webhooks/get-webhook.ts deleted file mode 100644 index 7242caa97..000000000 --- a/src/shared/db/webhooks/get-webhook.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { prisma } from "../client"; - -export const getWebhook = async (id: number) => { - return await prisma.webhooks.findUnique({ - where: { id }, - }); -}; diff --git a/src/shared/db/webhooks/revoke-webhook.ts b/src/shared/db/webhooks/revoke-webhook.ts deleted file mode 100644 index c986a6524..000000000 --- a/src/shared/db/webhooks/revoke-webhook.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { prisma } from "../client"; - -export const deleteWebhook = async (id: number) => { - const now = new Date(); - - return prisma.webhooks.update({ - where: { id }, - data: { - revokedAt: now, - updatedAt: now, - }, - }); -}; diff --git a/src/shared/lib/cache/swr.ts b/src/shared/lib/cache/swr.ts deleted file mode 100644 index 5f24157d7..000000000 --- a/src/shared/lib/cache/swr.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { logger } from "../../utils/logger"; - -type CacheEntry = { - data: T; - validUntil: number; -}; - -type SWROptions = { - ttlMs?: number; // How long until data is considered stale - maxEntries?: number; // Max number of entries to keep in cache -}; - -export class SWRCache { - private cache = new Map>(); - private inFlight = new Map>(); - private readonly options: Required; - - constructor(options: SWROptions = {}) { - this.options = { - ttlMs: options.ttlMs ?? 5 * 60 * 1000, // 5 minutes default - maxEntries: options.maxEntries ?? 1000, - }; - } - - async get(key: K, fetchFn: () => Promise): Promise { - const entry = this.cache.get(key); - const now = Date.now(); - - // If no cached data, handle fetch with deduplication - if (!entry) { - return this.dedupedFetch(key, fetchFn); - } - - // Check if stale - const isStale = now > entry.validUntil; - - // If stale, trigger background revalidation and return stale data - if (isStale) { - this.dedupedFetch(key, fetchFn).catch((error) => { - logger({ - service: "server", - level: "error", - message: `Failed to revalidate cache for key ${key}`, - error, - }); - // Silence background revalidation errors - }); - } - - return entry.data; - } - - private async dedupedFetch(key: K, fetchFn: () => Promise): Promise { - // Check for in-flight request - const inFlight = this.inFlight.get(key); - if (inFlight) { - return inFlight; - } - - // Create new request - const fetchPromise = (async () => { - try { - const data = await fetchFn(); - this.set(key, data); - return data; - } finally { - this.inFlight.delete(key); - } - })(); - - this.inFlight.set(key, fetchPromise); - return fetchPromise; - } - - private set(key: K, data: V): void { - if (this.cache.size >= this.options.maxEntries) { - const firstKey = this.cache.keys().next().value; - this.cache.delete(firstKey as K); - } - - this.cache.set(key, { - data, - validUntil: Date.now() + this.options.ttlMs, - }); - } -} - -export function createSWRCache(options?: SWROptions) { - return new SWRCache(options); -} diff --git a/src/shared/lib/chain/chain-capabilities.ts b/src/shared/lib/chain/chain-capabilities.ts deleted file mode 100644 index 7a584f5c5..000000000 --- a/src/shared/lib/chain/chain-capabilities.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { createSWRCache } from "../cache/swr"; - -const Services = [ - "contracts", - "connect-sdk", - "engine", - "account-abstraction", - "pay", - "rpc-edge", - "chainsaw", - "insight", -] as const; - -export type Service = (typeof Services)[number]; - -export type ChainCapabilities = Array<{ - service: Service; - enabled: boolean; -}>; - -// Create cache with 2048 entries and 30 minute TTL -const chainCapabilitiesCache = createSWRCache({ - maxEntries: 2048, - ttlMs: 1000 * 60 * 30, // 30 minutes -}); - -/** - * Get the capabilities of a chain (cached with stale-while-revalidate) - */ -export async function getChainCapabilities( - chainId: number, -): Promise { - return chainCapabilitiesCache.get(chainId, async () => { - const response = await fetch( - `https://api.thirdweb.com/v1/chains/${chainId}/services`, - ); - - const data = await response.json(); - - if (data.error) { - throw new Error(data.error); - } - - return data.data.services as ChainCapabilities; - }); -} - -/** - * Check if a chain supports a given service - */ -export async function doesChainSupportService( - chainId: number, - service: Service, -): Promise { - const chainCapabilities = await getChainCapabilities(chainId); - - return chainCapabilities.some( - (capability) => capability.service === service && capability.enabled, - ); -} diff --git a/src/shared/lib/transaction/get-transaction-receipt.ts b/src/shared/lib/transaction/get-transaction-receipt.ts deleted file mode 100644 index b95e108c8..000000000 --- a/src/shared/lib/transaction/get-transaction-receipt.ts +++ /dev/null @@ -1,73 +0,0 @@ -import assert from "node:assert"; -import { eth_getTransactionReceipt, getRpcClient } from "thirdweb"; -import type { UserOperationReceipt } from "thirdweb/dist/types/wallets/smart/types"; -import type { TransactionReceipt } from "thirdweb/transaction"; -import { getUserOpReceiptRaw } from "thirdweb/wallets/smart"; -import { getChain } from "../../utils/chain"; -import { thirdwebClient } from "../../utils/sdk"; -import type { AnyTransaction } from "../../utils/transaction/types"; - -/** - * Returns the transaction receipt for a given transaction, or null if not found. - * @param transaction - * @returns TransactionReceipt | null - */ -export async function getReceiptForEOATransaction( - transaction: AnyTransaction, -): Promise { - assert(!transaction.isUserOp); - - if (!("sentTransactionHashes" in transaction)) { - return null; - } - - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(transaction.chainId), - }); - - // Get the receipt for each transaction hash (in batches). - // Return if any receipt is found. - const BATCH_SIZE = 10; - for ( - let i = 0; - i < transaction.sentTransactionHashes.length; - i += BATCH_SIZE - ) { - const batch = transaction.sentTransactionHashes.slice(i, i + BATCH_SIZE); - const results = await Promise.allSettled( - batch.map((hash) => eth_getTransactionReceipt(rpcRequest, { hash })), - ); - - for (const result of results) { - if (result.status === "fulfilled") { - return result.value; - } - } - } - - return null; -} - -/** - * Returns the user operation receipt for a given transaction, or null if not found. - * The transaction receipt is available in the result under `result.receipt`. - * @param transaction - * @returns UserOperationReceipt | null - */ -export async function getReceiptForUserOp( - transaction: AnyTransaction, -): Promise { - assert(transaction.isUserOp); - - if (!("userOpHash" in transaction)) { - return null; - } - - const receipt = await getUserOpReceiptRaw({ - client: thirdwebClient, - chain: await getChain(transaction.chainId), - userOpHash: transaction.userOpHash, - }); - return receipt ?? null; -} diff --git a/src/shared/schemas/auth.ts b/src/shared/schemas/auth.ts deleted file mode 100644 index 2085c46cd..000000000 --- a/src/shared/schemas/auth.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Type } from "@sinclair/typebox"; - -export enum Permission { - Owner = "OWNER", - Admin = "ADMIN", -} - -export const permissionsSchema = Type.Union([ - Type.Literal(Permission.Admin), - Type.Literal(Permission.Owner), -]); diff --git a/src/shared/schemas/config.ts b/src/shared/schemas/config.ts deleted file mode 100644 index 97d7c6d38..000000000 --- a/src/shared/schemas/config.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { Configuration } from "@prisma/client"; -import type { Chain } from "thirdweb"; -import type { WalletType } from "./wallet"; - -export type AwsWalletConfiguration = { - awsAccessKeyId: string; - awsSecretAccessKey: string; - - defaultAwsRegion: string; -}; - -export type GcpWalletConfiguration = { - gcpApplicationCredentialEmail: string; - gcpApplicationCredentialPrivateKey: string; - - // these values are used as default so users don't need to specify them every time to the create wallet endpoint - // for fetching a wallet, always trust the resource path in the wallet details - // only use these values for creating a new wallet, when the resource path is not known - defaultGcpKmsLocationId: string; - defaultGcpKmsKeyRingId: string; - defaultGcpApplicationProjectId: string; -}; - -export type CircleWalletConfiguration = { - apiKey: string; -}; - -export interface ParsedConfig - extends Omit< - Configuration, - | "awsAccessKeyId" - | "awsSecretAccessKey" - | "awsRegion" - | "gcpApplicationProjectId" - | "gcpKmsLocationId" - | "gcpKmsKeyRingId" - | "gcpApplicationCredentialEmail" - | "gcpApplicationCredentialPrivateKey" - | "contractSubscriptionsRetryDelaySeconds" - | "mtlsCertificateEncrypted" - | "mtlsPrivateKeyEncrypted" - | "walletProviderConfigs" - > { - walletConfiguration: { - aws: AwsWalletConfiguration | null; - gcp: GcpWalletConfiguration | null; - circle: CircleWalletConfiguration | null; - legacyWalletType_removeInNextBreakingChange: WalletType; - }; - contractSubscriptionsRequeryDelaySeconds: string; - chainOverridesParsed: Chain[]; - mtlsCertificate: string | null; - mtlsPrivateKey: string | null; -} diff --git a/src/shared/schemas/extension.ts b/src/shared/schemas/extension.ts deleted file mode 100644 index b911f2e61..000000000 --- a/src/shared/schemas/extension.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type ContractExtension = - | "erc20" - | "erc721" - | "erc1155" - | "marketplace-v3-direct-listings" - | "marketplace-v3-english-auctions" - | "marketplace-v3-offers" - | "roles" - | "none" - | "withdraw" - | "deploy-prebuilt" - | "deploy-published" - | "account-factory" - | "account" - | "relayer"; diff --git a/src/shared/schemas/keypair.ts b/src/shared/schemas/keypair.ts deleted file mode 100644 index 5e0a85bc3..000000000 --- a/src/shared/schemas/keypair.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Keypairs } from "@prisma/client"; -import { type Static, Type } from "@sinclair/typebox"; - -// https://github.com/auth0/node-jsonwebtoken#algorithms-supported -const _supportedAlgorithms = [ - // Symmetric algorithms are disabled to avoid storing keys in plaintext. - // "HS256", - // "HS384", - // "HS512", - "RS256", - "RS384", - "RS512", - "ES256", - "ES384", - "ES512", - "PS256", - "PS384", - "PS512", -] as const; - -export type KeypairAlgorithm = (typeof _supportedAlgorithms)[number]; - -export const KeypairAlgorithmSchema = Type.Union( - _supportedAlgorithms.map((alg) => Type.Literal(alg)), -); - -export const KeypairSchema = Type.Object({ - hash: Type.String({ - description: "A unique identifier for the keypair", - }), - publicKey: Type.String({ - description: "The public key", - }), - algorithm: Type.String({ - description: "The keypair algorithm.", - }), - label: Type.Optional( - Type.String({ - description: "A description for the keypair.", - }), - ), - createdAt: Type.Unsafe({ - type: "string", - format: "date", - description: "When the keypair was added", - }), - updatedAt: Type.Unsafe({ - type: "string", - format: "date", - description: "When the keypair was updated", - }), -}); - -export const toKeypairSchema = ( - keypair: Keypairs, -): Static => ({ - hash: keypair.hash, - publicKey: keypair.publicKey, - algorithm: keypair.algorithm, - label: keypair.label ?? undefined, - createdAt: keypair.createdAt, - updatedAt: keypair.updatedAt, -}); diff --git a/src/shared/schemas/prisma.ts b/src/shared/schemas/prisma.ts deleted file mode 100644 index 03c088379..000000000 --- a/src/shared/schemas/prisma.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Prisma, PrismaClient } from "@prisma/client"; -import type { DefaultArgs } from "@prisma/client/runtime/library"; - -export type PrismaTransaction = Omit< - PrismaClient, - "$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends" ->; diff --git a/src/shared/schemas/relayer.ts b/src/shared/schemas/relayer.ts deleted file mode 100644 index f18063704..000000000 --- a/src/shared/schemas/relayer.ts +++ /dev/null @@ -1,212 +0,0 @@ -export const ForwarderAbi = [ - { inputs: [], stateMutability: "nonpayable", type: "constructor" }, - { - inputs: [ - { - components: [ - { internalType: "address", name: "from", type: "address" }, - { internalType: "address", name: "to", type: "address" }, - { internalType: "uint256", name: "value", type: "uint256" }, - { internalType: "uint256", name: "gas", type: "uint256" }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "bytes", name: "data", type: "bytes" }, - ], - internalType: "struct MinimalForwarder.ForwardRequest", - name: "req", - type: "tuple", - }, - { internalType: "bytes", name: "signature", type: "bytes" }, - ], - name: "execute", - outputs: [ - { internalType: "bool", name: "", type: "bool" }, - { internalType: "bytes", name: "", type: "bytes" }, - ], - stateMutability: "payable", - type: "function", - }, - { - inputs: [{ internalType: "address", name: "from", type: "address" }], - name: "getNonce", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - components: [ - { internalType: "address", name: "from", type: "address" }, - { internalType: "address", name: "to", type: "address" }, - { internalType: "uint256", name: "value", type: "uint256" }, - { internalType: "uint256", name: "gas", type: "uint256" }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "bytes", name: "data", type: "bytes" }, - ], - internalType: "struct MinimalForwarder.ForwardRequest", - name: "req", - type: "tuple", - }, - { internalType: "bytes", name: "signature", type: "bytes" }, - ], - name: "verify", - outputs: [{ internalType: "bool", name: "", type: "bool" }], - stateMutability: "view", - type: "function", - }, -]; - -export const ForwarderAbiEIP712ChainlessDomain = [ - { inputs: [], stateMutability: "nonpayable", type: "constructor" }, - { - inputs: [ - { - components: [ - { internalType: "address", name: "from", type: "address" }, - { internalType: "address", name: "to", type: "address" }, - { internalType: "uint256", name: "value", type: "uint256" }, - { internalType: "uint256", name: "gas", type: "uint256" }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "bytes", name: "data", type: "bytes" }, - { internalType: "uint256", name: "chainid", type: "uint256" }, - ], - internalType: "struct ForwarderChainlessDomain.ForwardRequest", - name: "req", - type: "tuple", - }, - { internalType: "bytes", name: "signature", type: "bytes" }, - ], - name: "execute", - outputs: [ - { internalType: "bool", name: "", type: "bool" }, - { internalType: "bytes", name: "", type: "bytes" }, - ], - stateMutability: "payable", - type: "function", - }, - { - inputs: [{ internalType: "address", name: "from", type: "address" }], - name: "getNonce", - outputs: [{ internalType: "uint256", name: "", type: "uint256" }], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - components: [ - { internalType: "address", name: "from", type: "address" }, - { internalType: "address", name: "to", type: "address" }, - { internalType: "uint256", name: "value", type: "uint256" }, - { internalType: "uint256", name: "gas", type: "uint256" }, - { internalType: "uint256", name: "nonce", type: "uint256" }, - { internalType: "bytes", name: "data", type: "bytes" }, - { internalType: "uint256", name: "chainid", type: "uint256" }, - ], - internalType: "struct ForwarderChainlessDomain.ForwardRequest", - name: "req", - type: "tuple", - }, - { internalType: "bytes", name: "signature", type: "bytes" }, - ], - name: "verify", - outputs: [{ internalType: "bool", name: "", type: "bool" }], - stateMutability: "view", - type: "function", - }, -]; - -export const ERC2771ContextAbi = [ - { - inputs: [ - { - internalType: "address[]", - name: "trustedForwarder", - type: "address[]", - }, - ], - stateMutability: "nonpayable", - type: "constructor", - }, - { - inputs: [ - { - internalType: "address", - name: "forwarder", - type: "address", - }, - ], - name: "isTrustedForwarder", - outputs: [ - { - internalType: "bool", - name: "", - type: "bool", - }, - ], - stateMutability: "view", - type: "function", - }, -]; - -export const ERC20PermitAbi = [ - { - inputs: [ - { - internalType: "address", - name: "owner", - type: "address", - }, - { - internalType: "address", - name: "spender", - type: "address", - }, - { - internalType: "uint256", - name: "value", - type: "uint256", - }, - { - internalType: "uint256", - name: "deadline", - type: "uint256", - }, - { - internalType: "uint8", - name: "v", - type: "uint8", - }, - { - internalType: "bytes32", - name: "r", - type: "bytes32", - }, - { - internalType: "bytes32", - name: "s", - type: "bytes32", - }, - ], - name: "permit", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, -]; - -export const NativeMetaTransaction = [ - { - inputs: [ - { internalType: "address", name: "userAddress", type: "address" }, - { internalType: "bytes", name: "functionSignature", type: "bytes" }, - { internalType: "bytes32", name: "sigR", type: "bytes32" }, - { internalType: "bytes32", name: "sigS", type: "bytes32" }, - { internalType: "uint8", name: "sigV", type: "uint8" }, - ], - name: "executeMetaTransaction", - outputs: [{ internalType: "bytes", name: "", type: "bytes" }], - stateMutability: "payable", - type: "function", - }, -]; diff --git a/src/shared/schemas/wallet.ts b/src/shared/schemas/wallet.ts deleted file mode 100644 index 6c856e86b..000000000 --- a/src/shared/schemas/wallet.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as z from "zod"; - -export enum CircleWalletType { - circle = "circle", - - // Smart wallets - smartCircle = "smart:circle", -} - -export enum LegacyWalletType { - local = "local", - awsKms = "aws-kms", - gcpKms = "gcp-kms", - - // Smart wallets - smartAwsKms = "smart:aws-kms", - smartGcpKms = "smart:gcp-kms", - smartLocal = "smart:local", -} - -export enum WalletType { - // Legacy wallet types - local = "local", - awsKms = "aws-kms", - gcpKms = "gcp-kms", - - // Smart wallets - smartAwsKms = "smart:aws-kms", - smartGcpKms = "smart:gcp-kms", - smartLocal = "smart:local", - - // New credential based wallet types - circle = "circle", - - // Smart wallets - smartCircle = "smart:circle", -} - -export const cirlceEntitySecretZodSchema = z.string().regex(/^[0-9a-fA-F]{64}$/, { - message: "entitySecret must be a 32-byte hex string", -}); diff --git a/src/shared/schemas/webhooks.ts b/src/shared/schemas/webhooks.ts deleted file mode 100644 index 57279d378..000000000 --- a/src/shared/schemas/webhooks.ts +++ /dev/null @@ -1,19 +0,0 @@ -export enum WebhooksEventTypes { - QUEUED_TX = "queued_transaction", - SENT_TX = "sent_transaction", - MINED_TX = "mined_transaction", - ERRORED_TX = "errored_transaction", - CANCELLED_TX = "cancelled_transaction", - ALL_TX = "all_transactions", - BACKEND_WALLET_BALANCE = "backend_wallet_balance", - AUTH = "auth", - CONTRACT_SUBSCRIPTION = "contract_subscription", -} - -export type BackendWalletBalanceWebhookParams = { - walletAddress: string; - minimumBalance: string; - currentBalance: string; - chainId: number; - message: string; -}; diff --git a/src/shared/utils/account.ts b/src/shared/utils/account.ts deleted file mode 100644 index 10944fa66..000000000 --- a/src/shared/utils/account.ts +++ /dev/null @@ -1,273 +0,0 @@ -import LRUMap from "mnemonist/lru-map"; -import { getAddress, type Address, type Chain } from "thirdweb"; -import type { Account } from "thirdweb/wallets"; -import { - getWalletDetails, - isSmartBackendWallet, - type ParsedWalletDetails, -} from "../db/wallets/get-wallet-details"; -import { WalletType } from "../schemas/wallet"; -import { splitAwsKmsArn } from "../../server/utils/wallets/aws-kms-arn"; -import { getConnectedSmartWallet } from "../../server/utils/wallets/create-smart-wallet"; -import { getAwsKmsAccount } from "../../server/utils/wallets/get-aws-kms-account"; -import { getGcpKmsAccount } from "../../server/utils/wallets/get-gcp-kms-account"; -import { - encryptedJsonToAccount, - getLocalWalletAccount, -} from "../../server/utils/wallets/get-local-wallet"; -import { getSmartWalletV5 } from "./cache/get-smart-wallet-v5"; -import { getChain } from "./chain"; -import { thirdwebClient } from "./sdk"; -import { getWalletCredential } from "../db/wallet-credentials/get-wallet-credential"; -import { getCircleAccount } from "../../server/utils/wallets/circle"; -import { getConfig } from "./cache/get-config"; - -export const _accountsCache = new LRUMap(2048); - -export const getAccount = async (args: { - chainId: number; - from: Address; - accountAddress?: Address; -}): Promise => { - const { chainId, from, accountAddress } = args; - const chain = await getChain(chainId); - - if (accountAddress) return getSmartWalletV5({ chain, accountAddress, from }); - - // Get from cache. - const cacheKey = getAccountCacheKey({ chainId, from, accountAddress }); - const cached = _accountsCache.get(cacheKey); - if (cached) { - return cached; - } - - const walletDetails = await getWalletDetails({ - address: from, - }); - - const { account } = await walletDetailsToAccount({ walletDetails, chain }); - _accountsCache.set(cacheKey, account); - return account; -}; - -export const walletDetailsToAccount = async ({ - walletDetails, - chain, -}: { - walletDetails: ParsedWalletDetails; - chain: Chain; -}) => { - switch (walletDetails.type) { - case WalletType.awsKms: { - const { keyId, region } = splitAwsKmsArn(walletDetails.awsKmsArn); - - const account = await getAwsKmsAccount({ - client: thirdwebClient, - keyId, - config: { - region, - credentials: { - accessKeyId: walletDetails.awsKmsAccessKeyId, - secretAccessKey: walletDetails.awsKmsSecretAccessKey, - }, - }, - }); - - return { account }; - } - case WalletType.gcpKms: { - const account = await getGcpKmsAccount({ - client: thirdwebClient, - name: walletDetails.gcpKmsResourcePath, - clientOptions: { - credentials: { - client_email: walletDetails.gcpApplicationCredentialEmail, - private_key: walletDetails.gcpApplicationCredentialPrivateKey, - }, - }, - }); - return { account }; - } - case WalletType.local: { - const account = await getLocalWalletAccount( - getAddress(walletDetails.address), - ); - return { account }; - } - case WalletType.smartAwsKms: { - const { keyId, region } = splitAwsKmsArn(walletDetails.awsKmsArn); - - const adminAccount = await getAwsKmsAccount({ - client: thirdwebClient, - keyId, - config: { - region, - credentials: { - accessKeyId: walletDetails.awsKmsAccessKeyId, - secretAccessKey: walletDetails.awsKmsSecretAccessKey, - }, - }, - }); - - const connectedWallet = await getConnectedSmartWallet({ - adminAccount: adminAccount, - accountFactoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - chain: chain, - }); - - return { account: connectedWallet, adminAccount: adminAccount }; - } - - case WalletType.smartGcpKms: { - const adminAccount = await getGcpKmsAccount({ - client: thirdwebClient, - name: walletDetails.gcpKmsResourcePath, - clientOptions: { - credentials: { - client_email: walletDetails.gcpApplicationCredentialEmail, - private_key: walletDetails.gcpApplicationCredentialPrivateKey, - }, - }, - }); - - const connectedWallet = await getConnectedSmartWallet({ - adminAccount: adminAccount, - accountFactoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - chain: chain, - }); - - return { account: connectedWallet, adminAccount }; - } - - case WalletType.smartLocal: { - const adminAccount = await encryptedJsonToAccount( - walletDetails.encryptedJson, - ); - - const connectedWallet = await getConnectedSmartWallet({ - adminAccount: adminAccount, - accountFactoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - chain: chain, - }); - - return { account: connectedWallet, adminAccount }; - } - - case WalletType.circle: { - const { - walletConfiguration: { circle }, - } = await getConfig(); - - if (!circle) - throw new Error("No configuration found for circle wallet type"); - - const credentials = await getWalletCredential({ - id: walletDetails.credentialId, - }); - - const account = await getCircleAccount({ - apiKey: circle.apiKey, - client: thirdwebClient, - entitySecret: credentials.data.entitySecret, - walletId: walletDetails.platformIdentifiers.circleWalletId, - }); - - return { account }; - } - - case WalletType.smartCircle: { - const { - walletConfiguration: { circle }, - } = await getConfig(); - - if (!circle) - throw new Error("No configuration found for circle wallet type"); - - const credentials = await getWalletCredential({ - id: walletDetails.credentialId, - }); - - const adminAccount = await getCircleAccount({ - apiKey: circle.apiKey, - client: thirdwebClient, - entitySecret: credentials.data.entitySecret, - walletId: walletDetails.platformIdentifiers.circleWalletId, - }); - - const connectedWallet = await getConnectedSmartWallet({ - adminAccount: adminAccount, - accountFactoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - chain: chain, - }); - - return { account: connectedWallet, adminAccount }; - } - - default: - throw new Error(`Wallet type not supported: ${walletDetails.type}`); - } -}; - -export const _adminAccountsCache = new LRUMap(2048); - -/** - * Get the admin account for a smart backend wallet (cached) - * Will throw if the wallet is not a smart backend wallet - */ -export const getSmartBackendWalletAdminAccount = async ({ - chainId, - accountAddress, -}: { - chainId: number; - accountAddress: Address; -}) => { - const chain = await getChain(chainId); - - // Get from cache. - const cacheKey = getAdminAccountCacheKey({ chainId, accountAddress }); - const cached = _adminAccountsCache.get(cacheKey); - if (cached) { - return cached; - } - - const walletDetails = await getWalletDetails({ - address: accountAddress, - }); - - if (!isSmartBackendWallet(walletDetails)) { - throw new Error( - "Wallet is not a smart backend wallet and does not have an admin account", - ); - } - - const { adminAccount } = await walletDetailsToAccount({ - walletDetails, - chain, - }); - - if (!adminAccount) { - // todo: error improvement, make it easy to parse whether user error or system error - throw new Error("Unexpected error: admin account not found"); - } - - _adminAccountsCache.set(cacheKey, adminAccount); - return adminAccount; -}; - -const getAdminAccountCacheKey = (args: { - chainId: number; - accountAddress: Address; -}) => `${args.chainId}-${args.accountAddress}`; - -const getAccountCacheKey = (args: { - chainId: number; - from: Address; - accountAddress?: Address; -}) => - args.accountAddress - ? `${args.chainId}-${args.from}-${args.accountAddress}` - : `${args.chainId}-${args.from}`; diff --git a/src/shared/utils/auth.ts b/src/shared/utils/auth.ts deleted file mode 100644 index 0adec4ff7..000000000 --- a/src/shared/utils/auth.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { authenticateJWT } from "@thirdweb-dev/auth"; -import { utils } from "ethers"; -import { env } from "./env"; - -export const THIRDWEB_DASHBOARD_ISSUER = - "0x016757dDf2Ab6a998a4729A80a091308d9059E17"; - -export const handleSiwe = async ( - jwt: string, - domain: string, - issuer: string, -) => { - try { - return await authenticateJWT({ - clientOptions: { - secretKey: env.THIRDWEB_API_SECRET_KEY, - }, - // A stub implementation of a wallet that can only verify a signature. - wallet: { - type: "evm", - getAddress: async () => issuer, - verifySignature: async ( - message: string, - signature: string, - address: string, - ) => { - const messageHash = utils.hashMessage(message); - const messageHashBytes = utils.arrayify(messageHash); - const recoveredAddress = utils.recoverAddress( - messageHashBytes, - signature, - ); - return recoveredAddress === address; - }, - signMessage: async (_: string) => "", - }, - jwt, - options: { domain }, - }); - } catch { - return null; - } -}; diff --git a/src/shared/utils/block.ts b/src/shared/utils/block.ts deleted file mode 100644 index 36d6bfd0c..000000000 --- a/src/shared/utils/block.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { eth_blockNumber, getRpcClient } from "thirdweb"; -import { getChain } from "./chain"; -import { redis } from "./redis/redis"; -import { thirdwebClient } from "./sdk"; - -/** - * Returns the latest block number. Falls back to the last known block number. - * Only use if the precise block number is not required. - * - * @param chainId - * @returns bigint - The latest block number. - */ -export const getBlockNumberish = async (chainId: number): Promise => { - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - - const key = `latestBlock:${chainId}`; - try { - const blockNumber = await eth_blockNumber(rpcRequest); - // Non-blocking update to cache. - redis.set(key, blockNumber.toString()).catch((_e) => {}); - return blockNumber; - } catch (_e) { - const cached = await redis.get(key); - if (cached) { - return BigInt(cached); - } - - throw new Error("Error getting latest block number."); - } -}; diff --git a/src/shared/utils/cache/access-token.ts b/src/shared/utils/cache/access-token.ts deleted file mode 100644 index 139f16013..000000000 --- a/src/shared/utils/cache/access-token.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Tokens } from "@prisma/client"; -import LRUMap from "mnemonist/lru-map"; -import { getToken } from "../../db/tokens/get-token"; - -// Cache an access token JWT to the token object, or null if not found. -export const accessTokenCache = new LRUMap(2048); - -interface GetAccessTokenParams { - jwt: string; -} - -export const getAccessToken = async ({ - jwt, -}: GetAccessTokenParams): Promise => { - const cached = accessTokenCache.get(jwt); - if (cached) { - return cached; - } - - const accessToken = await getToken(jwt); - accessTokenCache.set(jwt, accessToken); - return accessToken; -}; diff --git a/src/shared/utils/cache/auth-wallet.ts b/src/shared/utils/cache/auth-wallet.ts deleted file mode 100644 index 0da2eb19e..000000000 --- a/src/shared/utils/cache/auth-wallet.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { LocalWallet } from "@thirdweb-dev/wallets"; -import { updateConfiguration } from "../../db/configuration/update-configuration"; -import { env } from "../env"; -import { logger } from "../logger"; -import { getConfig } from "./get-config"; - -let authWallet: LocalWallet | undefined; - -export const getAuthWallet = async (): Promise => { - if (!authWallet) { - const config = await getConfig(); - authWallet = new LocalWallet(); - - try { - // First, we try to load the wallet with the encryption password - await authWallet.import({ - encryptedJson: config.authWalletEncryptedJson, - password: env.ENCRYPTION_PASSWORD, - }); - } catch { - // If that fails, we try to load the wallet with the secret key - await authWallet.import({ - encryptedJson: config.authWalletEncryptedJson, - password: env.THIRDWEB_API_SECRET_KEY, - }); - - // And then update the auth wallet to use encryption password instead - const encryptedJson = await authWallet.export({ - strategy: "encryptedJson", - password: env.ENCRYPTION_PASSWORD, - }); - - logger({ - service: "server", - level: "info", - message: - "[Encryption] Updating authWalletEncryptedJson to use ENCRYPTION_PASSWORD", - }); - - await updateConfiguration({ - authWalletEncryptedJson: encryptedJson, - }); - } - } - - return authWallet; -}; diff --git a/src/shared/utils/cache/clear-cache.ts b/src/shared/utils/cache/clear-cache.ts deleted file mode 100644 index e70fa38be..000000000 --- a/src/shared/utils/cache/clear-cache.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { env } from "../env"; -import { accessTokenCache } from "./access-token"; -import { invalidateConfig } from "./get-config"; -import { sdkCache } from "./get-sdk"; -import { walletsCache } from "./get-wallet"; -import { webhookCache } from "./get-webhook"; -import { keypairCache } from "./keypair"; - -export const clearCache = async ( - _service: (typeof env)["LOG_SERVICES"][0], -): Promise => { - invalidateConfig(); - webhookCache.clear(); - sdkCache.clear(); - walletsCache.clear(); - accessTokenCache.clear(); - keypairCache.clear(); -}; diff --git a/src/shared/utils/cache/get-config.ts b/src/shared/utils/cache/get-config.ts deleted file mode 100644 index f88dd75c1..000000000 --- a/src/shared/utils/cache/get-config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getConfiguration } from "../../db/configuration/get-configuration"; -import type { ParsedConfig } from "../../schemas/config"; - -let _config: ParsedConfig | null = null; - -export const getConfig = async ( - retrieveFromCache = true, -): Promise => { - if (!_config || !retrieveFromCache) { - _config = await getConfiguration(); - } - - return _config; -}; - -export const invalidateConfig = () => { - _config = null; -}; diff --git a/src/shared/utils/cache/get-contract.ts b/src/shared/utils/cache/get-contract.ts deleted file mode 100644 index baa5a49e8..000000000 --- a/src/shared/utils/cache/get-contract.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { type Static, Type } from "@sinclair/typebox"; -import { StatusCodes } from "http-status-codes"; -import { createCustomError } from "../../../server/middleware/error"; -import { abiSchema } from "../../../server/schemas/contract"; -import { getSdk } from "./get-sdk"; -import type { ThirdwebSDK } from "@thirdweb-dev/sdk"; - -const abiArraySchema = Type.Array(abiSchema); - -interface GetContractParams { - chainId: number; - walletAddress?: string; - accountAddress?: string; - contractAddress: string; - abi?: Static; -} - -export const getContract = async ({ - chainId, - walletAddress, - contractAddress, - accountAddress, - abi, -}: GetContractParams) => { - let sdk: ThirdwebSDK; - - try { - sdk = await getSdk({ chainId, walletAddress, accountAddress }); - } catch (e) { - throw createCustomError( - `Could not get SDK: ${e}`, - StatusCodes.BAD_REQUEST, - "INVALID_CHAIN_OR_WALLET_TYPE_FOR_ROUTE", - ); - } - - try { - if (abi) { - return sdk.getContractFromAbi(contractAddress, abi); - } - // SDK already handles caching. - return await sdk.getContract(contractAddress); - } catch (e) { - throw createCustomError( - `Contract metadata could not be resolved: ${e}`, - StatusCodes.BAD_REQUEST, - "INVALID_CONTRACT", - ); - } -}; diff --git a/src/shared/utils/cache/get-contractv5.ts b/src/shared/utils/cache/get-contractv5.ts deleted file mode 100644 index ae9bb0994..000000000 --- a/src/shared/utils/cache/get-contractv5.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { type ThirdwebContract, getContract } from "thirdweb"; -import type { Abi } from "thirdweb/utils"; -import { thirdwebClient } from "../../utils/sdk"; -import { getChain } from "../chain"; - -interface GetContractParams { - chainId: number; - contractAddress: string; - abi?: Abi; -} - -// Using new v5 SDK -export const getContractV5 = async ({ - chainId, - contractAddress, - abi, -}: GetContractParams): Promise => { - const definedChain = await getChain(chainId); - - // get a contract - return getContract({ - // the client you have created via `createThirdwebClient()` - client: thirdwebClient, - // the contract's address - address: contractAddress, - // the chain the contract is deployed on - chain: definedChain, - abi, - }) as ThirdwebContract; // not using type inference here; -}; diff --git a/src/shared/utils/cache/get-sdk.ts b/src/shared/utils/cache/get-sdk.ts deleted file mode 100644 index 92f80472b..000000000 --- a/src/shared/utils/cache/get-sdk.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Type } from "@sinclair/typebox"; -import { ThirdwebSDK } from "@thirdweb-dev/sdk"; -import LRUMap from "mnemonist/lru-map"; -import { getChainMetadata } from "thirdweb/chains"; -import { badChainError } from "../../../server/middleware/error"; -import { getChain } from "../chain"; -import { env } from "../env"; -import { getWallet } from "./get-wallet"; - -export const sdkCache = new LRUMap(2048); - -export const networkResponseSchema = Type.Object({ - name: Type.String({ - description: "Chain name", - }), - chain: Type.String({ - description: "Chain name", - }), - rpc: Type.Array( - Type.String({ - description: "RPC URL", - }), - ), - nativeCurrency: Type.Object({ - name: Type.String({ - description: "Native currency name", - }), - symbol: Type.String({ - description: "Native currency symbol", - }), - decimals: Type.Integer({ - description: "Native currency decimals", - }), - }), - shortName: Type.String({ - description: "Chain short name", - }), - chainId: Type.Integer({ - description: "Chain ID", - }), - testnet: Type.Boolean({ - description: "Is testnet", - }), - slug: Type.String({ - description: "Chain slug", - }), -}); - -interface GetSdkParams { - chainId: number; - walletAddress?: string; - accountAddress?: string; -} - -export const getSdk = async ({ - chainId, - walletAddress, - accountAddress, -}: GetSdkParams): Promise => { - const cacheKey = walletAddress - ? accountAddress - ? `${chainId}-${walletAddress}-${accountAddress}` - : `${chainId}-${walletAddress}` - : `${chainId}`; - - const cached = sdkCache.get(cacheKey); - if (cached) { - return cached; - } - - const chainV5 = await getChain(chainId); - const chain = await getChainMetadata(chainV5); - if (!chain) { - // TODO: move this out of a utils function. - throw badChainError(chainId); - } - - let sdk: ThirdwebSDK; - if (!walletAddress) { - sdk = new ThirdwebSDK(chain, { - secretKey: env.THIRDWEB_API_SECRET_KEY, - supportedChains: [{ ...chain, rpc: [...chain.rpc] }], - rpcBatchSettings: { - sizeLimit: env.SDK_BATCH_SIZE_LIMIT, - timeLimit: env.SDK_BATCH_TIME_LIMIT, - }, - }); - } else { - const wallet = await getWallet({ - chainId, - walletAddress, - accountAddress, - }); - sdk = await ThirdwebSDK.fromWallet(wallet, chainId, { - secretKey: env.THIRDWEB_API_SECRET_KEY, - supportedChains: [{ ...chain, rpc: [...chain.rpc] }], - rpcBatchSettings: { - sizeLimit: env.SDK_BATCH_SIZE_LIMIT, - timeLimit: env.SDK_BATCH_TIME_LIMIT, - }, - }); - } - - sdkCache.set(cacheKey, sdk); - return sdk; -}; diff --git a/src/shared/utils/cache/get-smart-wallet-v5.ts b/src/shared/utils/cache/get-smart-wallet-v5.ts deleted file mode 100644 index 7ab01f275..000000000 --- a/src/shared/utils/cache/get-smart-wallet-v5.ts +++ /dev/null @@ -1,63 +0,0 @@ -import LRUMap from "mnemonist/lru-map"; -import { getContract, readContract, type Address, type Chain } from "thirdweb"; -import { smartWallet, type Account } from "thirdweb/wallets"; -import { getAccount } from "../account"; -import { thirdwebClient } from "../sdk"; - -export const smartWalletsCache = new LRUMap(2048); - -interface SmartWalletParams { - chain: Chain; - accountAddress: Address; - from: Address; - accountFactoryAddress?: Address; -} - -export const getSmartWalletV5 = async ({ - chain, - accountAddress, - from, - accountFactoryAddress, -}: SmartWalletParams) => { - const cacheKey = `${chain.id}-${accountAddress}-${from}`; - const cachedWallet = smartWalletsCache.get(cacheKey); - - if (cachedWallet) { - return cachedWallet; - } - - // Resolve Smart-Account Contract - const smartAccountContract = getContract({ - client: thirdwebClient, - chain, - address: accountAddress as Address, - }); - - // Resolve Factory Contract Address from Smart-Account Contract - if (!accountFactoryAddress) { - accountFactoryAddress = (await readContract({ - contract: smartAccountContract, - method: "function factory() view returns (address)", - params: [], - })) as Address; - } - - // EOA Account - const account = await getAccount({ - chainId: chain.id, - from, - }); - - // Smart Account using the resolved Factory Contract Address - const smartAccount = await smartWallet({ - chain, - sponsorGas: true, - factoryAddress: accountFactoryAddress, - }).connect({ - client: thirdwebClient, - personalAccount: account, - }); - - smartWalletsCache.set(cacheKey, smartAccount); - return smartAccount; -}; diff --git a/src/shared/utils/cache/get-wallet.ts b/src/shared/utils/cache/get-wallet.ts deleted file mode 100644 index bc3124b86..000000000 --- a/src/shared/utils/cache/get-wallet.ts +++ /dev/null @@ -1,193 +0,0 @@ -import type { EVMWallet } from "@thirdweb-dev/wallets"; -import { AwsKmsWallet } from "@thirdweb-dev/wallets/evm/wallets/aws-kms"; -import { GcpKmsWallet } from "@thirdweb-dev/wallets/evm/wallets/gcp-kms"; -import LRUMap from "mnemonist/lru-map"; -import { - WalletDetailsError, - getWalletDetails, - type ParsedWalletDetails, -} from "../../db/wallets/get-wallet-details"; -import type { PrismaTransaction } from "../../schemas/prisma"; -import { WalletType } from "../../schemas/wallet"; -import { createCustomError } from "../../../server/middleware/error"; -import { splitAwsKmsArn } from "../../../server/utils/wallets/aws-kms-arn"; -import { splitGcpKmsResourcePath } from "../../../server/utils/wallets/gcp-kms-resource-path"; -import { getLocalWallet } from "../../../server/utils/wallets/get-local-wallet"; -import { getSmartWallet } from "../../../server/utils/wallets/get-smart-wallet"; - -export const walletsCache = new LRUMap(2048); - -interface GetWalletParams { - pgtx?: PrismaTransaction; - chainId: number; - walletAddress: string; - accountAddress?: string; -} - -export const getWallet = async ({ - pgtx, - chainId, - walletAddress, - accountAddress, -}: GetWalletParams): Promise => { - const cacheKey = accountAddress - ? `${chainId}-${walletAddress}-${accountAddress}` - : `${chainId}-${walletAddress}`; - - const cachedWallet = walletsCache.get(cacheKey); - if (cachedWallet) { - return cachedWallet as TWallet; - } - - let walletDetails: ParsedWalletDetails; - - try { - walletDetails = await getWalletDetails({ - pgtx, - address: walletAddress, - }); - } catch (e) { - if (e instanceof WalletDetailsError) { - throw createCustomError(e.message, 400, "BAD_REQUEST"); - } - throw e; - } - - let wallet: EVMWallet; - switch (walletDetails.type) { - case WalletType.awsKms: { - const splitArn = splitAwsKmsArn(walletDetails.awsKmsArn); - - wallet = new AwsKmsWallet({ - keyId: splitArn.keyId, - region: splitArn.region, - accessKeyId: walletDetails.awsKmsAccessKeyId, - secretAccessKey: walletDetails.awsKmsSecretAccessKey, - }); - - break; - } - - case WalletType.gcpKms: { - const splitResourcePath = splitGcpKmsResourcePath( - walletDetails.gcpKmsResourcePath, - ); - - wallet = new GcpKmsWallet({ - keyId: splitResourcePath.cryptoKeyId, - keyRingId: splitResourcePath.keyRingId, - keyVersion: splitResourcePath.versionId, - locationId: splitResourcePath.locationId, - projectId: splitResourcePath.projectId, - - applicationCredentialEmail: walletDetails.gcpApplicationCredentialEmail, - applicationCredentialPrivateKey: - walletDetails.gcpApplicationCredentialPrivateKey, - }); - break; - } - - case WalletType.local: - wallet = await getLocalWallet({ chainId, walletAddress }); - break; - - case WalletType.smartAwsKms: { - if (accountAddress) - throw new Error( - "Smart backend wallet cannot be used to operate external smart account", - ); - - const splitArn = splitAwsKmsArn(walletDetails.awsKmsArn); - - const adminWallet = new AwsKmsWallet({ - keyId: splitArn.keyId, - region: splitArn.region, - accessKeyId: walletDetails.awsKmsAccessKeyId, - secretAccessKey: walletDetails.awsKmsSecretAccessKey, - }); - - const smartWallet: EVMWallet = await getSmartWallet({ - chainId, - backendWallet: adminWallet, - accountAddress: walletDetails.address, - factoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - }); - - return smartWallet as TWallet; - } - - case WalletType.smartGcpKms: { - if (accountAddress) - throw new Error( - "Smart backend wallet cannot be used to operate external smart account", - ); - - const splitResourcePath = splitGcpKmsResourcePath( - walletDetails.gcpKmsResourcePath, - ); - - const adminWallet = new GcpKmsWallet({ - keyId: splitResourcePath.cryptoKeyId, - keyRingId: splitResourcePath.keyRingId, - keyVersion: splitResourcePath.versionId, - locationId: splitResourcePath.locationId, - projectId: splitResourcePath.projectId, - - applicationCredentialEmail: walletDetails.gcpApplicationCredentialEmail, - applicationCredentialPrivateKey: - walletDetails.gcpApplicationCredentialPrivateKey, - }); - - const smartWallet: EVMWallet = await getSmartWallet({ - chainId, - backendWallet: adminWallet, - accountAddress: walletDetails.address, - factoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - }); - - return smartWallet as TWallet; - } - - case WalletType.smartLocal: { - if (accountAddress) - throw new Error( - "Smart backend wallet cannot be used to operate external smart account", - ); - - const adminWallet = await getLocalWallet({ chainId, walletAddress }); - - const smartWallet: EVMWallet = await getSmartWallet({ - chainId, - backendWallet: adminWallet, - accountAddress: walletDetails.address, - factoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - }); - - return smartWallet as TWallet; - } - - default: - throw new Error( - `Wallet with address ${walletAddress} of type ${walletDetails.type} is not supported for these routes yet`, - ); - } - - if (!accountAddress) { - // If no account is specified, use the backend wallet itself - walletsCache.set(cacheKey, wallet); - return wallet as TWallet; - } - - // Otherwise, return the account with the backend wallet as the personal wallet - const smartWallet: EVMWallet = await getSmartWallet({ - chainId, - backendWallet: wallet, - accountAddress: accountAddress, - }); - - walletsCache.set(cacheKey, smartWallet); - return smartWallet as TWallet; -}; diff --git a/src/shared/utils/cache/get-webhook.ts b/src/shared/utils/cache/get-webhook.ts deleted file mode 100644 index 51326d569..000000000 --- a/src/shared/utils/cache/get-webhook.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Webhooks } from "@prisma/client"; -import LRUMap from "mnemonist/lru-map"; -import { getAllWebhooks } from "../../db/webhooks/get-all-webhooks"; -import type { WebhooksEventTypes } from "../../schemas/webhooks"; - -export const webhookCache = new LRUMap(2048); - -export const getWebhooksByEventType = async ( - eventType: WebhooksEventTypes, - retrieveFromCache = true, -): Promise => { - const cacheKey = eventType; - - if (retrieveFromCache && webhookCache.has(cacheKey)) { - return webhookCache.get(cacheKey) as Webhooks[]; - } - - const filteredWebhooks = (await getAllWebhooks()).filter( - (webhook) => webhook.eventType === eventType, - ); - - webhookCache.set(cacheKey, filteredWebhooks); - return filteredWebhooks; -}; diff --git a/src/shared/utils/cache/keypair.ts b/src/shared/utils/cache/keypair.ts deleted file mode 100644 index 17165ed5f..000000000 --- a/src/shared/utils/cache/keypair.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { Keypairs } from "@prisma/client"; -import LRUMap from "mnemonist/lru-map"; -import { getKeypairByHash, getKeypairByPublicKey } from "../../db/keypair/get"; - -// Cache a public key to the Keypair object, or null if not found. -export const keypairCache = new LRUMap(2048); - -/** - * Get a keypair by public key or hash. - */ -export const getKeypair = async (args: { - publicKey?: string; - publicKeyHash?: string; -}): Promise => { - const { publicKey, publicKeyHash } = args; - - const key = publicKey - ? `public-key:${args.publicKey}` - : publicKeyHash - ? `public-key-hash:${args.publicKeyHash}` - : null; - - if (!key) { - throw new Error('Must provide "publicKey" or "publicKeyHash".'); - } - - const cached = keypairCache.get(key); - if (cached) { - return cached; - } - - const keypair = publicKey - ? await getKeypairByPublicKey(publicKey) - : publicKeyHash - ? await getKeypairByHash(publicKeyHash) - : null; - - keypairCache.set(key, keypair); - return keypair; -}; diff --git a/src/shared/utils/chain.ts b/src/shared/utils/chain.ts deleted file mode 100644 index c0c581dad..000000000 --- a/src/shared/utils/chain.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineChain, type Chain } from "thirdweb"; -import { getConfig } from "./cache/get-config"; - -/** - * Get the chain for thirdweb v5 SDK. Supports chain overrides. - * @param chainId - * @returns Chain - */ -export const getChain = async (chainId: number): Promise => { - const config = await getConfig(); - - for (const override of config.chainOverridesParsed) { - if (chainId === override.id) { - // we need to call defineChain to ensure that the chain is registered in CUSTOM_CHAIN_MAP - // even if we have a Chain type, we need to call defineChain to ensure that the chain is registered - return defineChain(override); - } - } - - return defineChain(chainId); -}; diff --git a/src/shared/utils/cron/clear-cache-cron.ts b/src/shared/utils/cron/clear-cache-cron.ts deleted file mode 100644 index 6fed64673..000000000 --- a/src/shared/utils/cron/clear-cache-cron.ts +++ /dev/null @@ -1,23 +0,0 @@ -import cron from "node-cron"; -import { clearCache } from "../cache/clear-cache"; -import { getConfig } from "../cache/get-config"; -import type { env } from "../env"; - -let task: cron.ScheduledTask; -export const clearCacheCron = async ( - service: (typeof env)["LOG_SERVICES"][0], -) => { - const config = await getConfig(); - - if (!config.clearCacheCronSchedule) { - return; - } - - if (task) { - task.stop(); - } - - task = cron.schedule(config.clearCacheCronSchedule, async () => { - await clearCache(service); - }); -}; diff --git a/src/shared/utils/cron/is-valid-cron.ts b/src/shared/utils/cron/is-valid-cron.ts deleted file mode 100644 index 7615fde8e..000000000 --- a/src/shared/utils/cron/is-valid-cron.ts +++ /dev/null @@ -1,78 +0,0 @@ -import cronParser from "cron-parser"; -import { StatusCodes } from "http-status-codes"; -import { createCustomError } from "../../../server/middleware/error"; - -export const isValidCron = (input: string): boolean => { - try { - cronParser.parseExpression(input); - } catch (_error) { - throw createCustomError( - "Invalid cron expression. Please check the cron expression.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const fields = input.split(" "); - - // Check if the cron expression has 6 fields - if (fields.length !== 6) { - throw createCustomError( - "Invalid cron expression. Please check the cron expression.", - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const [seconds, minutes, hours, dayOfMonth, month, dayOfWeek] = fields; - - let parsedSecondsValue: number | null = null; - if (seconds.startsWith("*/")) { - parsedSecondsValue = Number.parseInt(seconds.split("/")[1]); - } - - // Check for specific invalid patterns in seconds field - if ( - (parsedSecondsValue !== null && - (parsedSecondsValue < 10 || parsedSecondsValue > 59)) || - seconds === "*" || - seconds === "*/1" - ) { - throw createCustomError( - `Invalid cron expression. ${ - parsedSecondsValue !== null - ? "Seconds must be between 10 and 59 when using an interval." - : "Cannot run every second of every minute of every hour." - }`, - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - // Check other fields - checkCronFieldInterval(minutes, 0, 59, "Minutes"); - checkCronFieldInterval(hours, 0, 23, "Hours"); - checkCronFieldInterval(dayOfMonth, 1, 31, "Day of month"); - checkCronFieldInterval(month, 1, 12, "Month"); - checkCronFieldInterval(dayOfWeek, 0, 7, "Day of week"); - - return true; -}; - -const checkCronFieldInterval = ( - field: string, - minValue: number, - maxValue: number, - fieldName: string, -) => { - if (field.startsWith("*/")) { - const parsedValue = Number.parseInt(field.split("/")[1]); - if (parsedValue < minValue || parsedValue > maxValue) { - throw createCustomError( - `Invalid cron expression. ${fieldName} must be between ${minValue} and ${maxValue} when using an interval.`, - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - } -}; diff --git a/src/shared/utils/crypto.ts b/src/shared/utils/crypto.ts deleted file mode 100644 index a6e8c4e8a..000000000 --- a/src/shared/utils/crypto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import CryptoJS from "crypto-js"; -import crypto from "node:crypto"; -import { env } from "./env"; - -export function encrypt(data: string): string { - return CryptoJS.AES.encrypt(data, env.ENCRYPTION_PASSWORD).toString(); -} - -export function decrypt(data: string, password: string) { - return CryptoJS.AES.decrypt(data, password).toString(CryptoJS.enc.Utf8); -} - -export function isWellFormedPublicKey(key: string) { - try { - crypto.createPublicKey(key); - return true; - } catch (_e) { - return false; - } -} diff --git a/src/shared/utils/custom-auth-header.ts b/src/shared/utils/custom-auth-header.ts deleted file mode 100644 index ac5fd54f5..000000000 --- a/src/shared/utils/custom-auth-header.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { createHmac } from "node:crypto"; - -/** - * Generates an HMAC-256 secret to set in the "Authorization" header. - * - * @param webhookUrl - The URL to call. - * @param body - The request body. - * @param timestamp - The request timestamp. - * @param nonce - A unique string for this request. Should not be re-used. - * @param clientId - Your application's client id. - * @param clientSecret - Your application's client secret. - * @returns - */ -export const generateSecretHmac256 = (args: { - webhookUrl: string; - body: Record; - timestamp: Date; - nonce: string; - clientId: string; - clientSecret: string; -}): string => { - const { webhookUrl, body, timestamp, nonce, clientId, clientSecret } = args; - - // Create the body hash by hashing the payload. - const bodyHash = createHmac("sha256", clientSecret) - .update(JSON.stringify(body), "utf8") - .digest("base64"); - - // Create the signature hash by hashing the signature. - const ts = timestamp.getTime(); // timestamp expected in milliseconds - const httpMethod = "POST"; - const url = new URL(webhookUrl); - const resourcePath = url.pathname; - const host = url.hostname; - const port = url.port - ? Number.parseInt(url.port) - : url.protocol === "https:" - ? 443 - : 80; - - const signature = [ - ts, - nonce, - httpMethod, - resourcePath, - host, - port, - bodyHash, - "", // to insert a newline at the end - ].join("\n"); - - const signatureHash = createHmac("sha256", clientSecret) - .update(signature, "utf8") - .digest("base64"); - - return [ - `MAC id="${clientId}"`, - `ts="${ts}"`, - `nonce="${nonce}"`, - `bodyhash="${bodyHash}"`, - `mac="${signatureHash}"`, - ].join(","); -}; diff --git a/src/shared/utils/date.ts b/src/shared/utils/date.ts deleted file mode 100644 index d730fc121..000000000 --- a/src/shared/utils/date.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Returns the milliseconds since a given past date. - * Returns 0 if the date is in the future. - * @param from A past date - * @returns number Milliseconds since the `from` date. - */ -export const msSince = (from: Date) => { - const ms = Date.now() - from.getTime(); - return Math.max(ms, 0); -}; diff --git a/src/shared/utils/env.ts b/src/shared/utils/env.ts deleted file mode 100644 index c048630d1..000000000 --- a/src/shared/utils/env.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { createEnv } from "@t3-oss/env-core"; -import * as dotenv from "dotenv"; -import type { ZodError } from "zod"; -import { z } from "zod"; - -const path = process.env.NODE_ENV === "test" ? ".env.test" : ".env"; -dotenv.config({ path }); - -const boolEnvSchema = (defaultBool: boolean) => - z - .string() - .default(defaultBool ? "true" : "false") - .refine((s) => s === "true" || s === "false", "must be 'true' or 'false'") - .transform((s) => s === "true"); - -export const UrlSchema = z - .string() - .refine( - (value) => value.startsWith("http://") || value.startsWith("https://"), - { message: "Invalid URL" }, - ); - -export const env = createEnv({ - server: { - NODE_ENV: z - .enum(["production", "development", "test", "local"]) - .default("development"), - LOG_LEVEL: z - .enum(["fatal", "error", "warn", "info", "debug", "trace"]) - .default("info"), - LOG_SERVICES: z - .string() - .default("server,worker,cache,websocket") - .transform((s) => - z - .array(z.enum(["server", "worker", "cache", "websocket"])) - .parse(s.split(",")), - ), - ENGINE_VERSION: z.string().optional(), - ENGINE_TIER: z.string().optional(), - THIRDWEB_API_SECRET_KEY: z.string().min(1), - ADMIN_WALLET_ADDRESS: z.string().min(1), - ENCRYPTION_PASSWORD: z.string().min(1), - POSTGRES_CONNECTION_URL: z - .string() - .default( - "postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable", - ), - PORT: z.coerce.number().default(3005), - HOST: z.string().default("0.0.0.0"), - ENABLE_HTTPS: boolEnvSchema(false), - HTTPS_PASSPHRASE: z.string().default("thirdweb-engine"), - TRUST_PROXY: boolEnvSchema(false), - CLIENT_ANALYTICS_URL: z - .union([UrlSchema, z.literal("")]) - .default("https://c.thirdweb.com/event"), - SDK_BATCH_TIME_LIMIT: z.coerce.number().default(0), - SDK_BATCH_SIZE_LIMIT: z.coerce.number().default(100), - REDIS_URL: z.string(), - SEND_TRANSACTION_QUEUE_CONCURRENCY: z.coerce.number().default(200), - CONFIRM_TRANSACTION_QUEUE_CONCURRENCY: z.coerce.number().default(200), - ENGINE_MODE: z - .enum(["default", "sandbox", "server_only", "worker_only"]) - .default("default"), - GLOBAL_RATE_LIMIT_PER_MIN: z.coerce.number().default(400 * 60), - DD_TRACER_ACTIVATED: boolEnvSchema(false), - - // Prometheus - METRICS_PORT: z.coerce.number().default(4001), - METRICS_ENABLED: boolEnvSchema(true), - - /** - * Limits - */ - // Sets the max amount of memory Redis can use. - // "0" means use all available memory. - REDIS_MAXMEMORY: z.string().default("0"), - // Sets the number of recent transactions to store. Older transactions are pruned periodically. - // In testing, 100k transactions consumes ~300mb memory. - TRANSACTION_HISTORY_COUNT: z.coerce.number().default(100_000), - // Sets the number of recent completed jobs in each queue. - QUEUE_COMPLETE_HISTORY_COUNT: z.coerce.number().default(2_000), - // Sets the number of recent failed jobs in each queue. - // These limits are higher to debug failed jobs. - QUEUE_FAIL_HISTORY_COUNT: z.coerce.number().default(10_000), - // Sets the number of recent nonces to map to queue IDs. - NONCE_MAP_COUNT: z.coerce.number().default(10_000), - - ENABLE_KEYPAIR_AUTH: boolEnvSchema(false), - ENABLE_CUSTOM_HMAC_AUTH: boolEnvSchema(false), - CUSTOM_HMAC_AUTH_CLIENT_ID: z.string().optional(), - CUSTOM_HMAC_AUTH_CLIENT_SECRET: z.string().optional(), - - /** - * Experimental env vars. These may be renamed or removed in future non-major releases. - */ - // Sets how long the mine worker waits for a transaction receipt before considering the transaction dropped. Default: 30 minutes - EXPERIMENTAL__MINE_WORKER_TIMEOUT_SECONDS: z.coerce - .number() - .default(30 * 60), - // Sets the max gas price for a transaction attempt. Most RPCs reject transactions above a certain gas price. Default: 10^18 wei. - EXPERIMENTAL__MAX_GAS_PRICE_WEI: z.coerce.number().default(10 ** 18), - }, - clientPrefix: "NEVER_USED", - client: {}, - isServer: true, - runtimeEnvStrict: { - NODE_ENV: process.env.NODE_ENV, - LOG_LEVEL: process.env.LOG_LEVEL, - LOG_SERVICES: process.env.LOG_SERVICES, - ENGINE_VERSION: process.env.ENGINE_VERSION, - ENGINE_TIER: process.env.ENGINE_TIER, - THIRDWEB_API_SECRET_KEY: process.env.THIRDWEB_API_SECRET_KEY, - ADMIN_WALLET_ADDRESS: process.env.ADMIN_WALLET_ADDRESS, - ENCRYPTION_PASSWORD: process.env.ENCRYPTION_PASSWORD, - POSTGRES_CONNECTION_URL: process.env.POSTGRES_CONNECTION_URL, - PORT: process.env.PORT, - HOST: process.env.HOST, - ENABLE_HTTPS: process.env.ENABLE_HTTPS, - HTTPS_PASSPHRASE: process.env.HTTPS_PASSPHRASE, - TRUST_PROXY: process.env.TRUST_PROXY, - CLIENT_ANALYTICS_URL: process.env.CLIENT_ANALYTICS_URL, - SDK_BATCH_TIME_LIMIT: process.env.SDK_BATCH_TIME_LIMIT, - SDK_BATCH_SIZE_LIMIT: process.env.SDK_BATCH_SIZE_LIMIT, - REDIS_URL: process.env.REDIS_URL, - SEND_TRANSACTION_QUEUE_CONCURRENCY: - process.env.SEND_TRANSACTION_QUEUE_CONCURRENCY, - CONFIRM_TRANSACTION_QUEUE_CONCURRENCY: - process.env.CONFIRM_TRANSACTION_QUEUE_CONCURRENCY, - ENGINE_MODE: process.env.ENGINE_MODE, - REDIS_MAXMEMORY: process.env.REDIS_MAXMEMORY, - TRANSACTION_HISTORY_COUNT: process.env.TRANSACTION_HISTORY_COUNT, - GLOBAL_RATE_LIMIT_PER_MIN: process.env.GLOBAL_RATE_LIMIT_PER_MIN, - DD_TRACER_ACTIVATED: process.env.DD_TRACER_ACTIVATED, - QUEUE_COMPLETE_HISTORY_COUNT: process.env.QUEUE_COMPLETE_HISTORY_COUNT, - QUEUE_FAIL_HISTORY_COUNT: process.env.QUEUE_FAIL_HISTORY_COUNT, - NONCE_MAP_COUNT: process.env.NONCE_MAP_COUNT, - EXPERIMENTAL__MINE_WORKER_TIMEOUT_SECONDS: - process.env.EXPERIMENTAL__MINE_WORKER_TIMEOUT_SECONDS, - EXPERIMENTAL__MAX_GAS_PRICE_WEI: - process.env.EXPERIMENTAL__MAX_GAS_PRICE_WEI, - METRICS_PORT: process.env.METRICS_PORT, - METRICS_ENABLED: process.env.METRICS_ENABLED, - ENABLE_KEYPAIR_AUTH: process.env.ENABLE_KEYPAIR_AUTH, - ENABLE_CUSTOM_HMAC_AUTH: process.env.ENABLE_CUSTOM_HMAC_AUTH, - CUSTOM_HMAC_AUTH_CLIENT_ID: process.env.CUSTOM_HMAC_AUTH_CLIENT_ID, - CUSTOM_HMAC_AUTH_CLIENT_SECRET: process.env.CUSTOM_HMAC_AUTH_CLIENT_SECRET, - }, - onValidationError: (error: ZodError) => { - console.error( - "❌ Invalid environment variables:", - error.flatten().fieldErrors, - ); - throw new Error("Invalid environment variables"); - }, -}); diff --git a/src/shared/utils/error.ts b/src/shared/utils/error.ts deleted file mode 100644 index 51d4f8f47..000000000 --- a/src/shared/utils/error.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { ethers } from "ethers"; -import { stringify } from "thirdweb/utils"; -import { isEthersErrorCode } from "./ethers"; - -export const wrapError = (error: unknown, prefix: "RPC" | "Bundler") => - new Error(`[${prefix}] ${prettifyError(error)}`); - -export const prettifyError = (error: unknown): string => - error instanceof Error ? error.message : stringify(error); - -const _parseMessage = (error: unknown): string | null => { - return error && typeof error === "object" && "message" in error - ? (error.message as string).toLowerCase() - : null; -}; - -export const isNonceAlreadyUsedError = (error: unknown) => { - const message = _parseMessage(error); - - if (message) { - return ( - message.includes("nonce too low") || message.includes("already known") - ); - } - - return isEthersErrorCode(error, ethers.errors.NONCE_EXPIRED); -}; - -export const isReplacementGasFeeTooLow = (error: unknown) => { - const message = _parseMessage(error); - if (message) { - return ( - message.includes("replacement fee too low") || - message.includes("replacement transaction underpriced") - ); - } - return isEthersErrorCode(error, ethers.errors.REPLACEMENT_UNDERPRICED); -}; - -export const isInsufficientFundsError = (error: unknown) => { - const message = _parseMessage(error); - if (message) { - return message.includes("insufficient funds"); - } - return isEthersErrorCode(error, ethers.errors.INSUFFICIENT_FUNDS); -}; diff --git a/src/shared/utils/ethers.ts b/src/shared/utils/ethers.ts deleted file mode 100644 index a430c467a..000000000 --- a/src/shared/utils/ethers.ts +++ /dev/null @@ -1,48 +0,0 @@ -// import { EthersError } from "@ethersproject/logger"; -import { ethers } from "ethers"; - -// Copied from: https://github.com/ethers-io/ethers.js/blob/main/src.ts/utils/errors.ts#L156 -// EthersError in ethers isn't exported. -export interface EthersError extends Error { - /** - * The string error code. - */ - code: ethers.errors; - - /** - * A short message describing the error, with minimal additional - * details. - */ - shortMessage: string; - - /** - * Additional info regarding the error that may be useful. - * - * This is generally helpful mostly for human-based debugging. - */ - info?: Record; - - /** - * Any related error. - */ - error?: Error; -} - -export const ETHERS_ERROR_CODES = new Set(Object.values(ethers.errors)); - -/** - * Returns an EthersError, or null if the error is not an ethers error. - * @param error - * @returns EthersError | null - */ -export const parseEthersError = (error: unknown): EthersError | null => { - const isNonNullObject = error && typeof error === "object"; - const hasCodeProperty = isNonNullObject && "code" in error; - if (hasCodeProperty && ETHERS_ERROR_CODES.has(error.code as ethers.errors)) { - return error as EthersError; - } - return null; -}; - -export const isEthersErrorCode = (error: unknown, code: ethers.errors) => - parseEthersError(error)?.code === code; diff --git a/src/shared/utils/indexer/get-block-time.ts b/src/shared/utils/indexer/get-block-time.ts deleted file mode 100644 index 3454bb100..000000000 --- a/src/shared/utils/indexer/get-block-time.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { eth_getBlockByNumber, getRpcClient } from "thirdweb"; -import { getChain } from "../chain"; -import { thirdwebClient } from "../sdk"; - -export const getBlockTimeSeconds = async ( - chainId: number, - blocksToEstimate: number, -) => { - const chain = await getChain(chainId); - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain, - }); - - const latestBlock = await eth_getBlockByNumber(rpcRequest, { - blockTag: "latest", - includeTransactions: false, - }); - const referenceBlock = await eth_getBlockByNumber(rpcRequest, { - blockNumber: latestBlock.number - BigInt(blocksToEstimate), - includeTransactions: false, - }); - - const diffSeconds = latestBlock.timestamp - referenceBlock.timestamp; - return Number(diffSeconds) / (blocksToEstimate + 1); -}; diff --git a/src/shared/utils/logger.ts b/src/shared/utils/logger.ts deleted file mode 100644 index 5c51c4c8f..000000000 --- a/src/shared/utils/logger.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { createLogger, format, transports } from "winston"; -import { env } from "./env"; - -type LogLevels = typeof env.LOG_LEVEL; - -// Define custom log levels that strictly match the log levels in the env file -const customLevels: { - levels: { [K in LogLevels]: number }; - colors: { [K in LogLevels]: string }; -} = { - levels: { - fatal: 0, - error: 1, - warn: 2, - info: 3, - debug: 4, - trace: 5, - }, - colors: { - fatal: "red", - error: "red", - warn: "yellow", - info: "green", - debug: "blue", - trace: "gray", - }, -}; - -// Custom filter for stdout transport -const filterNonErrors = format((info) => { - if (info.level === "error" || info.level === "fatal") { - return false; // only include non-error logs - } - return info; -}); - -// Custom filter for stderr transport -const filterErrorsAndFatal = format((info) => { - if (info.level === "error" || info.level === "fatal") { - return info; // only include error and fatal logs - } - return false; -}); - -const colorizeFormat = () => { - if (env.NODE_ENV === "development") { - return format.colorize({ colors: customLevels.colors }); - } - return format.uncolorize(); -}; - -const winstonLogger = createLogger({ - levels: customLevels.levels, - level: env.LOG_LEVEL, - format: format.combine( - format.timestamp(), - format.errors({ stack: true }), - format.splat(), - colorizeFormat(), - format.printf(({ level, message, timestamp, error }) => { - if (error) { - return `[${timestamp}] ${level}: ${message} - ${(error as Error).stack}`; - } - return `[${timestamp}] ${level}: ${message}`; - }), - ), - transports: [ - // Transport for stdout (non-error logs) - new transports.Console({ - format: format.combine(filterNonErrors()), - }), - // Transport for stderr (error and fatal logs) - new transports.Console({ - format: format.combine(filterErrorsAndFatal()), - stderrLevels: ["error", "fatal"], - }), - ], -}); - -interface LoggerParams { - service: (typeof env)["LOG_SERVICES"][0]; - level: (typeof env)["LOG_LEVEL"]; - message: string; - queueId?: string | null; - error?: unknown; - data?: unknown; -} - -export const logger = ({ - service, - level, - queueId, - message, - error, - data, -}: LoggerParams) => { - if (!env.LOG_SERVICES.includes(service)) { - return; - } - - let prefix = `[${service.charAt(0).toUpperCase() + service.slice(1)}] `; - if (queueId) { - prefix += `[Transaction] [${queueId}] `; - } - - let suffix = ""; - if (data) { - suffix += ` - ${JSON.stringify(data)}`; - } - - if (error) { - winstonLogger.error(level, `${prefix}${message}${suffix}`, { error }); - } else { - winstonLogger.log(level, `${prefix}${message}${suffix}`); - } -}; diff --git a/src/shared/utils/math.ts b/src/shared/utils/math.ts deleted file mode 100644 index 5ec56723a..000000000 --- a/src/shared/utils/math.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const getPercentile = (arr: number[], percentile: number): number => { - if (arr.length === 0) { - return 0; - } - - arr.sort((a, b) => a - b); - const index = Math.floor((percentile / 100) * (arr.length - 1)); - return arr[index]; -}; - -export const BigIntMath = { - min: (a: bigint, b: bigint) => (a < b ? a : b), - max: (a: bigint, b: bigint) => (a > b ? a : b), -}; diff --git a/src/shared/utils/primitive-types.ts b/src/shared/utils/primitive-types.ts deleted file mode 100644 index 759902bc2..000000000 --- a/src/shared/utils/primitive-types.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { Address } from "thirdweb"; -import { checksumAddress } from "thirdweb/utils"; - -export const maybeBigInt = (val?: string) => (val ? BigInt(val) : undefined); -export const maybeInt = (val?: string) => - val ? Number.parseInt(val) : undefined; - -// These overloads hint TS at the response type (ex: Address if `val` is Address). -export function normalizeAddress(val: Address): Address; -export function normalizeAddress(val?: Address): Address | undefined; -export function normalizeAddress(val: string): Address; -export function normalizeAddress(val?: string): Address | undefined; -export function normalizeAddress(val: string | null): Address | undefined; -export function normalizeAddress( - val?: string | Address | null, -): Address | undefined { - return val ? (val.toLowerCase() as Address) : undefined; -} - -export function getChecksumAddress(val: Address): Address; -export function getChecksumAddress(val?: Address): Address | undefined; -export function getChecksumAddress(val: string): Address; -export function getChecksumAddress(val?: string): Address | undefined; -export function getChecksumAddress(val: string | null): Address | undefined; -export function getChecksumAddress( - val?: string | Address | null, -): Address | undefined { - return val ? checksumAddress(val) : undefined; -} - -export function maybeDate(val: number): Date; -export function maybeDate(val?: number): Date | undefined; -export function maybeDate(val?: number): Date | undefined { - return val ? new Date(val) : undefined; -} diff --git a/src/shared/utils/redis/lock.ts b/src/shared/utils/redis/lock.ts deleted file mode 100644 index 7417f34f0..000000000 --- a/src/shared/utils/redis/lock.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { redis } from "./redis"; - -// Add more locks here. -type LockType = "lock:apply-migrations"; - -/** - * Acquire a lock to prevent duplicate runs of a workflow. - * - * @param key string The lock identifier. - * @param ttlSeconds number The number of seconds before the lock is automatically released. - * @returns true if the lock was acquired. Else false. - */ -export const acquireLock = async ( - key: LockType, - ttlSeconds: number, -): Promise => { - const result = await redis.set(key, Date.now(), "EX", ttlSeconds, "NX"); - return result === "OK"; -}; - -/** - * Release a lock. - * - * @param key The lock identifier. - * @returns true if the lock was active before releasing. - */ -export const releaseLock = async (key: LockType) => { - const result = await redis.del(key); - return result > 0; -}; - -/** - * Blocking polls a lock every second until it's released. - * - * @param key The lock identifier. - */ -export const waitForLock = async (key: LockType) => { - while (await redis.get(key)) { - await new Promise((resolve) => setTimeout(resolve, 1_000)); - } -}; diff --git a/src/shared/utils/redis/redis.ts b/src/shared/utils/redis/redis.ts deleted file mode 100644 index 9821f7e4b..000000000 --- a/src/shared/utils/redis/redis.ts +++ /dev/null @@ -1,44 +0,0 @@ -import Redis from "ioredis"; -import { env } from "../env"; -import { logger } from "../logger"; - -// ioredis has issues with batches over 100k+ (source: https://github.com/redis/ioredis/issues/801). -export const MAX_REDIS_BATCH_SIZE = 50_000; - -export const redis = new Redis(env.REDIS_URL, { - enableAutoPipelining: true, - maxRetriesPerRequest: null, -}); -try { - await redis.config("SET", "maxmemory", env.REDIS_MAXMEMORY); -} catch (error) { - logger({ - level: "error", - message: `Initializing Redis: ${error}`, - service: "worker", - }); -} - -redis.on("error", (error) => () => { - logger({ - level: "error", - message: `Redis error: ${error}`, - service: "worker", - }); -}); -redis.on("ready", () => { - logger({ - level: "debug", - message: "Redis ready", - service: "worker", - }); -}); - -export const isRedisReachable = async () => { - try { - await redis.ping(); - return true; - } catch { - return false; - } -}; diff --git a/src/shared/utils/sdk.ts b/src/shared/utils/sdk.ts deleted file mode 100644 index eeccff5d6..000000000 --- a/src/shared/utils/sdk.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { sha256HexSync } from "@thirdweb-dev/crypto"; -import { createThirdwebClient } from "thirdweb"; -import type { TransactionReceipt } from "thirdweb/transaction"; -import { env } from "./env"; - -export const thirdwebClientId = sha256HexSync( - env.THIRDWEB_API_SECRET_KEY, -).slice(0, 32); - -export const thirdwebClient = createThirdwebClient({ - secretKey: env.THIRDWEB_API_SECRET_KEY, - config: { - rpc: { maxBatchSize: 50 }, - }, -}); - -/** - * Helper functions to handle v4 -> v5 SDK migration. - */ - -export const fromTransactionStatus = (status: "success" | "reverted") => - status === "success" ? 1 : 0; - -export const fromTransactionType = (type: TransactionReceipt["type"]) => { - if (type === "legacy") return 0; - if (type === "eip1559") return 1; - if (type === "eip2930") return 2; - if (type === "eip4844") return 3; - if (type === "eip7702") return 4; - throw new Error(`Unexpected transaction type ${type}`); -}; - -export const toTransactionType = (value: number) => { - if (value === 0) return "legacy"; - if (value === 1) return "eip1559"; - if (value === 2) return "eip2930"; - if (value === 3) return "eip4844"; - if (value === 4) return "eip7702"; - throw new Error(`Unexpected transaction type number ${value}`); -}; diff --git a/src/shared/utils/transaction/cancel-transaction.ts b/src/shared/utils/transaction/cancel-transaction.ts deleted file mode 100644 index 52d3f432d..000000000 --- a/src/shared/utils/transaction/cancel-transaction.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { type Address, toSerializableTransaction } from "thirdweb"; -import { getAccount } from "../account"; -import { getChain } from "../chain"; -import { getChecksumAddress } from "../primitive-types"; -import { thirdwebClient } from "../sdk"; - -interface CancellableTransaction { - chainId: number; - from: Address; - nonce: number; -} - -export const sendCancellationTransaction = async ( - transaction: CancellableTransaction, -) => { - const { chainId, from, nonce } = transaction; - - const chain = await getChain(chainId); - const populatedTransaction = await toSerializableTransaction({ - from: getChecksumAddress(from), - transaction: { - client: thirdwebClient, - chain, - to: from, - data: "0x", - value: 0n, - nonce, - }, - }); - - // Set 2x current gas to prioritize this transaction over any pending one. - // NOTE: This will not cancel a pending transaction set with higher gas. - if (populatedTransaction.gasPrice) { - populatedTransaction.gasPrice *= 2n; - } - if (populatedTransaction.maxFeePerGas) { - populatedTransaction.maxFeePerGas *= 2n; - } - if (populatedTransaction.maxFeePerGas) { - populatedTransaction.maxFeePerGas *= 2n; - } - - const account = await getAccount({ chainId, from }); - const { transactionHash } = await account.sendTransaction( - populatedTransaction, - ); - return transactionHash; -}; diff --git a/src/shared/utils/transaction/insert-transaction.ts b/src/shared/utils/transaction/insert-transaction.ts deleted file mode 100644 index 7b529b3c8..000000000 --- a/src/shared/utils/transaction/insert-transaction.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { StatusCodes } from "http-status-codes"; -import { randomUUID } from "node:crypto"; -import { TransactionDB } from "../../../shared/db/transactions/db"; -import { - getWalletDetails, - isSmartBackendWallet, - WalletDetailsError, - type ParsedWalletDetails, -} from "../../../shared/db/wallets/get-wallet-details"; -import { createCustomError } from "../../../server/middleware/error"; -import { SendTransactionQueue } from "../../../worker/queues/send-transaction-queue"; -import { getChecksumAddress } from "../primitive-types"; -import { recordMetrics } from "../prometheus"; -import { reportUsage } from "../usage"; -import { doSimulateTransaction } from "./simulate-queued-transaction"; -import type { InsertedTransaction, QueuedTransaction } from "./types"; - -interface InsertTransactionData { - insertedTransaction: InsertedTransaction; - idempotencyKey?: string; - shouldSimulate?: boolean; -} - -/** - * Enqueue a transaction to be submitted onchain. - * - * @param args - * @returns queueId - */ -export const insertTransaction = async ( - args: InsertTransactionData, -): Promise => { - const { insertedTransaction, idempotencyKey, shouldSimulate = false } = args; - - // The queueId uniquely represents an enqueued transaction. - // It's also used as the idempotency key (default = no idempotence). - let queueId: string = randomUUID(); - if (idempotencyKey) { - queueId = idempotencyKey; - if (await TransactionDB.exists(queueId)) { - // No-op. Return the existing queueId. - return queueId; - } - } - - let queuedTransaction: QueuedTransaction = { - ...insertedTransaction, - status: "queued", - queueId, - queuedAt: new Date(), - resendCount: 0, - - from: getChecksumAddress(insertedTransaction.from), - to: getChecksumAddress(insertedTransaction.to), - signerAddress: getChecksumAddress(insertedTransaction.signerAddress), - accountAddress: getChecksumAddress(insertedTransaction.accountAddress), - accountSalt: insertedTransaction.accountSalt, - target: getChecksumAddress(insertedTransaction.target), - sender: getChecksumAddress(insertedTransaction.sender), - value: insertedTransaction.value ?? 0n, - }; - - let walletDetails: ParsedWalletDetails | undefined; - - try { - walletDetails = await getWalletDetails({ - address: queuedTransaction.from, - }); - - // when using the v5 SDK with smart backend wallets, the following values are not set correctly: - // isUserOp is set to false - // account address is blank or the user provided value (this should be the SBW account address) - // from is set to the SBW account address (this should be the SBW signer address) - // these values need to be corrected so the worker can process the transaction - if (isSmartBackendWallet(walletDetails)) { - if (queuedTransaction.accountAddress) { - throw createCustomError( - "Smart backend wallets do not support interacting with other smart accounts", - StatusCodes.BAD_REQUEST, - "INVALID_SMART_BACKEND_WALLET_INTERACTION", - ); - } - - queuedTransaction = { - ...queuedTransaction, - isUserOp: true, - signerAddress: walletDetails.accountSignerAddress, - from: walletDetails.accountSignerAddress, - accountAddress: queuedTransaction.from, - target: queuedTransaction.to, - accountFactoryAddress: walletDetails.accountFactoryAddress ?? undefined, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - }; - } - } catch (e) { - if (e instanceof WalletDetailsError) { - // do nothing. The this is a smart backend wallet using a v4 endpoint - } - // if other type of error, rethrow - throw e; - } - - if (!walletDetails && queuedTransaction.accountAddress) { - try { - walletDetails = await getWalletDetails({ - address: queuedTransaction.accountAddress, - }); - - // when using v4 SDK with smart backend wallets, the following values are not set correctly: - // entrypointAddress is not set - // accountFactoryAddress is not set - if (walletDetails && isSmartBackendWallet(walletDetails)) { - queuedTransaction = { - ...queuedTransaction, - entrypointAddress: walletDetails.entrypointAddress ?? undefined, - accountFactoryAddress: - walletDetails.accountFactoryAddress ?? undefined, - }; - } - } catch (e: unknown) { - // if wallet details are not found for this either, this backend wallet does not exist at all - if (e instanceof WalletDetailsError) { - throw createCustomError( - "Account not found", - StatusCodes.BAD_REQUEST, - "ACCOUNT_NOT_FOUND", - ); - } - throw e; - } - } - - // Simulate the transaction. - if (shouldSimulate) { - const error = await doSimulateTransaction(queuedTransaction); - if (error) { - throw createCustomError( - `Simulation failed: ${error.replace(/[\r\n]+/g, " --- ")}`, - 400, - "BAD_REQUEST", - ); - } - } - - await TransactionDB.set(queuedTransaction); - await SendTransactionQueue.add({ - queueId: queuedTransaction.queueId, - resendCount: 0, - }); - reportUsage([{ action: "queue_tx", input: queuedTransaction }]); - - recordMetrics({ - event: "transaction_queued", - params: { - chainId: queuedTransaction.chainId.toString(), - walletAddress: queuedTransaction.from, - }, - }); - - return queueId; -}; diff --git a/src/shared/utils/transaction/queue-transation.ts b/src/shared/utils/transaction/queue-transation.ts deleted file mode 100644 index 35e391cb3..000000000 --- a/src/shared/utils/transaction/queue-transation.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { Static } from "@sinclair/typebox"; -import { StatusCodes } from "http-status-codes"; -import { - encode, - type Address, - type Hex, - type PreparedTransaction, -} from "thirdweb"; -import { resolvePromisedValue } from "thirdweb/utils"; -import { createCustomError } from "../../../server/middleware/error"; -import type { txOverridesWithValueSchema } from "../../../server/schemas/tx-overrides"; -import { parseTransactionOverrides } from "../../../server/utils/transaction-overrides"; -import { prettifyError } from "../error"; -import { insertTransaction } from "./insert-transaction"; -import type { InsertedTransaction } from "./types"; - -export type QueuedTransactionParams = { - transaction: PreparedTransaction; - fromAddress: Address; - toAddress: Address | undefined; - accountAddress: Address | undefined; - accountFactoryAddress: Address | undefined; - accountSalt: string | undefined; - transactionMode: "sponsored" | undefined; - txOverrides?: Static< - typeof txOverridesWithValueSchema.properties.txOverrides - >; - idempotencyKey?: string; - shouldSimulate?: boolean; - /** For display purposes only. */ - functionName?: string; - /** For display purposes only. */ - extension?: string; -}; - -/** - * Encodes a transaction to generate data, and inserts it into the transaction queue using the insertTransaction() - * - * Note: - * - functionName must be provided to populate the functionName field in the queued transaction - * - value and chain details are resolved from the transaction - */ -export async function queueTransaction(args: QueuedTransactionParams) { - const { - transaction, - fromAddress, - toAddress, - accountAddress, - accountFactoryAddress, - accountSalt, - txOverrides, - idempotencyKey, - shouldSimulate, - functionName, - extension, - transactionMode, - } = args; - - let data: Hex; - try { - data = await encode(transaction); - } catch (e) { - throw createCustomError( - prettifyError(e), - StatusCodes.BAD_REQUEST, - "BAD_REQUEST", - ); - } - - const insertedTransaction: InsertedTransaction = { - chainId: transaction.chain.id, - from: fromAddress, - to: toAddress, - data, - value: await resolvePromisedValue(transaction.value), - functionName, - extension, - transactionMode, - ...parseTransactionOverrides(txOverrides), - ...(accountAddress - ? { - isUserOp: true, - accountAddress: accountAddress, - signerAddress: fromAddress, - target: toAddress, - accountFactoryAddress, - accountSalt, - } - : { isUserOp: false }), - }; - - return insertTransaction({ - insertedTransaction, - shouldSimulate, - idempotencyKey, - }); -} diff --git a/src/shared/utils/transaction/simulate-queued-transaction.ts b/src/shared/utils/transaction/simulate-queued-transaction.ts deleted file mode 100644 index fde349950..000000000 --- a/src/shared/utils/transaction/simulate-queued-transaction.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { TransactionError } from "@thirdweb-dev/sdk"; -import { - prepareTransaction, - simulateTransaction, - type PreparedTransaction, -} from "thirdweb"; -import { isZkSyncChain, stringify } from "thirdweb/utils"; -import { smartWallet, type Account } from "thirdweb/wallets"; -import { getAccount } from "../account"; -import { getSmartWalletV5 } from "../cache/get-smart-wallet-v5"; -import { getChain } from "../chain"; -import { thirdwebClient } from "../sdk"; -import type { AnyTransaction } from "./types"; - -/** - * Simulate the queued transaction. - * @param transaction - * @returns string - The simulation error, or null if no error. - */ -export const doSimulateTransaction = async ( - transaction: AnyTransaction, -): Promise => { - const { - chainId, - to, - data, - value, - accountAddress, - accountFactoryAddress, - target, - from, - } = transaction; - - const chain = await getChain(chainId); - - let preparedTransaction: PreparedTransaction; - if (data && (to || target)) { - // Resolve data. - preparedTransaction = prepareTransaction({ - client: thirdwebClient, - chain, - to: to ?? target, - data, - value, - }); - } else { - throw new Error( - `Transaction cannot be simulated: ${stringify(transaction)}`, - ); - } - - let account: Account | undefined; - if (from && accountAddress) { - account = await getSmartWalletV5({ - from, - chain, - accountAddress, - accountFactoryAddress, - }); - } else { - const ownerAccount = await getAccount({ - chainId, - from, - }); - - if (transaction.transactionMode === "sponsored") { - if (!(await isZkSyncChain(chain))) { - throw new Error( - "Sponsored EOA transactions are only supported on zkSync chains.", - ); - } - - account = await smartWallet({ chain, sponsorGas: true }).connect({ - personalAccount: ownerAccount, - client: thirdwebClient, - }); - } - - // If no account was provided, use the owner account. - account ??= ownerAccount; - } - - try { - // Use an account to simulate the transaction to catch fund errors. - await simulateTransaction({ - transaction: preparedTransaction, - account, - }); - return null; - } catch (e: unknown) { - if (!(e instanceof TransactionError)) { - throw e; - } - // Error should be of type TransactionError in the thirdweb SDK. - return `${e.name}: ${e.message}`; - } -}; diff --git a/src/shared/utils/transaction/types.ts b/src/shared/utils/transaction/types.ts deleted file mode 100644 index 6b28b88d3..000000000 --- a/src/shared/utils/transaction/types.ts +++ /dev/null @@ -1,138 +0,0 @@ -import type { Address, Hex, toSerializableTransaction } from "thirdweb"; -import type { TransactionType } from "viem"; - -// TODO: Replace with thirdweb SDK exported type when available. -export type PopulatedTransaction = Awaited< - ReturnType ->; - -export type AnyTransaction = - | QueuedTransaction - | SentTransaction - | MinedTransaction - | CancelledTransaction - | ErroredTransaction; - -export type BatchOperation = { - to?: Address; - value: bigint; - data?: Hex; - functionName?: string; - functionArgs?: unknown[]; -}; - -// InsertedTransaction is the raw input from the caller. -export type InsertedTransaction = { - isUserOp: boolean; - chainId: number; - from: Address; - to?: Address; - value?: bigint; - - data?: Hex; - functionName?: string; - functionArgs?: unknown[]; - - // User-provided overrides. - overrides?: { - gas?: bigint; - gasPrice?: bigint; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - }; - timeoutSeconds?: number; - - // todo: transactionMode should not be specified along with isUserOp: true - // data model needs changes to make incorrect states unrepresentable - transactionMode: "sponsored" | undefined; - - // Offchain metadata - deployedContractAddress?: Address; - deployedContractType?: string; - extension?: string; - - // User Operation - signerAddress?: Address; - accountAddress?: Address; - accountSalt?: string; - accountFactoryAddress?: Address; - entrypointAddress?: Address; - batchOperations?: BatchOperation[]; - target?: Address; - sender?: Address; -}; - -// QueuedTransaction is a transaction added to the queue. No preparation has been done yet. -export type QueuedTransaction = InsertedTransaction & { - status: "queued"; - - resendCount: number; - queueId: string; - queuedAt: Date; - value: bigint; - data?: Hex; -}; - -// SentTransaction has been submitted to RPC successfully. -export type SentTransaction = (Omit & { - status: "sent"; - - sentAt: Date; - sentAtBlock: bigint; - - // Gas settings are estimated if not provided in `overrides`. - // For a MinedTransaction, these are replaced by onchain values from the receipt. - gas: bigint; - gasPrice?: bigint; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; -}) & - ( - | { isUserOp: false; nonce: number; sentTransactionHashes: Hex[] } - | { isUserOp: true; nonce: string; userOpHash: Hex } - ); - -// This type allows extending SentTransaction to support the ORed fields. -type _SentTransactionEOA = SentTransaction & { isUserOp: false }; -type _SentTransactionUserOp = SentTransaction & { isUserOp: true }; - -export type MinedTransaction = ( - | Omit<_SentTransactionEOA, "status"> - | Omit<_SentTransactionUserOp, "status"> -) & { - status: "mined"; - - transactionHash: Hex; - minedAt: Date; - minedAtBlock: bigint; - transactionType: TransactionType; - onchainStatus: "success" | "reverted"; - gasUsed: bigint; - effectiveGasPrice?: bigint; - cumulativeGasUsed?: bigint; - - // mined transactions can have an error message if they revert - errorMessage?: string; -}; - -// ErroredTransaction received an error before or while sending to RPC. -// A transaction that reverted onchain is not considered "errored". -export type ErroredTransaction = ( - | Omit - | Omit<_SentTransactionEOA, "status"> - | Omit<_SentTransactionUserOp, "status"> -) & { - status: "errored"; - - errorMessage: string; -}; - -// CancelledTransaction has been cancelled either via API or after some deadline. -export type CancelledTransaction = ( - | Omit<_SentTransactionEOA, "status"> - | Omit<_SentTransactionUserOp, "status"> -) & { - status: "cancelled"; - - cancelledAt: Date; -}; diff --git a/src/shared/utils/transaction/webhook.ts b/src/shared/utils/transaction/webhook.ts deleted file mode 100644 index 305a94c9e..000000000 --- a/src/shared/utils/transaction/webhook.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { WebhooksEventTypes } from "../../schemas/webhooks"; -import { SendWebhookQueue } from "../../../worker/queues/send-webhook-queue"; -import type { AnyTransaction } from "./types"; - -export const enqueueTransactionWebhook = async ( - transaction: AnyTransaction, -) => { - const { queueId, status } = transaction; - const type = - status === "sent" - ? WebhooksEventTypes.SENT_TX - : status === "mined" - ? WebhooksEventTypes.MINED_TX - : status === "cancelled" - ? WebhooksEventTypes.CANCELLED_TX - : status === "errored" - ? WebhooksEventTypes.ERRORED_TX - : null; - if (type) { - await SendWebhookQueue.enqueueWebhook({ type, queueId }); - } -}; diff --git a/src/shared/utils/usage.ts b/src/shared/utils/usage.ts deleted file mode 100644 index 64ec568e8..000000000 --- a/src/shared/utils/usage.ts +++ /dev/null @@ -1,144 +0,0 @@ -import type { Static } from "@sinclair/typebox"; -import type { UsageEvent } from "@thirdweb-dev/service-utils/cf-worker"; -import type { FastifyInstance } from "fastify"; -import type { Address, Hex } from "thirdweb"; -import { ADMIN_QUEUES_BASEPATH } from "../../server/middleware/admin-routes"; -import { OPENAPI_ROUTES } from "../../server/middleware/open-api"; -import type { contractParamSchema } from "../../server/schemas/shared-api-schemas"; -import type { walletWithAddressParamSchema } from "../../server/schemas/wallet"; -import { getChainIdFromChain } from "../../server/utils/chain"; -import { env } from "./env"; -import { logger } from "./logger"; -import { thirdwebClientId } from "./sdk"; - -export interface ReportUsageParams { - action: - | "queue_tx" - | "not_send_tx" - | "send_tx" - | "mine_tx" - | "cancel_tx" - | "error_tx" - | "api_request"; - input: { - chainId?: number; - from?: Address; - to?: Address; - value?: bigint; - transactionHash?: Hex; - onChainTxStatus?: number; - userOpHash?: Hex; - functionName?: string; - extension?: string; - retryCount?: number; - provider?: string; - msSinceQueue?: number; - msSinceSend?: number; - }; - error?: string; -} - -const ANALYTICS_DEFAULT_HEADERS = { - "Content-Type": "application/json", - "x-sdk-version": process.env.ENGINE_VERSION, - "x-product-name": "engine", - "x-client-id": thirdwebClientId, -} as HeadersInit; - -const SKIP_USAGE_PATHS = new Set([ - "", - "/", - "/favicon.ico", - "/system/health", - "/static", - ...OPENAPI_ROUTES, -]); - -export function withServerUsageReporting(server: FastifyInstance) { - // Skip reporting if CLIENT_ANALYTICS_URL is unset. - if (env.CLIENT_ANALYTICS_URL === "") { - return; - } - - server.addHook("onResponse", async (request, reply) => { - if ( - request.method === "OPTIONS" || - !request.routeOptions.url || - SKIP_USAGE_PATHS.has(request.routeOptions.url) || - request.routeOptions.url.startsWith(ADMIN_QUEUES_BASEPATH) - ) { - return; - } - - const requestParams = request.params as - | (Static & - Static) - | undefined; - - const chainId = requestParams?.chain - ? await getChainIdFromChain(requestParams.chain) - : undefined; - - const requestBody: UsageEvent = { - source: "engine", - action: "api_request", - clientId: thirdwebClientId, - pathname: reply.request.routeOptions.url, - chainId, - walletAddress: requestParams?.walletAddress, - contractAddress: requestParams?.contractAddress, - httpStatusCode: reply.statusCode, - msTotalDuration: Math.ceil(reply.elapsedTime), - httpMethod: request.method.toUpperCase() as UsageEvent["httpMethod"], - }; - - fetch(env.CLIENT_ANALYTICS_URL, { - method: "POST", - headers: ANALYTICS_DEFAULT_HEADERS, - body: JSON.stringify(requestBody), - }).catch(() => {}); // Catch uncaught exceptions since this fetch call is non-blocking. - }); -} - -export const reportUsage = (usageEvents: ReportUsageParams[]) => { - // Skip reporting if CLIENT_ANALYTICS_URL is unset. - if (env.CLIENT_ANALYTICS_URL === "") { - return; - } - - usageEvents.map(async ({ action, input, error }) => { - try { - const requestBody: UsageEvent = { - source: "engine", - action, - clientId: thirdwebClientId, - chainId: input.chainId, - walletAddress: input.from, - contractAddress: input.to, - transactionValue: input.value?.toString(), - transactionHash: input.transactionHash, - userOpHash: input.userOpHash, - errorCode: input.onChainTxStatus === 0 ? "EXECUTION_REVERTED" : error, - functionName: input.functionName, - extension: input.extension, - retryCount: input.retryCount, - provider: input.provider, - msSinceQueue: input.msSinceQueue, - msSinceSend: input.msSinceSend, - }; - - fetch(env.CLIENT_ANALYTICS_URL, { - method: "POST", - headers: ANALYTICS_DEFAULT_HEADERS, - body: JSON.stringify(requestBody), - }).catch(() => {}); // Catch uncaught exceptions since this fetch call is non-blocking. - } catch (e) { - logger({ - service: "worker", - level: "error", - message: "Error:", - error: e, - }); - } - }); -}; diff --git a/src/shared/utils/webhook.ts b/src/shared/utils/webhook.ts deleted file mode 100644 index 1997502e6..000000000 --- a/src/shared/utils/webhook.ts +++ /dev/null @@ -1,120 +0,0 @@ -import type { Webhooks } from "@prisma/client"; -import assert from "node:assert"; -import crypto, { randomUUID } from "node:crypto"; -import { Agent, fetch } from "undici"; -import { getConfig } from "./cache/get-config"; -import { env } from "./env"; -import { prettifyError } from "./error"; -import { generateSecretHmac256 } from "./custom-auth-header"; - -function generateSignature( - body: Record, - timestampSeconds: number, - secret: string, -): string { - const _body = JSON.stringify(body); - const payload = `${timestampSeconds}.${_body}`; - return crypto.createHmac("sha256", secret).update(payload).digest("hex"); -} - -function generateAuthorization(args: { - webhook: Webhooks; - timestamp: Date; - body: Record; -}): string { - const { webhook, timestamp, body } = args; - - if (env.ENABLE_CUSTOM_HMAC_AUTH) { - assert( - env.CUSTOM_HMAC_AUTH_CLIENT_ID, - 'Missing "CUSTOM_HMAC_AUTH_CLIENT_ID".', - ); - assert( - env.CUSTOM_HMAC_AUTH_CLIENT_SECRET, - 'Missing "CUSTOM_HMAC_AUTH_CLIENT_SECRET"', - ); - - return generateSecretHmac256({ - webhookUrl: webhook.url, - body, - timestamp, - nonce: randomUUID(), - clientId: env.CUSTOM_HMAC_AUTH_CLIENT_ID, - clientSecret: env.CUSTOM_HMAC_AUTH_CLIENT_SECRET, - }); - } - - return `Bearer ${webhook.secret}`; -} - -export function generateRequestHeaders(args: { - webhook: Webhooks; - body: Record; - timestamp: Date; -}): HeadersInit { - const { webhook, body, timestamp } = args; - - const timestampSeconds = Math.floor(timestamp.getTime() / 1000); - const signature = generateSignature(body, timestampSeconds, webhook.secret); - const authorization = generateAuthorization({ webhook, timestamp, body }); - return { - Accept: "application/json", - "Content-Type": "application/json", - Authorization: authorization, - "x-engine-signature": signature, - "x-engine-timestamp": timestampSeconds.toString(), - }; -} - -export interface WebhookResponse { - ok: boolean; - status: number; - body: string; -} - -export const sendWebhookRequest = async ( - webhook: Webhooks, - body: Record, -): Promise => { - try { - const config = await getConfig(); - - // If mTLS is enabled, provide the certificate with this request. - const dispatcher = - config.mtlsCertificate && config.mtlsPrivateKey - ? new Agent({ - connect: { - cert: config.mtlsCertificate, - key: config.mtlsPrivateKey, - // Validate the server's certificate. - rejectUnauthorized: true, - }, - }) - : undefined; - - const headers = generateRequestHeaders({ - webhook, - body, - timestamp: new Date(), - }); - - const resp = await fetch(webhook.url, { - method: "POST", - headers: headers, - body: JSON.stringify(body), - dispatcher, - }); - - return { - ok: resp.ok, - status: resp.status, - body: await resp.text(), - }; - } catch (e) { - return { - ok: false, - status: 500, - body: prettifyError(e), - }; - } -}; diff --git a/src/worker/index.ts b/src/worker/index.ts deleted file mode 100644 index dce96767f..000000000 --- a/src/worker/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { chainIndexerListener } from "./listeners/chain-indexer-listener"; -import { - newConfigurationListener, - updatedConfigurationListener, -} from "./listeners/config-listener"; -import { - newWebhooksListener, - updatedWebhooksListener, -} from "./listeners/webhook-listener"; -import { initCancelRecycledNoncesWorker } from "./tasks/cancel-recycled-nonces-worker"; -import { initMineTransactionWorker } from "./tasks/mine-transaction-worker"; -import { initNonceHealthCheckWorker } from "./tasks/nonce-health-check-worker"; -import { initNonceResyncWorker } from "./tasks/nonce-resync-worker"; -import { initProcessEventLogsWorker } from "./tasks/process-event-logs-worker"; -import { initProcessTransactionReceiptsWorker } from "./tasks/process-transaction-receipts-worker"; -import { initPruneTransactionsWorker } from "./tasks/prune-transactions-worker"; -import { initSendTransactionWorker } from "./tasks/send-transaction-worker"; -import { initSendWebhookWorker } from "./tasks/send-webhook-worker"; - -export const initWorker = async () => { - initCancelRecycledNoncesWorker(); - initProcessEventLogsWorker(); - initProcessTransactionReceiptsWorker(); - initPruneTransactionsWorker(); - initSendTransactionWorker(); - initMineTransactionWorker(); - initSendWebhookWorker(); - - initNonceHealthCheckWorker(); - - await initNonceResyncWorker(); - - // Listen for new & updated configuration data. - await newConfigurationListener(); - await updatedConfigurationListener(); - - // Listen for new & updated webhooks data. - await newWebhooksListener(); - await updatedWebhooksListener(); - - // Contract subscriptions. - await chainIndexerListener(); -}; diff --git a/src/worker/indexers/chain-indexer-registry.ts b/src/worker/indexers/chain-indexer-registry.ts deleted file mode 100644 index ed091e288..000000000 --- a/src/worker/indexers/chain-indexer-registry.ts +++ /dev/null @@ -1,78 +0,0 @@ -import cron from "node-cron"; -import { getBlockTimeSeconds } from "../../shared/utils/indexer/get-block-time"; -import { logger } from "../../shared/utils/logger"; -import { handleContractSubscriptions } from "../tasks/chain-indexer"; - -// @TODO: Move all worker logic to Bullmq to better handle multiple hosts. -export const INDEXER_REGISTRY = {} as Record; - -export const addChainIndexer = async (chainId: number) => { - if (INDEXER_REGISTRY[chainId]) { - return; - } - - // Estimate the block time in the last 100 blocks. Default to 2 second block times. - let blockTimeSeconds: number; - try { - blockTimeSeconds = await getBlockTimeSeconds(chainId, 100); - } catch (error) { - logger({ - service: "worker", - level: "error", - message: `Could not estimate block time for chain ${chainId}`, - error, - }); - blockTimeSeconds = 2; - } - const cronSchedule = createScheduleSeconds( - Math.max(Math.round(blockTimeSeconds), 1), - ); - logger({ - service: "worker", - level: "info", - message: `Indexing contracts on chain ${chainId} with schedule: ${cronSchedule}`, - }); - - let inProgress = false; - - const task = cron.schedule(cronSchedule, async () => { - if (inProgress) { - return; - } - - inProgress = true; - try { - await handleContractSubscriptions(chainId); - } catch (error) { - logger({ - service: "worker", - level: "error", - message: `Failed to index on chain ${chainId}`, - error, - }); - } finally { - inProgress = false; - } - }); - - INDEXER_REGISTRY[chainId] = task; -}; - -export const removeChainIndexer = async (chainId: number) => { - const task = INDEXER_REGISTRY[chainId]; - if (!task) { - return; - } - - logger({ - service: "worker", - level: "info", - message: `Removing chain indexer for chainId: ${chainId}`, - }); - - task.stop(); - delete INDEXER_REGISTRY[chainId]; -}; - -export const createScheduleSeconds = (seconds: number) => - `*/${seconds} * * * * *`; diff --git a/src/worker/listeners/chain-indexer-listener.ts b/src/worker/listeners/chain-indexer-listener.ts deleted file mode 100644 index f2c05e6e0..000000000 --- a/src/worker/listeners/chain-indexer-listener.ts +++ /dev/null @@ -1,31 +0,0 @@ -import cron from "node-cron"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { logger } from "../../shared/utils/logger"; -import { manageChainIndexers } from "../tasks/manage-chain-indexers"; - -let processChainIndexerStarted = false; -let task: cron.ScheduledTask; - -export const chainIndexerListener = async (): Promise => { - const config = await getConfig(); - if (!config.indexerListenerCronSchedule) { - return; - } - if (task) { - task.stop(); - } - - task = cron.schedule(config.indexerListenerCronSchedule, async () => { - if (!processChainIndexerStarted) { - processChainIndexerStarted = true; - await manageChainIndexers(); - processChainIndexerStarted = false; - } else { - logger({ - service: "worker", - level: "warn", - message: "manageChainIndexers already running, skipping", - }); - } - }); -}; diff --git a/src/worker/listeners/config-listener.ts b/src/worker/listeners/config-listener.ts deleted file mode 100644 index bda2e9c9f..000000000 --- a/src/worker/listeners/config-listener.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { knex } from "../../shared/db/client"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { clearCacheCron } from "../../shared/utils/cron/clear-cache-cron"; -import { logger } from "../../shared/utils/logger"; -import { chainIndexerListener } from "./chain-indexer-listener"; - -export const newConfigurationListener = async (): Promise => { - logger({ - service: "worker", - level: "info", - message: "Listening for new configuration data", - }); - - // TODO: This doesn't even need to be a listener - const connection = await knex.client.acquireConnection(); - connection.query("LISTEN new_configuration_data"); - - // Whenever we receive a new transaction, process it - connection.on( - "notification", - async (_msg: { channel: string; payload: string }) => { - // Update Configs Data - await getConfig(false); - }, - ); - - connection.on("end", async () => { - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on end", - }); - }); - - connection.on("error", async (err: unknown) => { - logger({ - service: "worker", - level: "error", - message: "Database connection error", - error: err, - }); - - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on error", - error: err, - }); - }); -}; - -export const updatedConfigurationListener = async (): Promise => { - logger({ - service: "worker", - level: "info", - message: "Listening for updated configuration data", - }); - - // TODO: This doesn't even need to be a listener - const connection = await knex.client.acquireConnection(); - connection.query("LISTEN updated_configuration_data"); - - // Whenever we receive a new transaction, process it - connection.on( - "notification", - async (_msg: { channel: string; payload: string }) => { - // Update Configs Data - logger({ - service: "worker", - level: "info", - message: "Updated configuration data", - }); - await getConfig(false); - await clearCacheCron("worker"); - await chainIndexerListener(); - }, - ); - - connection.on("end", async () => { - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on end", - }); - }); - - connection.on("error", async (err: unknown) => { - logger({ - service: "worker", - level: "error", - message: "Database connection error", - error: err, - }); - - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on error", - error: err, - }); - }); -}; diff --git a/src/worker/listeners/webhook-listener.ts b/src/worker/listeners/webhook-listener.ts deleted file mode 100644 index 759182170..000000000 --- a/src/worker/listeners/webhook-listener.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { knex } from "../../shared/db/client"; -import { webhookCache } from "../../shared/utils/cache/get-webhook"; -import { logger } from "../../shared/utils/logger"; - -export const newWebhooksListener = async (): Promise => { - logger({ - service: "worker", - level: "info", - message: "Listening for new webhooks data", - }); - - // TODO: This doesn't even need to be a listener - const connection = await knex.client.acquireConnection(); - connection.query("LISTEN new_webhook_data"); - - // Whenever we receive a new transaction, process it - connection.on( - "notification", - async (_msg: { channel: string; payload: string }) => { - logger({ - service: "worker", - level: "info", - message: "Received new webhooks data", - }); - // Update Webhooks Data - webhookCache.clear(); - }, - ); - - connection.on("end", async () => { - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on end", - }); - }); - - connection.on("error", async (err: unknown) => { - logger({ - service: "worker", - level: "error", - message: "Database connection error", - error: err, - }); - - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on error", - error: err, - }); - }); -}; - -export const updatedWebhooksListener = async (): Promise => { - logger({ - service: "worker", - level: "info", - message: "Listening for updated webhooks data", - }); - - // TODO: This doesn't even need to be a listener - const connection = await knex.client.acquireConnection(); - connection.query("LISTEN updated_webhook_data"); - - // Whenever we receive a new transaction, process it - connection.on( - "notification", - async (_msg: { channel: string; payload: string }) => { - // Update Configs Data - logger({ - service: "worker", - level: "info", - message: "Received updated webhooks data", - }); - webhookCache.clear(); - }, - ); - - connection.on("end", async () => { - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on end", - }); - }); - - connection.on("error", async (err: unknown) => { - logger({ - service: "worker", - level: "error", - message: "Database connection error", - error: err, - }); - - await knex.destroy(); - knex.client.releaseConnection(connection); - - logger({ - service: "worker", - level: "info", - message: "Released database connection on error", - error: err, - }); - }); -}; diff --git a/src/worker/queues/cancel-recycled-nonces-queue.ts b/src/worker/queues/cancel-recycled-nonces-queue.ts deleted file mode 100644 index 28bc4fde9..000000000 --- a/src/worker/queues/cancel-recycled-nonces-queue.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Queue } from "bullmq"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export class CancelRecycledNoncesQueue { - static q = new Queue("cancel-recycled-nonces", { - connection: redis, - defaultJobOptions, - }); - - constructor() { - CancelRecycledNoncesQueue.q.setGlobalConcurrency(1); - } -} diff --git a/src/worker/queues/mine-transaction-queue.ts b/src/worker/queues/mine-transaction-queue.ts deleted file mode 100644 index adb62adcb..000000000 --- a/src/worker/queues/mine-transaction-queue.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Queue } from "bullmq"; -import superjson from "superjson"; -import { env } from "../../shared/utils/env"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export type MineTransactionData = { - queueId: string; -}; - -// Attempts are made every ~20 seconds. See backoffStrategy in initMineTransactionWorker(). -const NUM_ATTEMPTS = env.EXPERIMENTAL__MINE_WORKER_TIMEOUT_SECONDS / 20; - -export class MineTransactionQueue { - static q = new Queue("transactions-2-mine", { - connection: redis, - // Backoff strategy is defined on the worker (`BackeoffStrategy`) and when adding to the queue (`attempts`). - defaultJobOptions, - }); - - // There must be a worker to poll the result for every transaction hash, - // even for the same queueId. This handles if any retried transactions succeed. - static jobId = (data: MineTransactionData) => `mine.${data.queueId}`; - - static add = async (data: MineTransactionData) => { - const serialized = superjson.stringify(data); - const jobId = this.jobId(data); - await this.q.add(jobId, serialized, { - jobId, - attempts: NUM_ATTEMPTS, - backoff: { type: "custom" }, - }); - }; - - static length = async () => this.q.getWaitingCount(); -} diff --git a/src/worker/queues/nonce-health-check-queue.ts b/src/worker/queues/nonce-health-check-queue.ts deleted file mode 100644 index 80ddf5453..000000000 --- a/src/worker/queues/nonce-health-check-queue.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Queue } from "bullmq"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export class NonceHealthCheckQueue { - static q = new Queue("nonceHealthCheck", { - connection: redis, - defaultJobOptions, - }); - - constructor() { - NonceHealthCheckQueue.q.setGlobalConcurrency(1); - } -} diff --git a/src/worker/queues/nonce-resync-queue.ts b/src/worker/queues/nonce-resync-queue.ts deleted file mode 100644 index 59ca44b65..000000000 --- a/src/worker/queues/nonce-resync-queue.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Queue } from "bullmq"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export class NonceResyncQueue { - static q = new Queue("nonce-resync-cron", { - connection: redis, - defaultJobOptions, - }); - - constructor() { - NonceResyncQueue.q.setGlobalConcurrency(1); - - // The cron job is defined in `initNonceResyncWorker` - // because it requires an async call to query configuration. - } -} diff --git a/src/worker/queues/process-event-logs-queue.ts b/src/worker/queues/process-event-logs-queue.ts deleted file mode 100644 index 2b9373717..000000000 --- a/src/worker/queues/process-event-logs-queue.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Queue } from "bullmq"; -import SuperJSON from "superjson"; -import type { Address } from "thirdweb"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -// Each job handles a block range for a given chain, filtered by addresses + events. -export type EnqueueProcessEventLogsData = { - chainId: number; - filters: { - address: Address; - events: string[]; - }[]; - fromBlock: number; // inclusive - toBlock: number; // inclusive -}; - -export class ProcessEventsLogQueue { - static q = new Queue("process-event-logs", { - connection: redis, - defaultJobOptions, - }); - - static add = async (data: EnqueueProcessEventLogsData) => { - const serialized = SuperJSON.stringify(data); - // e.g. 8453:14423125-14423685 - const jobName = `${data.chainId}:${data.fromBlock}-${data.toBlock}`; - const { contractSubscriptionsRequeryDelaySeconds } = await getConfig(); - const requeryDelays = contractSubscriptionsRequeryDelaySeconds.split(","); - - // Enqueue one job immediately and any delayed jobs. - await this.q.add(jobName, serialized); - - // The last attempt should attempt repeatedly to handle extended RPC issues. - // This backoff attempts at intervals: - // 30s, 1m, 2m, 4m, 8m, 16m, 32m, ~1h, ~2h, ~4h - for (let i = 0; i < requeryDelays.length; i++) { - const delay = Number.parseInt(requeryDelays[i]) * 1000; - const attempts = i === requeryDelays.length - 1 ? 10 : 0; - await this.q.add(jobName, serialized, { - delay, - attempts, - backoff: { type: "exponential", delay: 30_000 }, - }); - } - }; -} diff --git a/src/worker/queues/process-transaction-receipts-queue.ts b/src/worker/queues/process-transaction-receipts-queue.ts deleted file mode 100644 index 5ddb124e1..000000000 --- a/src/worker/queues/process-transaction-receipts-queue.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Queue } from "bullmq"; -import superjson from "superjson"; -import type { Address } from "thirdweb"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -// Each job handles a block range for a given chain, filtered by addresses + events. -export type EnqueueProcessTransactionReceiptsData = { - chainId: number; - filters: { - address: Address; - functions: string[]; - }[]; - fromBlock: number; // inclusive - toBlock: number; // inclusive -}; - -export class ProcessTransactionReceiptsQueue { - static q = new Queue("process-transaction-receipts", { - connection: redis, - defaultJobOptions, - }); - - static add = async (data: EnqueueProcessTransactionReceiptsData) => { - const serialized = superjson.stringify(data); - // e.g. 8453:14423125-14423685 - const jobName = `${data.chainId}:${data.fromBlock}-${data.toBlock}`; - const { contractSubscriptionsRequeryDelaySeconds } = await getConfig(); - const requeryDelays = contractSubscriptionsRequeryDelaySeconds.split(","); - - // Enqueue one job immediately and any delayed jobs. - await this.q.add(jobName, serialized); - - // The last attempt should attempt repeatedly to handle extended RPC issues. - // This backoff attempts at intervals: - // 30s, 1m, 2m, 4m, 8m, 16m, 32m, ~1h, ~2h, ~4h - for (let i = 0; i < requeryDelays.length; i++) { - const delay = Number.parseInt(requeryDelays[i]) * 1000; - const attempts = i === requeryDelays.length - 1 ? 10 : 0; - await this.q.add(jobName, serialized, { - delay, - attempts, - backoff: { type: "exponential", delay: 30_000 }, - }); - } - }; -} diff --git a/src/worker/queues/prune-transactions-queue.ts b/src/worker/queues/prune-transactions-queue.ts deleted file mode 100644 index 5786346cd..000000000 --- a/src/worker/queues/prune-transactions-queue.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Queue } from "bullmq"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export class PruneTransactionsQueue { - static q = new Queue("prune-transactions", { - connection: redis, - defaultJobOptions, - }); - - constructor() { - PruneTransactionsQueue.q.setGlobalConcurrency(1); - } -} diff --git a/src/worker/queues/queues.ts b/src/worker/queues/queues.ts deleted file mode 100644 index 6331d3a8d..000000000 --- a/src/worker/queues/queues.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { Job, JobsOptions, Worker } from "bullmq"; -import { env } from "../../shared/utils/env"; -import { logger } from "../../shared/utils/logger"; - -export const defaultJobOptions: JobsOptions = { - // Does not retry by default. Queues must explicitly define their own retry count and backoff behavior. - attempts: 0, - removeOnComplete: { - age: 7 * 24 * 60 * 60, - count: env.QUEUE_COMPLETE_HISTORY_COUNT, - }, - removeOnFail: { - age: 7 * 24 * 60 * 60, - count: env.QUEUE_FAIL_HISTORY_COUNT, - }, -}; - -export const logWorkerExceptions = (worker: Worker) => { - worker.on("failed", (job: Job | undefined, err: Error) => { - if (!job) { - return; - } - - job.log(`Job failed: ${err.message}`); - logger({ - level: "error", - message: `[${worker.name}] Job failed. jobId="${job.id}" data="${ - job.data - }", error="${err.message}" ${ - env.NODE_ENV === "development" ? err.stack : "" - }`, - service: "worker", - }); - }); -}; diff --git a/src/worker/queues/send-transaction-queue.ts b/src/worker/queues/send-transaction-queue.ts deleted file mode 100644 index c1d396e71..000000000 --- a/src/worker/queues/send-transaction-queue.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Queue } from "bullmq"; -import superjson from "superjson"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export type SendTransactionData = { - queueId: string; - resendCount: number; -}; - -export class SendTransactionQueue { - static q = new Queue("transactions-1-send", { - connection: redis, - defaultJobOptions: { - ...defaultJobOptions, - attempts: 5, - // Retries in: 1s, 2s, 4s, 8s, 16s - backoff: { type: "exponential", delay: 1_000 }, - }, - }); - - // Allow enqueuing the same queueId for multiple retries. - static jobId = (data: SendTransactionData) => - `${data.queueId}.${data.resendCount}`; - - static add = async (data: SendTransactionData) => { - const serialized = superjson.stringify(data); - const jobId = this.jobId(data); - await this.q.add(jobId, serialized, { jobId }); - }; - - static remove = async (data: SendTransactionData) => { - try { - await this.q.remove(this.jobId(data)); - } catch (_e) { - // Job is currently running. - } - }; - - static length = async () => this.q.getWaitingCount(); -} diff --git a/src/worker/queues/send-webhook-queue.ts b/src/worker/queues/send-webhook-queue.ts deleted file mode 100644 index 1f79bc224..000000000 --- a/src/worker/queues/send-webhook-queue.ts +++ /dev/null @@ -1,164 +0,0 @@ -import type { - ContractEventLogs, - ContractTransactionReceipts, - Webhooks, -} from "@prisma/client"; -import { Queue } from "bullmq"; -import SuperJSON from "superjson"; -import { - WebhooksEventTypes, - type BackendWalletBalanceWebhookParams, -} from "../../shared/schemas/webhooks"; -import { getWebhooksByEventType } from "../../shared/utils/cache/get-webhook"; -import { redis } from "../../shared/utils/redis/redis"; -import { defaultJobOptions } from "./queues"; - -export type EnqueueContractSubscriptionWebhookData = { - type: WebhooksEventTypes.CONTRACT_SUBSCRIPTION; - webhook: Webhooks; - eventLog?: ContractEventLogs; - transactionReceipt?: ContractTransactionReceipts; -}; - -export type EnqueueTransactionWebhookData = { - type: - | WebhooksEventTypes.SENT_TX - | WebhooksEventTypes.MINED_TX - | WebhooksEventTypes.ERRORED_TX - | WebhooksEventTypes.CANCELLED_TX; - queueId: string; -}; - -export type EnqueueLowBalanceWebhookData = { - type: WebhooksEventTypes.BACKEND_WALLET_BALANCE; - body: BackendWalletBalanceWebhookParams; -}; - -// Add other webhook event types here. -type EnqueueWebhookData = - | EnqueueContractSubscriptionWebhookData - | EnqueueTransactionWebhookData - | EnqueueLowBalanceWebhookData; - -export interface WebhookJob { - data: EnqueueWebhookData; - webhook: Webhooks; -} - -export class SendWebhookQueue { - static q = new Queue("send-webhook", { - connection: redis, - defaultJobOptions: { - ...defaultJobOptions, - attempts: 3, - backoff: { type: "exponential", delay: 5_000 }, - }, - }); - - static enqueueWebhook = async (data: EnqueueWebhookData) => { - switch (data.type) { - case WebhooksEventTypes.CONTRACT_SUBSCRIPTION: - return this._enqueueContractSubscriptionWebhook(data); - case WebhooksEventTypes.SENT_TX: - case WebhooksEventTypes.MINED_TX: - case WebhooksEventTypes.ERRORED_TX: - case WebhooksEventTypes.CANCELLED_TX: - return this._enqueueTransactionWebhook(data); - case WebhooksEventTypes.BACKEND_WALLET_BALANCE: - return this._enqueueBackendWalletBalanceWebhook(data); - } - }; - - /** - * Contract Subscriptions webhooks - */ - private static _enqueueContractSubscriptionWebhook = async ( - data: EnqueueContractSubscriptionWebhookData, - ) => { - const { type, webhook, eventLog, transactionReceipt } = data; - if (!eventLog && !transactionReceipt) { - throw 'Must provide "eventLog" or "transactionReceipt".'; - } - - if (!webhook.revokedAt && type === webhook.eventType) { - const job: WebhookJob = { data, webhook }; - const serialized = SuperJSON.stringify(job); - const idempotencyKey = this._getContractSubscriptionWebhookIdempotencyKey( - { - webhook, - eventLog, - transactionReceipt, - }, - ); - await this.q.add(`${data.type}:${webhook.id}`, serialized, { - jobId: idempotencyKey, - }); - } - }; - - /** - * Define an idempotency key that ensures a webhook URL will - * receive an event log or transaction receipt at most once. - */ - private static _getContractSubscriptionWebhookIdempotencyKey = (args: { - webhook: Webhooks; - eventLog?: ContractEventLogs; - transactionReceipt?: ContractTransactionReceipts; - }) => { - const { webhook, eventLog, transactionReceipt } = args; - - if (eventLog) { - return `${webhook.url}.${eventLog.transactionHash}.${eventLog.logIndex}`; - } - if (transactionReceipt) { - return `${webhook.url}.${transactionReceipt.transactionHash}`; - } - throw 'Must provide "eventLog" or "transactionReceipt".'; - }; - - /** - * Transaction webhooks - */ - static _enqueueTransactionWebhook = async ( - data: EnqueueTransactionWebhookData, - ) => { - const webhooks = [ - ...(await getWebhooksByEventType(WebhooksEventTypes.ALL_TX)), - ...(await getWebhooksByEventType(data.type)), - ]; - - for (const webhook of webhooks) { - const job: WebhookJob = { data, webhook }; - const serialized = SuperJSON.stringify(job); - await this.q.add(`${data.type}:${webhook.id}`, serialized, { - jobId: this._getTransactionWebhookIdempotencyKey({ - webhook, - eventType: data.type, - queueId: data.queueId, - }), - }); - } - }; - - private static _getTransactionWebhookIdempotencyKey = (args: { - webhook: Webhooks; - eventType: WebhooksEventTypes; - queueId: string; - }) => `${args.webhook.url}.${args.eventType}.${args.queueId}`; - - private static _enqueueBackendWalletBalanceWebhook = async ( - data: EnqueueLowBalanceWebhookData, - ) => { - const webhooks = await getWebhooksByEventType( - WebhooksEventTypes.BACKEND_WALLET_BALANCE, - ); - for (const webhook of webhooks) { - const job: WebhookJob = { data, webhook }; - const serialized = SuperJSON.stringify(job); - await this.q.add( - `${data.type}:${data.body.chainId}:${data.body.walletAddress}`, - serialized, - ); - } - }; -} diff --git a/src/worker/tasks/cancel-recycled-nonces-worker.ts b/src/worker/tasks/cancel-recycled-nonces-worker.ts deleted file mode 100644 index 7a3629375..000000000 --- a/src/worker/tasks/cancel-recycled-nonces-worker.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { type Job, type Processor, Worker } from "bullmq"; -import type { Address } from "thirdweb"; -import { - deleteNoncesForBackendWallets, - recycleNonce, -} from "../../shared/db/wallets/wallet-nonce"; -import { - isInsufficientFundsError, - isNonceAlreadyUsedError, -} from "../../shared/utils/error"; -import { logger } from "../../shared/utils/logger"; -import { redis } from "../../shared/utils/redis/redis"; -import { sendCancellationTransaction } from "../../shared/utils/transaction/cancel-transaction"; -import { CancelRecycledNoncesQueue } from "../queues/cancel-recycled-nonces-queue"; -import { logWorkerExceptions } from "../queues/queues"; - -// Must be explicitly called for the worker to run on this host. -export const initCancelRecycledNoncesWorker = () => { - CancelRecycledNoncesQueue.q.add("cron", "", { - repeat: { pattern: "* * * * *" }, - jobId: "cancel-recycled-nonces-cron", - }); - - const _worker = new Worker(CancelRecycledNoncesQueue.q.name, handler, { - connection: redis, - concurrency: 1, - }); - logWorkerExceptions(_worker); -}; - -/** - * Sends a cancel transaction for all recycled nonces. - */ -const handler: Processor = async (job: Job) => { - const keys = await redis.keys("nonce-recycled:*"); - - for (const key of keys) { - const { chainId, walletAddress } = fromRecycledNoncesKey(key); - - const recycledNonces = await getAndDeleteRecycledNonces(key); - job.log(`Found recycled nonces: key=${key} nonces=${recycledNonces}`); - - if (recycledNonces.length > 0) { - const success: number[] = []; - const fail: number[] = []; - const ignore: number[] = []; - for (const nonce of recycledNonces) { - try { - await sendCancellationTransaction({ - chainId, - from: walletAddress, - nonce, - }); - success.push(nonce); - } catch (error: unknown) { - if (isInsufficientFundsError(error)) { - // Wallet is out of funds. Reset the nonce state. - // After funded, the next transaction will resync the nonce. - job.log( - `Wallet ${chainId}:${walletAddress} out of funds. Resetting nonce.`, - ); - await deleteNoncesForBackendWallets([{ chainId, walletAddress }]); - } else if (isNonceAlreadyUsedError(error)) { - // Nonce is used. Don't recycle it. - ignore.push(nonce); - } else { - // Nonce is not used onchain. Recycle it. - job.log(`Recycling nonce: ${nonce}`); - await recycleNonce(chainId, walletAddress, nonce); - fail.push(nonce); - } - } - } - - const message = `Cancelling nonces for ${key}. success=${success} fail=${fail} ignored=${ignore}`; - job.log(message); - logger({ service: "worker", level: "info", message }); - } - } -}; - -const fromRecycledNoncesKey = (key: string) => { - const [_, chainId, walletAddress] = key.split(":"); - return { - chainId: Number.parseInt(chainId), - walletAddress: walletAddress as Address, - }; -}; - -const getAndDeleteRecycledNonces = async (key: string) => { - // Returns all recycled nonces for this key and deletes the key. - // Example response: - // [ - // [ null, [ '1', '2', '3', '4' ] ], - // [ null, 1 ] - // ] - const multiResult = await redis.multi().zrange(key, 0, -1).del(key).exec(); - if (!multiResult) { - throw new Error(`Error getting members of ${key}.`); - } - const [error, nonces] = multiResult[0]; - if (error) { - throw new Error(`Error getting members of ${key}: ${error}`); - } - // No need to sort here as ZRANGE returns elements in ascending order - return (nonces as string[]).map((v) => Number.parseInt(v)); -}; diff --git a/src/worker/tasks/chain-indexer.ts b/src/worker/tasks/chain-indexer.ts deleted file mode 100644 index c318aa3ef..000000000 --- a/src/worker/tasks/chain-indexer.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { - eth_blockNumber, - eth_getBlockByNumber, - getRpcClient, - type Address, -} from "thirdweb"; -import { getBlockForIndexing } from "../../shared/db/chain-indexers/get-chain-indexer"; -import { upsertChainIndexer } from "../../shared/db/chain-indexers/upsert-chain-indexer"; -import { prisma } from "../../shared/db/client"; -import { getContractSubscriptionsByChainId } from "../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { getChain } from "../../shared/utils/chain"; -import { logger } from "../../shared/utils/logger"; -import { thirdwebClient } from "../../shared/utils/sdk"; -import { ProcessEventsLogQueue } from "../queues/process-event-logs-queue"; -import { ProcessTransactionReceiptsQueue } from "../queues/process-transaction-receipts-queue"; - -// A reasonable block range that is within RPC limits. -// The minimum job time is 1 second, so this value should higher than the # blocks per second -// on any chain to allow catching up if delayed. -const MAX_BLOCK_RANGE = 500; - -export const handleContractSubscriptions = async (chainId: number) => { - const chain = await getChain(chainId); - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain, - }); - - await prisma.$transaction( - async (pgtx) => { - let fromBlock: number; - try { - fromBlock = await getBlockForIndexing({ chainId, pgtx }); - } catch { - // row is locked, return - return; - } - - // Cap the range to avoid hitting rate limits or block range limits from RPC. - const latestBlockNumber = await eth_blockNumber(rpcRequest); - const toBlock = Math.min( - Number(latestBlockNumber), - fromBlock + MAX_BLOCK_RANGE, - ); - - // No-op if fromBlock is already up-to-date. - if (fromBlock >= toBlock) { - return; - } - - // Ensure that the block data exists. - // Sometimes the RPC nodes do not yet return data for the latest block. - const block = await eth_getBlockByNumber(rpcRequest, { - blockNumber: BigInt(toBlock), - }); - if (!block) { - logger({ - service: "worker", - level: "warn", - message: `Block ${toBlock} data not available on chain ${chainId} yet.`, - }); - return; - } - - const contractSubscriptions = await getContractSubscriptionsByChainId( - chainId, - true, - ); - - // Identify contract addresses + event names to parse event logs, if any. - const eventLogFilters: { - address: Address; - events: string[]; - }[] = contractSubscriptions - .filter((c) => c.processEventLogs) - .map((c) => ({ - address: c.contractAddress as Address, - events: c.filterEvents, - })); - if (eventLogFilters.length > 0) { - await ProcessEventsLogQueue.add({ - chainId, - fromBlock, - toBlock, - filters: eventLogFilters, - }); - } - - // Identify addresses + function names to parse transaction receipts, if any. - const transactionReceiptFilters: { - address: Address; - functions: string[]; - }[] = contractSubscriptions - .filter((c) => c.processTransactionReceipts) - .map((c) => ({ - address: c.contractAddress as Address, - functions: c.filterFunctions, - })); - if (transactionReceiptFilters.length > 0) { - await ProcessTransactionReceiptsQueue.add({ - chainId, - fromBlock, - toBlock, - filters: transactionReceiptFilters, - }); - } - - // Update the latest block number. - try { - await upsertChainIndexer({ - pgtx, - chainId, - currentBlockNumber: toBlock, - }); - } catch (error) { - logger({ - service: "worker", - level: "error", - message: `Updating latest block number on chain ${chainId}`, - error, - }); - } - }, - { - timeout: 60 * 1000, - }, - ); -}; diff --git a/src/worker/tasks/manage-chain-indexers.ts b/src/worker/tasks/manage-chain-indexers.ts deleted file mode 100644 index 84724e916..000000000 --- a/src/worker/tasks/manage-chain-indexers.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { getContractSubscriptionsUniqueChainIds } from "../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { - INDEXER_REGISTRY, - addChainIndexer, - removeChainIndexer, -} from "../indexers/chain-indexer-registry"; - -export const manageChainIndexers = async () => { - const chainIdsToIndex = await getContractSubscriptionsUniqueChainIds(); - - for (const chainId of chainIdsToIndex) { - if (!(chainId in INDEXER_REGISTRY)) { - await addChainIndexer(chainId); - } - } - - for (const chainId in INDEXER_REGISTRY) { - const chainIdNum = Number.parseInt(chainId); - if (!chainIdsToIndex.includes(chainIdNum)) { - await removeChainIndexer(chainIdNum); - } - } -}; diff --git a/src/worker/tasks/mine-transaction-worker.ts b/src/worker/tasks/mine-transaction-worker.ts deleted file mode 100644 index 69d8b0184..000000000 --- a/src/worker/tasks/mine-transaction-worker.ts +++ /dev/null @@ -1,366 +0,0 @@ -import { Worker, type Job, type Processor } from "bullmq"; -import assert from "node:assert"; -import superjson from "superjson"; -import { - eth_getBalance, - getAddress, - getRpcClient, - toTokens, - type Address, -} from "thirdweb"; -import { stringify } from "thirdweb/utils"; -import { getUserOpReceipt } from "thirdweb/wallets/smart"; -import { TransactionDB } from "../../shared/db/transactions/db"; -import { - recycleNonce, - removeSentNonce, -} from "../../shared/db/wallets/wallet-nonce"; -import { - getReceiptForEOATransaction, - getReceiptForUserOp, -} from "../../shared/lib/transaction/get-transaction-receipt"; -import { WebhooksEventTypes } from "../../shared/schemas/webhooks"; -import { getBlockNumberish } from "../../shared/utils/block"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { getWebhooksByEventType } from "../../shared/utils/cache/get-webhook"; -import { getChain } from "../../shared/utils/chain"; -import { msSince } from "../../shared/utils/date"; -import { env } from "../../shared/utils/env"; -import { prettifyError } from "../../shared/utils/error"; -import { logger } from "../../shared/utils/logger"; -import { recordMetrics } from "../../shared/utils/prometheus"; -import { redis } from "../../shared/utils/redis/redis"; -import { thirdwebClient } from "../../shared/utils/sdk"; -import type { - ErroredTransaction, - MinedTransaction, - SentTransaction, -} from "../../shared/utils/transaction/types"; -import { enqueueTransactionWebhook } from "../../shared/utils/transaction/webhook"; -import { reportUsage } from "../../shared/utils/usage"; -import { - MineTransactionQueue, - type MineTransactionData, -} from "../queues/mine-transaction-queue"; -import { SendTransactionQueue } from "../queues/send-transaction-queue"; -import { SendWebhookQueue } from "../queues/send-webhook-queue"; - -/** - * Check if the submitted transaction or userOp is mined onchain. - * - * If an EOA transaction is not mined after some time, resend it. - */ -const handler: Processor = async (job: Job) => { - const { queueId } = superjson.parse(job.data); - - // Assert valid transaction state. - const sentTransaction = await TransactionDB.get(queueId); - if (sentTransaction?.status !== "sent") { - job.log(`Invalid transaction state: ${stringify(sentTransaction)}`); - return; - } - - // MinedTransaction = the transaction or userOp was mined. - // null = the transaction or userOp is not yet mined. - let resultTransaction: MinedTransaction | null; - if (sentTransaction.isUserOp) { - resultTransaction = await _mineUserOp(job, sentTransaction); - } else { - resultTransaction = await _mineTransaction(job, sentTransaction); - } - - if (!resultTransaction) { - throw new Error("NOT_CONFIRMED_YET"); - } - - if (resultTransaction.status === "mined") { - await TransactionDB.set(resultTransaction); - await enqueueTransactionWebhook(resultTransaction); - await _notifyIfLowBalance(resultTransaction); - await _reportUsageSuccess(resultTransaction); - recordMetrics({ - event: "transaction_mined", - params: { - chainId: resultTransaction.chainId.toString(), - queuedToMinedDurationSeconds: - msSince(resultTransaction.queuedAt) / 1000, - durationSeconds: msSince(resultTransaction.sentAt) / 1000, - walletAddress: getAddress(resultTransaction.from), - }, - }); - } -}; - -const _reportUsageSuccess = async (minedTransaction: MinedTransaction) => { - const chain = await getChain(minedTransaction.chainId); - reportUsage([ - { - action: "mine_tx", - input: { - ...minedTransaction, - provider: chain.rpc, - msSinceQueue: msSince(minedTransaction.queuedAt), - msSinceSend: msSince(minedTransaction.sentAt), - }, - }, - ]); -}; - -const _reportUsageError = (erroredTransaction: ErroredTransaction) => { - reportUsage([ - { - action: "error_tx", - input: { - ...erroredTransaction, - msSinceQueue: msSince(erroredTransaction.queuedAt), - }, - error: erroredTransaction.errorMessage, - }, - ]); -}; - -const _mineTransaction = async ( - job: Job, - sentTransaction: SentTransaction, -): Promise => { - assert(!sentTransaction.isUserOp); - - const receipt = await getReceiptForEOATransaction(sentTransaction); - - if (receipt) { - job.log( - `Found receipt. transactionHash=${receipt.transactionHash} block=${receipt.blockNumber}`, - ); - - const removed = await removeSentNonce( - sentTransaction.chainId, - sentTransaction.from, - sentTransaction.nonce, - ); - logger({ - level: "debug", - message: `[mineTransactionWorker] Removed nonce ${sentTransaction.nonce} from nonce-sent set: ${removed}`, - service: "worker", - }); - - // Though the transaction is mined successfully, set an error message if the transaction failed onchain. - const errorMessage = - receipt.status === "reverted" - ? "The transaction failed onchain. See: https://portal.thirdweb.com/engine/troubleshooting" - : undefined; - - return { - ...sentTransaction, - status: "mined", - transactionHash: receipt.transactionHash, - minedAt: new Date(), - minedAtBlock: receipt.blockNumber, - transactionType: receipt.type, - onchainStatus: receipt.status, - gasUsed: receipt.gasUsed, - effectiveGasPrice: receipt.effectiveGasPrice, - cumulativeGasUsed: receipt.cumulativeGasUsed, - errorMessage, - }; - } - - // Else the transaction is not mined yet. - const elapsedSeconds = msSince(sentTransaction.sentAt) / 1000; - job.log( - `Transaction is not mined yet. Check again later. elapsed=${elapsedSeconds}s`, - ); - - // Resend the transaction if `minEllapsedBlocksBeforeRetry` blocks or 120 seconds have passed since the last send attempt. - const config = await getConfig(); - const blockNumber = await getBlockNumberish(sentTransaction.chainId); - const elapsedBlocks = blockNumber - sentTransaction.sentAtBlock; - const shouldResend = - elapsedBlocks >= config.minEllapsedBlocksBeforeRetry || - elapsedSeconds > 120; - if (shouldResend) { - job.log( - `Resending transaction after ${elapsedBlocks} blocks. blockNumber=${blockNumber} sentAtBlock=${sentTransaction.sentAtBlock}`, - ); - await SendTransactionQueue.add({ - queueId: sentTransaction.queueId, - resendCount: sentTransaction.resendCount + 1, - }); - } - - return null; -}; - -const _mineUserOp = async ( - job: Job, - sentTransaction: SentTransaction, -): Promise => { - assert(sentTransaction.isUserOp); - - const userOpReceipt = await getReceiptForUserOp(sentTransaction); - if (!userOpReceipt) { - job.log( - `UserOp is not mined yet. Check again later. userOpHash=${sentTransaction.userOpHash}`, - ); - return null; - } - const { receipt } = userOpReceipt; - - job.log( - `Found receipt. transactionHash=${receipt.transactionHash} block=${receipt.blockNumber}`, - ); - - let errorMessage: string | undefined; - - // if the userOpReceipt is not successful, try to get the parsed userOpReceipt - // we expect this to fail, but we want the error message if it does - if (!userOpReceipt.success) { - try { - const chain = await getChain(sentTransaction.chainId); - const userOpReceipt = await getUserOpReceipt({ - client: thirdwebClient, - chain, - userOpHash: sentTransaction.userOpHash, - }); - job.log(`Found userOpReceipt: ${userOpReceipt}`); - } catch (e) { - if (e instanceof Error) { - errorMessage = e.message; - job.log(`Failed to get userOpReceipt: ${e.message}`); - } else { - throw e; - } - } - } - - return { - ...sentTransaction, - status: "mined", - transactionHash: receipt.transactionHash, - minedAt: new Date(), - minedAtBlock: receipt.blockNumber, - transactionType: receipt.type, - onchainStatus: userOpReceipt.success ? "success" : "reverted", - gasUsed: receipt.gasUsed, - effectiveGasPrice: receipt.effectiveGasPrice, - gas: receipt.gasUsed, - cumulativeGasUsed: receipt.cumulativeGasUsed, - sender: userOpReceipt.sender as Address, - nonce: userOpReceipt.nonce.toString(), - errorMessage, - }; -}; - -const _notifyIfLowBalance = async (transaction: MinedTransaction) => { - const { isUserOp, chainId, from } = transaction; - if (isUserOp) { - // Skip for userOps since they may not use the wallet's gas balance. - return; - } - - try { - const webhooks = await getWebhooksByEventType( - WebhooksEventTypes.BACKEND_WALLET_BALANCE, - ); - if (webhooks.length === 0) { - // Skip if no webhooks configured. - return; - } - - // Set a key with 5min TTL if it doesn't exist. - // This effectively throttles this check once every 5min. - const throttleKey = `webhook:${WebhooksEventTypes.BACKEND_WALLET_BALANCE}:${chainId}:${from}`; - const isThrottled = - (await redis.set(throttleKey, "", "EX", 5 * 60, "NX")) === null; - if (isThrottled) { - return; - } - - // Get the current wallet balance. - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - const currentBalance = await eth_getBalance(rpcRequest, { - address: from, - }); - - const config = await getConfig(); - if (currentBalance >= BigInt(config.minWalletBalance)) { - // Skip if the balance is above the alert threshold. - return; - } - - await SendWebhookQueue.enqueueWebhook({ - type: WebhooksEventTypes.BACKEND_WALLET_BALANCE, - body: { - chainId, - walletAddress: from, - minimumBalance: config.minWalletBalance, - currentBalance: currentBalance.toString(), - message: `LowBalance: The backend wallet ${from} on chain ${chainId} has ${toTokens(currentBalance, 18)} gas remaining.`, - }, - }); - } catch (e) { - logger({ - level: "warn", - message: `[mineTransactionWorker] Error sending low balance notification: ${prettifyError(e)}`, - service: "worker", - }); - } -}; - -// Must be explicitly called for the worker to run on this host. -export const initMineTransactionWorker = () => { - const _worker = new Worker(MineTransactionQueue.q.name, handler, { - concurrency: env.CONFIRM_TRANSACTION_QUEUE_CONCURRENCY, - connection: redis, - settings: { - backoffStrategy: (attemptsMade: number) => { - // Retries at 2s, 4s, 6s, ..., 18s, 20s, 20s, 20s, ... - return Math.min(attemptsMade * 2_000, 20_000); - }, - }, - }); - - // If a transaction fails to mine after all retries, set it as errored and release the nonce. - _worker.on("failed", async (job: Job | undefined) => { - if (job && job.attemptsMade === job.opts.attempts) { - const { queueId } = superjson.parse(job.data); - - const sentTransaction = await TransactionDB.get(queueId); - if (sentTransaction?.status !== "sent") { - job.log(`Invalid transaction state: ${stringify(sentTransaction)}`); - return; - } - - const erroredTransaction: ErroredTransaction = { - ...sentTransaction, - status: "errored", - errorMessage: "Transaction timed out.", - }; - job.log(`Transaction timed out: ${stringify(erroredTransaction)}`); - - await TransactionDB.set(erroredTransaction); - await enqueueTransactionWebhook(erroredTransaction); - _reportUsageError(erroredTransaction); - - if (!sentTransaction.isUserOp) { - // Release the nonce to allow it to be reused or cancelled. - job.log( - `Recycling nonce and removing from nonce-sent: ${sentTransaction.nonce}`, - ); - await recycleNonce( - sentTransaction.chainId, - sentTransaction.from, - sentTransaction.nonce, - ); - - await removeSentNonce( - sentTransaction.chainId, - sentTransaction.from, - sentTransaction.nonce, - ); - } - } - }); -}; diff --git a/src/worker/tasks/nonce-health-check-worker.ts b/src/worker/tasks/nonce-health-check-worker.ts deleted file mode 100644 index b75adf6e7..000000000 --- a/src/worker/tasks/nonce-health-check-worker.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { Worker, type Job, type Processor } from "bullmq"; -import { getAddress, type Address } from "thirdweb"; -import { - getUsedBackendWallets, - inspectNonce, -} from "../../shared/db/wallets/wallet-nonce"; -import { getLastUsedOnchainNonce } from "../../server/routes/admin/nonces"; -import { logger } from "../../shared/utils/logger"; -import { redis } from "../../shared/utils/redis/redis"; -import { NonceHealthCheckQueue } from "../queues/nonce-health-check-queue"; -import { logWorkerExceptions } from "../queues/queues"; - -// Configuration - -// Number of consecutive periods to check -// Checking over multiple periods avoids false positives due to intermittent stale RPC responses. -const CHECK_PERIODS = 5; - -// Frequency of the worker -const RUN_FREQUENCY_SECONDS = 60; // Run every minute - -// The number of wallets to check in parallel. -const BATCH_SIZE = 500; - -// Interfaces -interface NonceState { - onchainNonce: number; - largestSentNonce: number; -} -// Initialize the worker -export const initNonceHealthCheckWorker = () => { - NonceHealthCheckQueue.q.add("cron", "", { - repeat: { pattern: `*/${RUN_FREQUENCY_SECONDS} * * * * *` }, - jobId: "nonce-health-check-cron", - }); - - const _worker = new Worker(NonceHealthCheckQueue.q.name, handler, { - connection: redis, - concurrency: 1, - }); - logWorkerExceptions(_worker); -}; - -// Main handler function -const handler: Processor = async (_job: Job) => { - const allWallets = await getUsedBackendWallets(); - - for (let i = 0; i < allWallets.length; i += BATCH_SIZE) { - const batch = allWallets.slice(i, i + BATCH_SIZE); - - await Promise.all( - batch.map(async ({ chainId, walletAddress }) => { - const [_, isStuck, currentState] = await Promise.all([ - updateNonceHistory(walletAddress, chainId), - isQueueStuck(walletAddress, chainId), - getCurrentNonceState(walletAddress, chainId), - ]); - - logger({ - service: "worker", - level: isStuck ? "fatal" : "debug", - message: `[WALLET_HEALTH] ${walletAddress}:${chainId} isStuck:${isStuck} onchainNonce:${currentState.onchainNonce} largestSentNonce:${currentState.largestSentNonce}`, - }); - }), - ); - - await sleep(500); - } -}; - -// Check if a queue is stuck -async function isQueueStuck( - walletAddress: Address, - chainId: number, -): Promise { - const historicalStates = await getHistoricalNonceStates( - walletAddress, - chainId, - CHECK_PERIODS, - ); - - // ensure we have enough data to check - if (historicalStates.length < CHECK_PERIODS) return false; - - const oldestOnchainNonce = historicalStates.at(-1)?.onchainNonce; - - // if for every period, the onchain nonce has not changed, and the internal nonce has strictly increased - // then the queue is stuck - const isStuckForAllPeriods = historicalStates.every((state, index) => { - // check if the onchain nonce has changed, if yes, fail the check early - if (state.onchainNonce !== oldestOnchainNonce) return false; - - // if the current state is the oldest state, we don't need to check if engine nonce has increased - if (index === historicalStates.length - 1) return true; - - const previousState = historicalStates[index + 1]; - return state.largestSentNonce > previousState.largestSentNonce; - }); - - return isStuckForAllPeriods; -} - -// Get current nonce state -async function getCurrentNonceState( - walletAddress: Address, - chainId: number, -): Promise { - const [onchainNonce, largestSentNonce] = await Promise.all([ - getLastUsedOnchainNonce(chainId, walletAddress), - inspectNonce(chainId, walletAddress), - ]); - - return { - onchainNonce: onchainNonce, - largestSentNonce: largestSentNonce, - }; -} - -/** - * Stores a list of onchain vs sent nonces to check if the nonce is stuck over time. - */ -export function nonceHistoryKey(chainId: number, walletAddress: Address) { - return `nonce-history:${chainId}:${getAddress(walletAddress)}`; -} - -/** - * Get historical nonce states, ordered from newest to oldest - */ -async function getHistoricalNonceStates( - walletAddress: Address, - chainId: number, - periods: number, -): Promise { - const key = nonceHistoryKey(chainId, walletAddress); - const historicalStates = await redis.lrange(key, 0, periods - 1); - return historicalStates.map((state) => JSON.parse(state)); -} - -// Update nonce history -async function updateNonceHistory(walletAddress: Address, chainId: number) { - const currentState = await getCurrentNonceState(walletAddress, chainId); - const key = nonceHistoryKey(chainId, walletAddress); - - await redis - .multi() - .lpush(key, JSON.stringify(currentState)) - .ltrim(key, 0, CHECK_PERIODS - 1) - .exec(); -} - -const sleep = async (ms: number) => - new Promise((resolve) => setTimeout(resolve, ms, null)); diff --git a/src/worker/tasks/nonce-resync-worker.ts b/src/worker/tasks/nonce-resync-worker.ts deleted file mode 100644 index a0b8b7e4c..000000000 --- a/src/worker/tasks/nonce-resync-worker.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Worker, type Job, type Processor } from "bullmq"; -import { eth_getTransactionCount, getRpcClient } from "thirdweb"; -import { - inspectNonce, - isSentNonce, - recycleNonce, - splitSentNoncesKey, -} from "../../shared/db/wallets/wallet-nonce"; -import { getConfig } from "../../shared/utils/cache/get-config"; -import { getChain } from "../../shared/utils/chain"; -import { prettifyError } from "../../shared/utils/error"; -import { logger } from "../../shared/utils/logger"; -import { redis } from "../../shared/utils/redis/redis"; -import { thirdwebClient } from "../../shared/utils/sdk"; -import { NonceResyncQueue } from "../queues/nonce-resync-queue"; -import { logWorkerExceptions } from "../queues/queues"; - -// Must be explicitly called for the worker to run on this host. -export const initNonceResyncWorker = async () => { - const config = await getConfig(); - if (config.minedTxListenerCronSchedule) { - NonceResyncQueue.q.add("cron", "", { - repeat: { pattern: config.minedTxListenerCronSchedule }, - jobId: "nonce-resync-cron", - }); - } - - const _worker = new Worker(NonceResyncQueue.q.name, handler, { - connection: redis, - concurrency: 1, - }); - logWorkerExceptions(_worker); -}; - -/** - * Resyncs nonces for all wallets. - * This worker should be run periodically to ensure that nonces are not skipped. - * It checks the onchain nonce for each wallet and recycles any missing nonces. - * - * This is to unblock a wallet that has been stuck due to one or more skipped nonces. - */ -const handler: Processor = async (job: Job) => { - const sentNoncesKeys = await redis.keys("nonce-sent:*"); - if (sentNoncesKeys.length === 0) { - job.log("No active wallets."); - return; - } - - for (const sentNonceKey of sentNoncesKeys) { - try { - const { chainId, walletAddress } = splitSentNoncesKey(sentNonceKey); - - const rpcRequest = getRpcClient({ - client: thirdwebClient, - chain: await getChain(chainId), - }); - const lastUsedNonceOnchain = - (await eth_getTransactionCount(rpcRequest, { - address: walletAddress, - blockTag: "latest", - })) - 1; - const lastUsedNonceDb = await inspectNonce(chainId, walletAddress); - - // Recycle all nonces between (onchain nonce, db nonce] if they aren't in-flight ("sent nonce"). - const recycled: number[] = []; - for ( - let nonce = lastUsedNonceOnchain + 1; - nonce <= lastUsedNonceDb; - nonce++ - ) { - const exists = await isSentNonce(chainId, walletAddress, nonce); - if (!exists) { - await recycleNonce(chainId, walletAddress, nonce); - recycled.push(nonce); - } - } - - const message = `wallet=${chainId}:${walletAddress} lastUsedNonceOnchain=${lastUsedNonceOnchain} lastUsedNonceDb=${lastUsedNonceDb} numRecycled=${recycled.length} (min=${recycled.at(0) ?? "N/A"} max=${recycled.at(-1) ?? "N/A"})`; - job.log(message); - logger({ level: "debug", service: "worker", message }); - } catch (error) { - logger({ - level: "error", - message: `[nonceResyncWorker] ${prettifyError(error)}`, - service: "worker", - }); - } - } -}; diff --git a/src/worker/tasks/process-event-logs-worker.ts b/src/worker/tasks/process-event-logs-worker.ts deleted file mode 100644 index 95e3c9859..000000000 --- a/src/worker/tasks/process-event-logs-worker.ts +++ /dev/null @@ -1,297 +0,0 @@ -import type { Prisma, Webhooks } from "@prisma/client"; -import type { AbiEvent } from "abitype"; -import { Worker, type Job, type Processor } from "bullmq"; -import superjson from "superjson"; -import { - eth_getBlockByHash, - getContract, - getContractEvents, - getRpcClient, - prepareEvent, - type Address, - type Chain, - type Hex, - type PreparedEvent, - type ThirdwebContract, -} from "thirdweb"; -import { resolveContractAbi } from "thirdweb/contract"; -import { bulkInsertContractEventLogs } from "../../shared/db/contract-event-logs/create-contract-event-logs"; -import { getContractSubscriptionsByChainId } from "../../shared/db/contract-subscriptions/get-contract-subscriptions"; -import { WebhooksEventTypes } from "../../shared/schemas/webhooks"; -import { getChain } from "../../shared/utils/chain"; -import { logger } from "../../shared/utils/logger"; -import { normalizeAddress } from "../../shared/utils/primitive-types"; -import { redis } from "../../shared/utils/redis/redis"; -import { thirdwebClient } from "../../shared/utils/sdk"; -import { - type EnqueueProcessEventLogsData, - ProcessEventsLogQueue, -} from "../queues/process-event-logs-queue"; -import { logWorkerExceptions } from "../queues/queues"; -import { SendWebhookQueue } from "../queues/send-webhook-queue"; - -const handler: Processor = async (job: Job) => { - const { - chainId, - filters = [], - fromBlock, - toBlock, - } = superjson.parse(job.data); - - const logs = await getLogs({ - chainId, - fromBlock, - toBlock, - filters, - }); - if (logs.length === 0) { - return; - } - - // Store logs to DB. - const insertedLogs = await bulkInsertContractEventLogs({ logs }); - if (insertedLogs.length === 0) { - return; - } - job.log(`Inserted ${insertedLogs.length} events.`); - - // Enqueue webhooks. - const webhooksByContractAddress = - await getWebhooksByContractAddresses(chainId); - for (const eventLog of insertedLogs) { - const webhooks = webhooksByContractAddress[eventLog.contractAddress] ?? []; - for (const webhook of webhooks) { - await SendWebhookQueue.enqueueWebhook({ - type: WebhooksEventTypes.CONTRACT_SUBSCRIPTION, - webhook, - eventLog, - }); - } - } - - // Any logs inserted in a delayed job indicates missed logs in the realtime job. - if (job.opts.delay && job.opts.delay > 0) { - logger({ - service: "worker", - level: "warn", - message: `Found ${ - insertedLogs.length - } logs on chain: ${chainId}, block: ${insertedLogs.map( - (log) => log.blockNumber, - )} after ${job.opts.delay / 1000}s.`, - }); - } -}; - -export const getWebhooksByContractAddresses = async ( - chainId: number, -): Promise> => { - const contractSubscriptions = await getContractSubscriptionsByChainId( - chainId, - true, - ); - - // Map { contractAddress => array of webhooks } - const webhooksByContractAddress: Record = {}; - for (const { contractAddress, webhook } of contractSubscriptions) { - if (webhook) { - if (!webhooksByContractAddress[contractAddress]) { - webhooksByContractAddress[contractAddress] = []; - } - webhooksByContractAddress[contractAddress].push(webhook); - } - } - return webhooksByContractAddress; -}; - -type GetLogsParams = EnqueueProcessEventLogsData; - -/** - * Gets all event logs for the subscribed addresses and filters. - * @returns A list of logs to insert to the ContractEventLogs table. - */ -const getLogs = async ({ - chainId, - fromBlock, - toBlock, - filters, -}: GetLogsParams): Promise => { - if (filters.length === 0) { - return []; - } - - const chain = await getChain(chainId); - // Store a reference to `contract` so ABI fetches are cached. - const addressConfig: Record< - Address, - { - contract: ThirdwebContract; - } - > = {}; - for (const filter of filters) { - addressConfig[filter.address] = { - contract: getContract({ - client: thirdwebClient, - chain, - address: filter.address, - }), - }; - } - - // Get events for each contract address. Apply any filters. - const promises = filters.map(async (f) => { - const { contract } = addressConfig[f.address]; - - // Get events to filter by, if any. - // Resolve the event name, "Transfer", to event signature, "Transfer(address to, uint256 quantity)". - const events: PreparedEvent[] = []; - if (f.events.length > 0) { - const abi = await resolveContractAbi(contract); - for (const signature of abi) { - if (f.events.includes(signature.name)) { - events.push(prepareEvent({ signature })); - } - } - } - - return await getContractEvents({ - contract, - fromBlock: BigInt(fromBlock), - toBlock: BigInt(toBlock), - events, // [] means return all events - }); - }); - - // Query and flatten all events. - const allLogs = (await Promise.all(promises)).flat(); - - // Get timestamps for blocks. - const blockHashes = allLogs.map((e) => e.blockHash); - const blockTimestamps = await getBlockTimestamps(chain, blockHashes); - - // Transform logs into the DB schema. - return await Promise.all( - allLogs.map( - async (log): Promise => ({ - chainId: chainId.toString(), - blockNumber: Number(log.blockNumber), - contractAddress: normalizeAddress(log.address), - transactionHash: log.transactionHash, - topic0: log.topics[0], - topic1: log.topics[1], - topic2: log.topics[2], - topic3: log.topics[3], - data: log.data, - eventName: log.eventName, - decodedLog: await formatDecodedLog({ - contract: addressConfig[normalizeAddress(log.address)].contract, - eventName: log.eventName, - logArgs: log.args as Record, - }), - timestamp: blockTimestamps[log.blockHash], - transactionIndex: log.transactionIndex, - logIndex: log.logIndex, - }), - ), - ); -}; - -/** - * Transform v5 SDK to v4 log format. - * - * Example input: - * { - * "to": "0x123...", - * "quantity": 2n - * } - * - * Example output: - * { - * "to": { - * "type:" "address", - * "value": "0x123..." - * }, - * "quantity": { - * "type:" "uint256", - * "value": "2" - * } - * } - */ -const formatDecodedLog = async (args: { - contract: ThirdwebContract; - eventName: string; - logArgs: Record; -}): Promise | undefined> => { - const { contract, eventName, logArgs } = args; - - const abi = await resolveContractAbi(contract); - const eventSignature = abi.find((a) => a.name === eventName); - if (!eventSignature) { - return; - } - - const res: Record = {}; - for (const { name, type } of eventSignature.inputs) { - if (name && name in logArgs) { - res[name] = { - type, - value: logArgToString(logArgs[name]), - }; - } - } - return res; -}; - -/** - * Gets the timestamps for a list of block hashes. Falls back to the current time. - * @param chain - * @param blockHashes - * @returns Record - */ -const getBlockTimestamps = async ( - chain: Chain, - blockHashes: Hex[], -): Promise> => { - const now = new Date(); - const dedupe = Array.from(new Set(blockHashes)); - const rpcRequest = getRpcClient({ client: thirdwebClient, chain }); - - const blocks = await Promise.all( - dedupe.map(async (blockHash) => { - try { - const block = await eth_getBlockByHash(rpcRequest, { blockHash }); - return new Date(Number(block.timestamp) * 1000); - } catch (_e) { - return now; - } - }), - ); - - const res: Record = {}; - for (let i = 0; i < dedupe.length; i++) { - res[dedupe[i]] = blocks[i]; - } - return res; -}; - -const logArgToString = (arg: unknown): string => { - if (arg === null) { - return ""; - } - if (typeof arg === "object") { - return Object.values(arg).map(logArgToString).join(","); - } - if (Array.isArray(arg)) { - return arg.map(logArgToString).join(","); - } - return String(arg); -}; - -// Must be explicitly called for the worker to run on this host. -export const initProcessEventLogsWorker = () => { - const _worker = new Worker(ProcessEventsLogQueue.q.name, handler, { - concurrency: 5, - connection: redis, - }); - logWorkerExceptions(_worker); -}; diff --git a/src/worker/tasks/process-transaction-receipts-worker.ts b/src/worker/tasks/process-transaction-receipts-worker.ts deleted file mode 100644 index 1d4e64703..000000000 --- a/src/worker/tasks/process-transaction-receipts-worker.ts +++ /dev/null @@ -1,232 +0,0 @@ -import type { Prisma } from "@prisma/client"; -import type { AbiEvent } from "abitype"; -import { Worker, type Job, type Processor } from "bullmq"; -import superjson from "superjson"; -import { - eth_getBlockByNumber, - eth_getTransactionReceipt, - getContract, - getRpcClient, - type Address, - type ThirdwebContract, -} from "thirdweb"; -import { resolveContractAbi } from "thirdweb/contract"; -import { decodeFunctionData, type Abi, type Hash } from "viem"; -import { bulkInsertContractTransactionReceipts } from "../../shared/db/contract-transaction-receipts/create-contract-transaction-receipts"; -import { WebhooksEventTypes } from "../../shared/schemas/webhooks"; -import { getChain } from "../../shared/utils/chain"; -import { logger } from "../../shared/utils/logger"; -import { normalizeAddress } from "../../shared/utils/primitive-types"; -import { redis } from "../../shared/utils/redis/redis"; -import { thirdwebClient } from "../../shared/utils/sdk"; -import { - ProcessTransactionReceiptsQueue, - type EnqueueProcessTransactionReceiptsData, -} from "../queues/process-transaction-receipts-queue"; -import { logWorkerExceptions } from "../queues/queues"; -import { SendWebhookQueue } from "../queues/send-webhook-queue"; -import { getWebhooksByContractAddresses } from "./process-event-logs-worker"; - -const handler: Processor = async (job: Job) => { - const { - chainId, - filters = [], - fromBlock, - toBlock, - } = superjson.parse(job.data); - - const receipts = await getFormattedTransactionReceipts({ - chainId, - fromBlock, - toBlock, - filters, - }); - if (receipts.length === 0) { - return; - } - - // Store logs to DB. - const insertedReceipts = await bulkInsertContractTransactionReceipts({ - receipts, - }); - if (insertedReceipts.length === 0) { - return; - } - job.log(`Inserted ${insertedReceipts.length} events.`); - - // Enqueue webhooks. - const webhooksByContractAddress = - await getWebhooksByContractAddresses(chainId); - for (const transactionReceipt of insertedReceipts) { - const webhooks = - webhooksByContractAddress[transactionReceipt.contractAddress] ?? []; - for (const webhook of webhooks) { - await SendWebhookQueue.enqueueWebhook({ - type: WebhooksEventTypes.CONTRACT_SUBSCRIPTION, - webhook, - transactionReceipt, - }); - } - } - - // Any receipts inserted in a delayed job indicates missed receipts in the realtime job. - if (job.opts.delay && job.opts.delay > 0) { - logger({ - service: "worker", - level: "warn", - message: `Found ${ - insertedReceipts.length - } receipts on chain: ${chainId}, block: ${insertedReceipts.map( - (receipt) => receipt.blockNumber, - )} after ${job.opts.delay / 1000}s.`, - }); - } -}; - -/** - * Gets all transaction receipts for the subscribed addresses and filters. - * @returns A list of receipts to insert to the ContractTransactionReceipts table. - */ -const getFormattedTransactionReceipts = async ({ - chainId, - fromBlock, - toBlock, - filters, -}: EnqueueProcessTransactionReceiptsData): Promise< - Prisma.ContractTransactionReceiptsCreateInput[] -> => { - if (filters.length === 0) { - return []; - } - - const chain = await getChain(chainId); - const rpcRequest = getRpcClient({ client: thirdwebClient, chain }); - - // Get array of block numbers between `fromBlock` and `toBlock` inclusive. - const blockRange: bigint[] = []; - for (let i = fromBlock; i <= toBlock; i++) { - blockRange.push(BigInt(i)); - } - - // Get the filtered functions (empty = no filter) and contract object for each address. - const addressConfig: Record< - Address, - { - functions: string[]; - contract: ThirdwebContract; - } - > = {}; - for (const filter of filters) { - // Merge multiple filters for the same address. - if (filter.address in addressConfig) { - addressConfig[filter.address].functions.push(...filter.functions); - } - - addressConfig[filter.address] = { - functions: filter.functions, - contract: getContract({ - client: thirdwebClient, - chain, - address: filter.address, - }), - }; - } - - const getFormattedTransactionReceiptsFromBlock = async ( - blockNumber: bigint, - ): Promise => { - const block = await eth_getBlockByNumber(rpcRequest, { - blockNumber, - includeTransactions: true, - }); - - const receipts: Prisma.ContractTransactionReceiptsCreateInput[] = []; - for (const transaction of block.transactions) { - if (!transaction.to) { - // This transaction is a contract deployment. - continue; - } - const toAddress = normalizeAddress(transaction.to); - const config = addressConfig[toAddress]; - if (!config) { - // This transaction is not to a subscribed address. - continue; - } - - let functionName: string | undefined; - try { - functionName = await getFunctionName({ - contract: config.contract, - data: transaction.input, - }); - } catch { - // Unable to parse function. Continue. - } - - if ( - config.functions.length > 0 && - (!functionName || !config.functions.includes(functionName)) - ) { - // Function not found, or this transaction is not for a subscribed function. - continue; - } - - // Store the transaction and receipt. - const receipt = await eth_getTransactionReceipt(rpcRequest, { - hash: transaction.hash, - }); - - receipts.push({ - chainId: chainId.toString(), - blockNumber: Number(receipt.blockNumber), - contractAddress: toAddress, - contractId: getContractId(chainId, toAddress), - blockHash: receipt.blockHash.toLowerCase(), - transactionHash: receipt.transactionHash.toLowerCase(), - timestamp: new Date(Number(block.timestamp) * 1000), - to: toAddress, - from: normalizeAddress(receipt.from), - value: transaction.value.toString(), - data: transaction.input, - functionName, - transactionIndex: receipt.transactionIndex, - gasUsed: receipt.gasUsed.toString(), - effectiveGasPrice: receipt.effectiveGasPrice?.toString() ?? "", - status: receipt.status === "success" ? 1 : 0, - }); - } - - return receipts; - }; - - const allReceipts = await Promise.all( - blockRange.map((blockNumber) => - getFormattedTransactionReceiptsFromBlock(blockNumber), - ), - ); - return allReceipts.flat(); -}; - -const getFunctionName = async (args: { - contract: ThirdwebContract; - data: Hash; -}) => { - const abi = await resolveContractAbi(args.contract); - const decoded = decodeFunctionData({ - abi, - data: args.data, - }); - return decoded.functionName; -}; - -// Must be explicitly called for the worker to run on this host. -export const initProcessTransactionReceiptsWorker = () => { - const _worker = new Worker(ProcessTransactionReceiptsQueue.q.name, handler, { - concurrency: 5, - connection: redis, - }); - logWorkerExceptions(_worker); -}; - -const getContractId = (chainId: number, contractAddress: string) => - `${chainId}:${contractAddress}`; diff --git a/src/worker/tasks/prune-transactions-worker.ts b/src/worker/tasks/prune-transactions-worker.ts deleted file mode 100644 index 4bac12a27..000000000 --- a/src/worker/tasks/prune-transactions-worker.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Worker, type Job, type Processor } from "bullmq"; -import { TransactionDB } from "../../shared/db/transactions/db"; -import { pruneNonceMaps } from "../../shared/db/wallets/nonce-map"; -import { env } from "../../shared/utils/env"; -import { redis } from "../../shared/utils/redis/redis"; -import { PruneTransactionsQueue } from "../queues/prune-transactions-queue"; -import { logWorkerExceptions } from "../queues/queues"; - -const handler: Processor = async (job: Job) => { - const numTransactionsDeleted = - await TransactionDB.pruneTransactionDetailsAndLists( - env.TRANSACTION_HISTORY_COUNT, - ); - job.log(`Pruned ${numTransactionsDeleted} transaction details.`); - - const numNonceMapsDeleted = await pruneNonceMaps(); - job.log(`Pruned ${numNonceMapsDeleted} nonce maps.`); -}; - -// Must be explicitly called for the worker to run on this host. -export const initPruneTransactionsWorker = () => { - PruneTransactionsQueue.q.add("cron", "", { - repeat: { pattern: "*/10 * * * *" }, - jobId: "prune-transactions-cron", - }); - - const _worker = new Worker(PruneTransactionsQueue.q.name, handler, { - concurrency: 1, - connection: redis, - }); - logWorkerExceptions(_worker); -}; diff --git a/src/worker/tasks/send-transaction-worker.ts b/src/worker/tasks/send-transaction-worker.ts deleted file mode 100644 index e00825db4..000000000 --- a/src/worker/tasks/send-transaction-worker.ts +++ /dev/null @@ -1,673 +0,0 @@ -import { Worker, type Job, type Processor } from "bullmq"; -import assert from "node:assert"; -import superjson from "superjson"; -import { - getAddress, - getContract, - readContract, - toSerializableTransaction, - toTokens, - type Hex, -} from "thirdweb"; -import { getChainMetadata } from "thirdweb/chains"; -import { isZkSyncChain, stringify } from "thirdweb/utils"; -import type { Account } from "thirdweb/wallets"; -import { - bundleUserOp, - createAndSignUserOp, - smartWallet, - type UserOperation, -} from "thirdweb/wallets/smart"; -import { getContractAddress } from "viem"; -import { TransactionDB } from "../../shared/db/transactions/db"; -import { - acquireNonce, - addSentNonce, - recycleNonce, - syncLatestNonceFromOnchainIfHigher, -} from "../../shared/db/wallets/wallet-nonce"; -import { - getAccount, - getSmartBackendWalletAdminAccount, -} from "../../shared/utils/account"; -import { getBlockNumberish } from "../../shared/utils/block"; -import { getChain } from "../../shared/utils/chain"; -import { msSince } from "../../shared/utils/date"; -import { env } from "../../shared/utils/env"; -import { - isInsufficientFundsError, - isNonceAlreadyUsedError, - isReplacementGasFeeTooLow, - wrapError, -} from "../../shared/utils/error"; -import { BigIntMath } from "../../shared/utils/math"; -import { getChecksumAddress } from "../../shared/utils/primitive-types"; -import { recordMetrics } from "../../shared/utils/prometheus"; -import { redis } from "../../shared/utils/redis/redis"; -import { thirdwebClient } from "../../shared/utils/sdk"; -import type { - ErroredTransaction, - PopulatedTransaction, - QueuedTransaction, - SentTransaction, -} from "../../shared/utils/transaction/types"; -import { enqueueTransactionWebhook } from "../../shared/utils/transaction/webhook"; -import { reportUsage } from "../../shared/utils/usage"; -import { MineTransactionQueue } from "../queues/mine-transaction-queue"; -import { logWorkerExceptions } from "../queues/queues"; -import { - SendTransactionQueue, - type SendTransactionData, -} from "../queues/send-transaction-queue"; - -/** - * Submit a transaction to RPC (EOA transactions) or bundler (userOps). - * - * This worker also handles retried EOA transactions. - */ -const handler: Processor = async (job: Job) => { - const { queueId, resendCount } = superjson.parse( - job.data, - ); - - const transaction = await TransactionDB.get(queueId); - if (!transaction) { - job.log(`Invalid transaction state: ${stringify(transaction)}`); - return; - } - - let resultTransaction: - | SentTransaction // Transaction sent successfully. - | ErroredTransaction // Transaction failed and will not be retried. - | null; // No attempt to send is made. - // This job may also throw to indicate an unexpected error that will be retried. - - if (transaction.status === "queued") { - if (transaction.isUserOp) { - resultTransaction = await _sendUserOp(job, transaction); - } else { - resultTransaction = await _sendTransaction(job, transaction); - } - } else if (transaction.status === "sent") { - resultTransaction = await _resendTransaction(job, transaction, resendCount); - } else { - job.log(`Invalid transaction state: ${stringify(transaction)}`); - return; - } - - if (resultTransaction) { - await TransactionDB.set(resultTransaction); - - if (resultTransaction.status === "sent") { - job.log(`Transaction sent: ${stringify(resultTransaction)}.`); - if (resendCount === 0) { - await MineTransactionQueue.add({ queueId: resultTransaction.queueId }); - await enqueueTransactionWebhook(resultTransaction); - await _reportSuccess(resultTransaction); - } - } else if (resultTransaction.status === "errored") { - job.log(`Transaction errored: ${stringify(resultTransaction)}.`); - await enqueueTransactionWebhook(resultTransaction); - _reportError(resultTransaction); - } - } -}; - -const _sendUserOp = async ( - job: Job, - queuedTransaction: QueuedTransaction, -): Promise => { - assert(queuedTransaction.isUserOp); - - if (_hasExceededTimeout(queuedTransaction)) { - // Fail if the transaction is not sent within the specified timeout. - return { - ...queuedTransaction, - status: "errored", - errorMessage: `Exceeded ${queuedTransaction.timeoutSeconds}s timeout`, - }; - } - - const { - from, - accountAddress, - to, - target, - chainId, - accountFactoryAddress: userProvidedAccountFactoryAddress, - entrypointAddress: userProvidedEntrypointAddress, - accountSalt, - overrides, - } = queuedTransaction; - const chain = await getChain(chainId); - - assert(accountAddress, "Invalid userOp parameters: accountAddress"); - const toAddress = to ?? target; - - if (queuedTransaction.batchOperations) { - queuedTransaction.batchOperations.map((op) => { - assert(op.to, "Invalid transaction parameters: to"); - }); - } else { - assert(toAddress, "Invalid transaction parameters: to"); - } - - // this can either be a regular backend wallet userop or a smart backend wallet userop - let adminAccount: Account | undefined; - - try { - adminAccount = await getSmartBackendWalletAdminAccount({ - accountAddress, - chainId: chainId, - }); - } catch { - // do nothing, this might still be a regular backend wallet userop - } - - if (!adminAccount) { - adminAccount = await getAccount({ - chainId: chainId, - from, - }); - } - - if (!adminAccount) { - job.log("Failed to find admin account for userop"); - return { - ...queuedTransaction, - status: "errored", - errorMessage: "Failed to find admin account for userop", - }; - } - - let signedUserOp: UserOperation; - try { - // Resolve the user factory from the provided address, or from the `factory()` method if found. - let accountFactoryAddress = userProvidedAccountFactoryAddress; - if (!accountFactoryAddress) { - // TODO: this is not a good solution since the assumption that the account has a factory function is not guaranteed - // instead, we should use default account factory address or throw here. - try { - const smartAccountContract = getContract({ - client: thirdwebClient, - chain, - address: accountAddress, - }); - const onchainAccountFactoryAddress = await readContract({ - contract: smartAccountContract, - method: "function factory() view returns (address)", - params: [], - }); - accountFactoryAddress = getAddress(onchainAccountFactoryAddress); - } catch { - throw new Error( - `Failed to find factory address for account '${accountAddress}' on chain '${chainId}'`, - ); - } - } - - const transactions = queuedTransaction.batchOperations - ? queuedTransaction.batchOperations.map((op) => ({ - ...op, - chain, - client: thirdwebClient, - })) - : [ - { - client: thirdwebClient, - chain, - ...queuedTransaction, - ...overrides, - to: getChecksumAddress(toAddress), - }, - ]; - - signedUserOp = (await createAndSignUserOp({ - client: thirdwebClient, - transactions, - adminAccount, - smartWalletOptions: { - chain, - sponsorGas: true, - factoryAddress: accountFactoryAddress, - overrides: { - accountAddress, - accountSalt, - entrypointAddress: userProvidedEntrypointAddress, - // TODO: let user pass entrypoint address for 0.7 support - }, - }, - // don't wait for the account to be deployed between userops - // making this true will cause issues since it will block this call - // until the previous userop for the same account is mined - // we don't want this behavior in the engine context - waitForDeployment: false, - })) as UserOperation; // TODO support entrypoint v0.7 accounts - } catch (error) { - const errorMessage = wrapError(error, "Bundler").message; - const erroredTransaction: ErroredTransaction = { - ...queuedTransaction, - status: "errored", - errorMessage, - }; - job.log(`Failed to populate transaction: ${errorMessage}`); - return erroredTransaction; - } - - job.log(`Populated userOp: ${stringify(signedUserOp)}`); - - const userOpHash = await bundleUserOp({ - userOp: signedUserOp, - options: { - client: thirdwebClient, - chain, - entrypointAddress: userProvidedEntrypointAddress, - }, - }); - - return { - ...queuedTransaction, - isUserOp: true, - status: "sent", - nonce: signedUserOp.nonce.toString(), - userOpHash, - sentAt: new Date(), - sentAtBlock: await getBlockNumberish(queuedTransaction.chainId), - gas: signedUserOp.callGasLimit, - maxFeePerGas: signedUserOp.maxFeePerGas, - maxPriorityFeePerGas: signedUserOp.maxPriorityFeePerGas, - }; -}; - -const _sendTransaction = async ( - job: Job, - queuedTransaction: QueuedTransaction, -): Promise => { - assert(!queuedTransaction.isUserOp); - - if (_hasExceededTimeout(queuedTransaction)) { - // Fail if the transaction is not sent within the specified timeout. - return { - ...queuedTransaction, - status: "errored", - errorMessage: `Exceeded ${queuedTransaction.timeoutSeconds}s timeout`, - }; - } - - const { queueId, chainId, from, to, overrides } = queuedTransaction; - const chain = await getChain(chainId); - - const ownerAccount = await getAccount({ - chainId: chainId, - from: from, - }); - - let account: Account; - - if (queuedTransaction.transactionMode === "sponsored") { - if (!(await isZkSyncChain(chain))) { - job.log( - "Sponsored EOA transactions are only supported on zkSync chains.", - ); - const erroredTransaction: ErroredTransaction = { - ...queuedTransaction, - status: "errored", - errorMessage: - "Sponsored EOA transactions are only supported on zkSync chains.", - }; - return erroredTransaction; - } - - account = await smartWallet({ chain, sponsorGas: true }).connect({ - personalAccount: ownerAccount, - client: thirdwebClient, - }); - } - - // If no account was provided, use the owner account. - account ??= ownerAccount; - - // Populate the transaction to resolve gas values. - // This call throws if the execution would be reverted. - // The nonce is _not_ set yet. - - let populatedTransaction: PopulatedTransaction; - try { - populatedTransaction = await toSerializableTransaction({ - from: getChecksumAddress(from), - transaction: { - client: thirdwebClient, - chain, - ...queuedTransaction, - to: getChecksumAddress(to), - // Use a dummy nonce since we override it later. - nonce: 1, - - // Apply gas setting overrides. - // Do not set `maxFeePerGas` to estimate the onchain value. - gas: overrides?.gas, - gasPrice: overrides?.gasPrice, - maxPriorityFeePerGas: overrides?.maxPriorityFeePerGas, - }, - }); - } catch (error: unknown) { - const errorMessage = wrapError(error, "RPC").message; - const erroredTransaction: ErroredTransaction = { - ...queuedTransaction, - status: "errored", - errorMessage, - }; - job.log(`Failed to populate transaction: ${errorMessage}`); - return erroredTransaction; - } - - // Handle if `maxFeePerGas` is overridden. - // Set it if the transaction will be sent, otherwise delay the job. - if (overrides?.maxFeePerGas && populatedTransaction.maxFeePerGas) { - if (overrides.maxFeePerGas > populatedTransaction.maxFeePerGas) { - populatedTransaction.maxFeePerGas = overrides.maxFeePerGas; - } else { - const retryAt = _minutesFromNow(5); - job.log( - `Override gas fee (${overrides.maxFeePerGas}) is lower than onchain fee (${populatedTransaction.maxFeePerGas}). Delaying job until ${retryAt}.`, - ); - await job.moveToDelayed(retryAt.getTime()); - return null; - } - } - - // Acquire an unused nonce for this transaction. - const { nonce, isRecycledNonce } = await acquireNonce({ - queueId, - chainId, - walletAddress: from, - }); - populatedTransaction.nonce = nonce; - job.log( - `Populated transaction (isRecycledNonce=${isRecycledNonce}): ${stringify(populatedTransaction)}`, - ); - - // Send transaction to RPC. - // This call throws if the RPC rejects the transaction. - let transactionHash: Hex; - try { - const sendTransactionResult = - await account.sendTransaction(populatedTransaction); - transactionHash = sendTransactionResult.transactionHash; - } catch (error: unknown) { - // If the nonce is already seen onchain (nonce too low) or in mempool (replacement underpriced), - // correct the DB nonce. - if (isNonceAlreadyUsedError(error) || isReplacementGasFeeTooLow(error)) { - const result = await syncLatestNonceFromOnchainIfHigher(chainId, from); - job.log(`Re-synced nonce: ${result}`); - } else { - // Otherwise this nonce is not used yet. Recycle it to be used by a future transaction. - job.log(`Recycling nonce: ${nonce}`); - await recycleNonce(chainId, from, nonce); - } - - // Do not retry errors that are expected to be rejected by RPC again. - if (isInsufficientFundsError(error)) { - const { name, nativeCurrency } = await getChainMetadata(chain); - const { gas, value = 0n } = populatedTransaction; - const gasPrice = - populatedTransaction.gasPrice ?? populatedTransaction.maxFeePerGas; - - const minGasTokens = gasPrice - ? toTokens(gas * gasPrice + value, 18) - : null; - const errorMessage = minGasTokens - ? `Insufficient funds in ${account.address} on ${name}. Transaction requires > ${minGasTokens} ${nativeCurrency.symbol}.` - : `Insufficient funds in ${account.address} on ${name}. Transaction requires more ${nativeCurrency.symbol}.`; - return { - ...queuedTransaction, - status: "errored", - errorMessage, - } satisfies ErroredTransaction; - } - - throw wrapError(error, "RPC"); - } - - await addSentNonce(chainId, from, nonce); - - return { - ...queuedTransaction, - status: "sent", - isUserOp: false, - nonce, - sentTransactionHashes: [transactionHash], - resendCount: 0, - sentAt: new Date(), - sentAtBlock: await getBlockNumberish(chainId), - gas: populatedTransaction.gas, - gasPrice: populatedTransaction.gasPrice, - maxFeePerGas: populatedTransaction.maxFeePerGas, - maxPriorityFeePerGas: populatedTransaction.maxPriorityFeePerGas, - deployedContractAddress: _resolveDeployedContractAddress( - queuedTransaction, - nonce, - ), - }; -}; - -const _resendTransaction = async ( - job: Job, - sentTransaction: SentTransaction, - resendCount: number, -): Promise => { - assert(!sentTransaction.isUserOp); - - if (_hasExceededTimeout(sentTransaction)) { - // Don't resend past the timeout. A transaction in mempool may still be mined later. - return null; - } - - // Populate the transaction with double gas. - const { chainId, from, overrides, sentTransactionHashes } = sentTransaction; - let populatedTransaction = await toSerializableTransaction({ - from: getChecksumAddress(from), - transaction: { - client: thirdwebClient, - chain: await getChain(chainId), - ...sentTransaction, - // Use overrides, if any. - // If no overrides, set to undefined so gas settings can be re-populated. - gas: overrides?.gas, - maxFeePerGas: overrides?.maxFeePerGas, - maxPriorityFeePerGas: overrides?.maxPriorityFeePerGas, - }, - }); - - // Increase gas fees for this resend attempt. - populatedTransaction = _updateGasFees( - populatedTransaction, - sentTransaction.resendCount + 1, - sentTransaction.overrides, - ); - - job.log(`Populated transaction: ${stringify(populatedTransaction)}`); - - // Send transaction to RPC. - // This call throws if the RPC rejects the transaction. - let transactionHash: Hex; - try { - const account = await getAccount({ chainId, from }); - const result = await account.sendTransaction(populatedTransaction); - transactionHash = result.transactionHash; - } catch (error) { - if (isNonceAlreadyUsedError(error)) { - job.log( - "Nonce used. This transaction was likely already mined. Do not resend.", - ); - return null; - } - if (isReplacementGasFeeTooLow(error)) { - job.log("A pending transaction exists with >= gas fees. Do not resend."); - return null; - } - throw wrapError(error, "RPC"); - } - - return { - ...sentTransaction, - resendCount, - sentAt: new Date(), - sentAtBlock: await getBlockNumberish(chainId), - // Dedupe transaction hashes. - sentTransactionHashes: [ - ...new Set([...sentTransactionHashes, transactionHash]), - ], - gas: populatedTransaction.gas, - gasPrice: populatedTransaction.gasPrice, - maxFeePerGas: populatedTransaction.maxFeePerGas, - maxPriorityFeePerGas: populatedTransaction.maxPriorityFeePerGas, - }; -}; - -const _reportSuccess = async (sentTransaction: SentTransaction) => { - const chain = await getChain(sentTransaction.chainId); - reportUsage([ - { - action: "send_tx", - input: { - ...sentTransaction, - provider: chain.rpc, - msSinceQueue: msSince(sentTransaction.queuedAt), - }, - }, - ]); - recordMetrics({ - event: "transaction_sent", - params: { - chainId: sentTransaction.chainId.toString(), - success: true, - walletAddress: getAddress(sentTransaction.from), - durationSeconds: msSince(sentTransaction.queuedAt) / 1000, - }, - }); -}; - -const _reportError = (erroredTransaction: ErroredTransaction) => { - reportUsage([ - { - action: "error_tx", - input: { - ...erroredTransaction, - msSinceQueue: msSince(erroredTransaction.queuedAt), - }, - error: erroredTransaction.errorMessage, - }, - ]); - recordMetrics({ - event: "transaction_sent", - params: { - chainId: erroredTransaction.chainId.toString(), - success: false, - walletAddress: getAddress(erroredTransaction.from), - durationSeconds: msSince(erroredTransaction.queuedAt) / 1000, - }, - }); -}; - -const _resolveDeployedContractAddress = ( - queuedTransaction: QueuedTransaction, - nonce: number, -) => { - if (queuedTransaction.deployedContractAddress) { - return queuedTransaction.deployedContractAddress; - } - - if ( - queuedTransaction.extension === "deploy-published" && - queuedTransaction.functionName === "deploy" - ) { - return getContractAddress({ - from: queuedTransaction.from, - nonce: BigInt(nonce), - }); - } -}; - -const _hasExceededTimeout = ( - transaction: QueuedTransaction | SentTransaction, -) => - transaction.timeoutSeconds !== undefined && - msSince(transaction.queuedAt) / 1000 > transaction.timeoutSeconds; - -const _minutesFromNow = (minutes: number) => - new Date(Date.now() + minutes * 60_000); - -/** - * Computes aggressive gas fees when resending a transaction. - * - * For legacy transactions (pre-EIP1559): - * - Gas price = (2 * attempt) * estimatedGasPrice, capped at 10x. - * - * For other transactions: - * - maxPriorityFeePerGas = (2 * attempt) * estimatedMaxPriorityFeePerGas, capped at 10x. - * - maxFeePerGas = (2 * estimatedMaxFeePerGas) + maxPriorityFeePerGas. - * - * @param populatedTransaction The transaction with estimated gas from RPC. - * @param resendCount The resend attempt #. Example: 2 = the transaction was initially sent, then resent once. This is the second resend attempt. - */ -export function _updateGasFees( - populatedTransaction: PopulatedTransaction, - resendCount: number, - overrides: SentTransaction["overrides"], -): PopulatedTransaction { - if (resendCount === 0) { - return populatedTransaction; - } - - const multiplier = BigIntMath.min(10n, BigInt(resendCount) * 2n); - const updated = { ...populatedTransaction }; - - // Update gas fees (unless they were explicitly overridden). - // Do not exceed MAX_GAS_PRICE_WEI. - const MAX_GAS_PRICE_WEI = BigInt(env.EXPERIMENTAL__MAX_GAS_PRICE_WEI); - - if (updated.gasPrice && !overrides?.gasPrice) { - const newGasPrice = updated.gasPrice * multiplier; - updated.gasPrice = BigIntMath.min(newGasPrice, MAX_GAS_PRICE_WEI); - } - if (updated.maxPriorityFeePerGas && !overrides?.maxPriorityFeePerGas) { - updated.maxPriorityFeePerGas *= multiplier; - } - if (updated.maxFeePerGas && !overrides?.maxFeePerGas) { - const newMaxFeePerGas = - updated.maxFeePerGas * 2n + (updated.maxPriorityFeePerGas ?? 0n); - updated.maxFeePerGas = BigIntMath.min(newMaxFeePerGas, MAX_GAS_PRICE_WEI); - } - - return updated; -} - -// Must be explicitly called for the worker to run on this host. -export const initSendTransactionWorker = () => { - const _worker = new Worker(SendTransactionQueue.q.name, handler, { - concurrency: env.SEND_TRANSACTION_QUEUE_CONCURRENCY, - connection: redis, - }); - logWorkerExceptions(_worker); - - // If a transaction fails to send after all retries, error it. - _worker.on("failed", async (job: Job | undefined, error: Error) => { - if (job && job.attemptsMade === job.opts.attempts) { - const { queueId } = superjson.parse(job.data); - const transaction = await TransactionDB.get(queueId); - if (transaction) { - const erroredTransaction: ErroredTransaction = { - ...transaction, - status: "errored", - errorMessage: error.message, - }; - job.log(`Transaction errored: ${stringify(erroredTransaction)}`); - - await TransactionDB.set(erroredTransaction); - await enqueueTransactionWebhook(erroredTransaction); - _reportError(erroredTransaction); - } - } - }); -}; diff --git a/src/worker/tasks/send-webhook-worker.ts b/src/worker/tasks/send-webhook-worker.ts deleted file mode 100644 index dda1f1f5b..000000000 --- a/src/worker/tasks/send-webhook-worker.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { Static } from "@sinclair/typebox"; -import { Worker, type Job, type Processor } from "bullmq"; -import superjson from "superjson"; -import { TransactionDB } from "../../shared/db/transactions/db"; -import { - WebhooksEventTypes, - type BackendWalletBalanceWebhookParams, -} from "../../shared/schemas/webhooks"; -import { toEventLogSchema } from "../../server/schemas/event-log"; -import { - toTransactionSchema, - type TransactionSchema, -} from "../../server/schemas/transaction"; -import { toTransactionReceiptSchema } from "../../server/schemas/transaction-receipt"; -import { logger } from "../../shared/utils/logger"; -import { redis } from "../../shared/utils/redis/redis"; -import { - sendWebhookRequest, - type WebhookResponse, -} from "../../shared/utils/webhook"; -import { SendWebhookQueue, type WebhookJob } from "../queues/send-webhook-queue"; - -const handler: Processor = async (job: Job) => { - const { data, webhook } = superjson.parse(job.data); - - let resp: WebhookResponse | undefined; - switch (data.type) { - case WebhooksEventTypes.CONTRACT_SUBSCRIPTION: { - let webhookBody: { - type: "event-log" | "transaction-receipt"; - data: unknown; - }; - if (data.eventLog) { - webhookBody = { - type: "event-log", - data: toEventLogSchema(data.eventLog), - }; - } else if (data.transactionReceipt) { - webhookBody = { - type: "transaction-receipt", - data: toTransactionReceiptSchema(data.transactionReceipt), - }; - } else { - throw new Error( - 'Missing "eventLog" or "transactionReceipt" for CONTRACT_SUBSCRIPTION webhook.', - ); - } - resp = await sendWebhookRequest(webhook, webhookBody); - break; - } - - case WebhooksEventTypes.SENT_TX: - case WebhooksEventTypes.MINED_TX: - case WebhooksEventTypes.ERRORED_TX: - case WebhooksEventTypes.CANCELLED_TX: { - const transaction = await TransactionDB.get(data.queueId); - if (!transaction) { - job.log("Transaction not found."); - return; - } - const webhookBody: Static = - toTransactionSchema(transaction); - resp = await sendWebhookRequest(webhook, webhookBody); - break; - } - - case WebhooksEventTypes.BACKEND_WALLET_BALANCE: { - const webhookBody: BackendWalletBalanceWebhookParams = data.body; - resp = await sendWebhookRequest(webhook, webhookBody); - break; - } - } - - // Throw on 5xx so it remains in the queue to retry later. - if (resp && resp.status >= 500) { - const error = new Error( - `Received status ${resp.status} from webhook ${webhook.url}.`, - ); - job.log(error.message); - logger({ - level: "debug", - message: error.message, - service: "worker", - }); - throw error; - } -}; - -// Must be explicitly called for the worker to run on this host. -export const initSendWebhookWorker = () => { - new Worker(SendWebhookQueue.q.name, handler, { - concurrency: 10, - connection: redis, - }); -}; diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 000000000..8ca0ea0ca --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +wallets*.json diff --git a/tests/e2e/.env.test.example b/tests/e2e/.env.test.example deleted file mode 100644 index 8a608e33a..000000000 --- a/tests/e2e/.env.test.example +++ /dev/null @@ -1,4 +0,0 @@ -THIRDWEB_API_SECRET_KEY="" -ENGINE_ACCESS_TOKEN="" -ENGINE_URL="http://127.0.0.1:3005/" -ANVIL_URL="" \ No newline at end of file diff --git a/tests/e2e/.gitignore b/tests/e2e/.gitignore deleted file mode 100644 index 7cf2c6b39..000000000 --- a/tests/e2e/.gitignore +++ /dev/null @@ -1,174 +0,0 @@ -# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore - -# Logs - -logs -_.log -npm-debug.log_ -yarn-debug.log* -yarn-error.log* -lerna-debug.log* -.pnpm-debug.log* - -# Caches - -.cache - -# Diagnostic reports (https://nodejs.org/api/report.html) - -report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json - -# Runtime data - -pids -_.pid -_.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover - -lib-cov - -# Coverage directory used by tools like istanbul - -coverage -*.lcov - -# nyc test coverage - -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) - -.grunt - -# Bower dependency directory (https://bower.io/) - -bower_components - -# node-waf configuration - -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) - -build/Release - -# Dependency directories - -node_modules/ -jspm_packages/ - -# Snowpack dependency directory (https://snowpack.dev/) - -web_modules/ - -# TypeScript cache - -*.tsbuildinfo - -# Optional npm cache directory - -.npm - - -# Optional stylelint cache - -.stylelintcache - -# Microbundle cache - -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history - -.node_repl_history - -# Output of 'npm pack' - -*.tgz - -# Yarn Integrity file - -.yarn-integrity - -# dotenv environment variable files - -.env -.env.development.local -.env.test.local -.env.production.local -.env.local - -# parcel-bundler cache (https://parceljs.org/) - -.parcel-cache - -# Next.js build output - -.next -out - -# Nuxt.js build / generate output - -.nuxt -dist - -# Gatsby files - -# Comment in the public line in if your project uses Gatsby and not Next.js - -# https://nextjs.org/blog/next-9-1#public-directory-support - -# public - -# vuepress build output - -.vuepress/dist - -# vuepress v2.x temp and cache directory - -.temp - -# Docusaurus cache and generated files - -.docusaurus - -# Serverless directories - -.serverless/ - -# FuseBox cache - -.fusebox/ - -# DynamoDB Local files - -.dynamodb/ - -# TernJS port file - -.tern-port - -# Stores VSCode versions used for testing VSCode extensions - -.vscode-test - -# yarn v2 - -.yarn/cache -.yarn/unplugged -.yarn/build-state.yml -.yarn/install-state.gz -.pnp.* - -# IntelliJ based IDEs -.idea - -# Finder (MacOS) folder config -.DS_Store - -.env.test \ No newline at end of file diff --git a/tests/e2e/README.md b/tests/e2e/README.md deleted file mode 100644 index a983ff554..000000000 --- a/tests/e2e/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# engine e2e test suite -## Configuration -1. Create a `.env.test` file (use `.env.test.example` as a template) and fill in the necessary values. -2. Check `config.ts` to configure the test suite. -3. Run `bun test` within the directory to run the tests. - -Note: make sure `engine` is running, and `anvil` is installed if running the tests on a local environment. (You can get the latest version of `anvil` by installing [`foundry`](https://book.getfoundry.sh/getting-started/installation)) - -## Running tests -The test suite depends on a local SDK to run tests. To run the tests, you need to generate the SDK. To do this, run the following command from the root of the repository: - -```bash -yarn generate:sdk -``` -Run all subsequent commands from the `test/e2e` directory. - -Some tests contains load tests which take a long time to run. To ensure they don't timeout, use the following command: - -```bash -bun test --timeout 300000 -``` - -To run a specific test, use the following command: - -```bash -bun test tests/.test.ts -``` \ No newline at end of file diff --git a/tests/e2e/bun.lockb b/tests/e2e/bun.lockb deleted file mode 100755 index ff0b23ec5..000000000 Binary files a/tests/e2e/bun.lockb and /dev/null differ diff --git a/tests/e2e/config.ts b/tests/e2e/config.ts deleted file mode 100644 index f1a111e49..000000000 --- a/tests/e2e/config.ts +++ /dev/null @@ -1,30 +0,0 @@ -import assert from "node:assert"; -import { anvil, type Chain } from "thirdweb/chains"; - -assert(process.env.ENGINE_URL, "ENGINE_URL is required"); -assert(process.env.ENGINE_ACCESS_TOKEN, "ENGINE_ACCESS_TOKEN is required"); - -export const CONFIG: Config = { - ACCESS_TOKEN: process.env.ENGINE_ACCESS_TOKEN, - URL: process.env.ENGINE_URL, - USE_LOCAL_CHAIN: true, - CHAIN: { - ...anvil, - rpc: "http://127.0.0.1:8545/1", - }, - TRANSACTION_COUNT: 500, - TRANSACTIONS_PER_BATCH: 100, - POLLING_INTERVAL: 1000, - STAGGER_MAX: 500, -}; - -type Config = { - ACCESS_TOKEN: string; - URL: string; - TRANSACTION_COUNT: number; - TRANSACTIONS_PER_BATCH: number; - POLLING_INTERVAL: number; - STAGGER_MAX: number; - CHAIN: Chain; - USE_LOCAL_CHAIN?: boolean; -}; diff --git a/tests/e2e/package.json b/tests/e2e/package.json deleted file mode 100644 index d9ecbc3bc..000000000 --- a/tests/e2e/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "e2e", - "module": "index.ts", - "devDependencies": { - "@types/bun": "latest", - "tsup": "^8.2.3" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "type": "module", - "dependencies": { - "prool": "^0.0.16", - "thirdweb": "^5.61.5" - } -} diff --git a/tests/e2e/scripts/counter.ts b/tests/e2e/scripts/counter.ts deleted file mode 100644 index 121e894e1..000000000 --- a/tests/e2e/scripts/counter.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Anvil chain outputs every RPC call to stdout -// You can save the output to a file and then use this script to count the number of times a specific RPC call is made. - -import { argv } from "bun"; -import { readFile } from "node:fs/promises"; -import { join } from "node:path"; - -const file = join(__dirname, argv[2]); - -async function countLines(file: string) { - const data = await readFile(file, "utf-8"); - const lines = data.split("\n"); - const statements = new Map(); - - for (const line of lines) { - if (!line.trim()) { - continue; - } - const statement = statements.get(line); - if (statement !== undefined) { - statements.set(line, statement + 1); - } else { - statements.set(line, 1); - } - } - - return statements; -} - -countLines(file).then((lines) => { - for (const [line, count] of lines) { - console.log(`${line}: ${count}`); - } -}); diff --git a/tests/e2e/tests/extensions.test.ts b/tests/e2e/tests/extensions.test.ts deleted file mode 100644 index 4fdb3c89c..000000000 --- a/tests/e2e/tests/extensions.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import assert from "node:assert"; -import { sleep } from "bun"; -import { beforeAll, describe, expect, test } from "bun:test"; -import { getAddress, type Address } from "viem"; -import { CONFIG } from "../config"; -import type { setupEngine } from "../utils/engine"; -import { setup } from "./setup"; - -describe("Extensions", () => { - let nftContractAddress: Address | undefined; - let engine: ReturnType; - let backendWallet: Address; - - beforeAll(async () => { - const setupRes = await setup(); - engine = setupRes.engine; - backendWallet = setupRes.backendWallet; - - const res = await engine.deploy.deployNftCollection( - CONFIG.CHAIN.id.toString(), - backendWallet, - { - contractMetadata: { - name: "Test NFT", - symbol: "TNFT", - fee_recipient: backendWallet, - platform_fee_basis_points: 0, - platform_fee_recipient: backendWallet, - seller_fee_basis_points: 0, - trusted_forwarders: [], - }, - }, - ); - - nftContractAddress = res.result.deployedAddress - ? getAddress(res.result.deployedAddress) - : undefined; - - let mined = false; - - assert(res.result.queueId, "Queue ID is not defined"); - while (!mined) { - const statusRes = await engine.transaction.status(res.result.queueId); - mined = statusRes.result.status === "mined"; - await sleep(1000); - } - - expect(nftContractAddress).toBeDefined(); - console.log("NFT Contract Address:", nftContractAddress); - }); - - test("Mint NFT", async () => { - expect(nftContractAddress).toBeDefined(); - assert(nftContractAddress, "NFT contract address is not defined"); - - const res = await engine.erc721.mintTo( - CONFIG.CHAIN.id.toString(), - nftContractAddress, - backendWallet, - { - receiver: backendWallet, - metadata: { - name: "My NFT", - description: "My NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - }, - ); - - expect(res.result.queueId).toBeDefined(); - assert(res.result.queueId, "Queue ID is not defined"); - - let mined = false; - while (!mined) { - const status = await engine.transaction.status(res.result.queueId); - mined = !!status.result.minedAt; - await sleep(1000); - } - - const engineBalanceOfBackendWallet = await engine.erc721.balanceOf( - backendWallet, - CONFIG.CHAIN.id.toString(), - nftContractAddress, - ); - - expect(engineBalanceOfBackendWallet.result).toEqual("1"); - }); -}); diff --git a/tests/e2e/tests/load.test.ts b/tests/e2e/tests/load.test.ts deleted file mode 100644 index 24eb798a2..000000000 --- a/tests/e2e/tests/load.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import assert from "node:assert"; -import { sleep } from "bun"; -import { describe, expect, test } from "bun:test"; -import { getAddress } from "viem"; -import { CONFIG } from "../config"; -import { printStats } from "../utils/statistics"; -import { - pollTransactionStatus, - sendMintToTransaction, - sendNoOpTransaction, -} from "../utils/transactions"; -import { setup } from "./setup"; - -describe("Load Test Transactions", () => { - test("Send NoOp Transactions", async () => { - const { engine, backendWallet } = await setup(); - - const timings = []; - for ( - let i = 0; - i < CONFIG.TRANSACTION_COUNT; - i += CONFIG.TRANSACTIONS_PER_BATCH - ) { - const batch = await Promise.all( - new Array(CONFIG.TRANSACTIONS_PER_BATCH) - .fill(0) - .map(() => sendNoOpTransaction(engine, backendWallet)), - ); - timings.push(...batch); - await sleep(1000); - } - - const results = await Promise.all( - timings.map(async (queueId) => { - if (!queueId) return null; - return pollTransactionStatus(engine, queueId); - }), - ); - - const minedTimes = results.map((r) => - r ? (r.minedAt || 0) - (r.queuedAt || 0) : 0, - ); - const sentTimes = results.map((r) => - r ? (r.sentAt || 0) - (r.queuedAt || 0) : 0, - ); - - printStats(minedTimes, sentTimes); - - expect(results.filter((r) => r !== null).length).toBe( - CONFIG.TRANSACTION_COUNT, - ); - }); - - test("Send MintTo Transactions", async () => { - const { engine, backendWallet } = await setup(); - - // First, deploy an NFT contract - const deployRes = await engine.deploy.deployNftCollection( - CONFIG.CHAIN.id.toString(), - backendWallet, - { - contractMetadata: { - name: "Test NFT", - symbol: "TNFT", - fee_recipient: backendWallet, - platform_fee_basis_points: 0, - platform_fee_recipient: backendWallet, - seller_fee_basis_points: 0, - trusted_forwarders: [], - }, - }, - ); - - const nftContractAddress = deployRes.result.deployedAddress - ? getAddress(deployRes.result.deployedAddress) - : undefined; - - expect(nftContractAddress).toBeDefined(); - - assert(nftContractAddress, "NFT contract address is not defined"); - - assert(deployRes.result.queueId, "Queue ID is not defined"); - - // Wait for the contract to be deployed - await pollTransactionStatus(engine, deployRes.result.queueId); - - const timings = []; - for ( - let i = 0; - i < CONFIG.TRANSACTION_COUNT; - i += CONFIG.TRANSACTIONS_PER_BATCH - ) { - const batch = await Promise.all( - new Array(CONFIG.TRANSACTIONS_PER_BATCH) - .fill(0) - .map(() => - sendMintToTransaction(engine, nftContractAddress, backendWallet), - ), - ); - timings.push(...batch); - await sleep(1000); - } - - const results = await Promise.all( - timings.map(async (queueId) => { - if (!queueId) return null; - return pollTransactionStatus(engine, queueId); - }), - ); - - const minedTimes = results.map((r) => - r ? (r.minedAt || 0) - (r.queuedAt || 0) : 0, - ); - const sentTimes = results.map((r) => - r ? (r.sentAt || 0) - (r.queuedAt || 0) : 0, - ); - - printStats(minedTimes, sentTimes); - - expect(results.filter((r) => r !== null).length).toBe( - CONFIG.TRANSACTION_COUNT, - ); - }); -}); diff --git a/tests/e2e/tests/read.test.ts b/tests/e2e/tests/read.test.ts deleted file mode 100644 index 25acbc951..000000000 --- a/tests/e2e/tests/read.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { beforeAll, describe, expect, test } from "bun:test"; -import { sepolia } from "thirdweb/chains"; -import type { ApiError } from "../../../sdk/dist/thirdweb-dev-engine.cjs.js"; -import type { setupEngine } from "../utils/engine"; -import { setup } from "./setup"; - -const structContractAddress = "0x83ca896ef0a66d39f0e6fcc1a93c0a09366b85b1"; -const chainIdString = sepolia.id.toString(); - -describe("Read Tests", () => { - let engine: ReturnType; - - beforeAll(async () => { - const { engine: _engine, backendWallet: _backendWallet } = await setup(); - engine = _engine; - }); - - test("Read a contract method with struct and number params", async () => { - const structValues = { - name: "test", - value: 123, - }; - - const structString = JSON.stringify(structValues); - - const { result } = await engine.contract.read( - "readStructAndInts", - chainIdString, - structContractAddress, - `${structString},1,2`, - ); - - expect(result[0]).toEqual("test"); - expect(result[1]).toEqual("123"); - expect(result[2]).toEqual("1"); - expect(result[3]).toEqual("2"); - }); - - test("Incorrectly read a contract should 400 (incorrect arity)", async () => { - const structValues = { - name: "test", - value: 123, - }; - - const structString = JSON.stringify(structValues); - - try { - await engine.contract.read( - "readStructAndInts", - chainIdString, - structContractAddress, - [structString, 1].join(","), - ); - throw new Error("Expected method to throw"); - } catch (error) { - expect((error as ApiError).status).toBe(400); - } - }); -}); diff --git a/tests/e2e/tests/routes/erc1155-transfer.test.ts b/tests/e2e/tests/routes/erc1155-transfer.test.ts deleted file mode 100644 index b2c015700..000000000 --- a/tests/e2e/tests/routes/erc1155-transfer.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { beforeAll, describe, expect, test } from "bun:test"; -import assert from "node:assert"; -import { ZERO_ADDRESS, type Address } from "thirdweb"; -import { CONFIG } from "../../config"; -import { getEngineBackendWalletB, type setupEngine } from "../../utils/engine"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -describe("ER1155 transfer", () => { - let tokenContractAddress: string; - let engine: ReturnType; - let backendWalletA: Address; - let backendWalletB: Address; - - beforeAll(async () => { - const setupRes = await setup(); - engine = setupRes.engine; - backendWalletA = setupRes.backendWallet; - backendWalletB = await getEngineBackendWalletB(engine); - - const deployRes = await engine.deploy.deployEdition( - CONFIG.CHAIN.id.toString(), - backendWalletA, - { - contractMetadata: { - name: "test token", - platform_fee_basis_points: 0, - platform_fee_recipient: ZERO_ADDRESS, - seller_fee_basis_points: 0, - fee_recipient: ZERO_ADDRESS, - symbol: "TT", - trusted_forwarders: [], - }, - }, - ); - assert(deployRes.result.queueId); - console.log("Waiting: deploying contract..."); - await pollTransactionStatus(engine, deployRes.result.queueId, false); - - assert(deployRes.result.deployedAddress, "deployedAddress must be defined"); - tokenContractAddress = deployRes.result.deployedAddress; - - const mintToRes0 = await engine.erc1155.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - receiver: backendWalletA, - metadataWithSupply: { - metadata: "ipfs://test", - supply: "10", - }, - }, - ); - console.log("Waiting: minting token ID 0..."); - await pollTransactionStatus(engine, mintToRes0.result.queueId, false); - - const mintToRes1 = await engine.erc1155.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - receiver: backendWalletB, - metadataWithSupply: { - metadata: "ipfs://test", - supply: "10", - }, - }, - ); - console.log("Waiting: minting token ID 1..."); - await pollTransactionStatus(engine, mintToRes1.result.queueId, false); - }); - - const getBalance = async (walletAddress: Address, tokenId: string) => { - const balanceOfRes = await engine.erc1155.balanceOf( - walletAddress, - tokenId, - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - ); - return balanceOfRes.result ? BigInt(balanceOfRes.result) : 0n; - }; - - test("Calling transfer succeeds", async () => { - const balanceStart = await getBalance(backendWalletA, "0"); - - const transferRes = await engine.erc1155.transfer( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - to: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - tokenId: "0", - amount: "1", - data: "0xabc", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletA, "0"); - expect(balanceStart - balanceEnd).toEqual(1n); - }); - - test("Calling transferFrom succeds after allowance", async () => { - let balanceStart = await getBalance(backendWalletB, "1"); - // Expected to fail. - const transferFromRes = await engine.erc1155.transferFrom( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - from: backendWalletB, - to: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - tokenId: "1", - amount: "1", - data: "0xabc", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferFromRes.result.queueId, false); - - let balanceEnd = await getBalance(backendWalletB, "1"); - expect(balanceStart - balanceEnd).toEqual(0n); - - const setAllowanceRes = await engine.erc1155.setApprovalForAll( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletB, - { - operator: backendWalletA, - approved: true, - }, - ); - await pollTransactionStatus(engine, setAllowanceRes.result.queueId, false); - - balanceStart = await getBalance(backendWalletB, "1"); - const transferFromRes2 = await engine.erc1155.transferFrom( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - from: backendWalletB, - to: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - tokenId: "1", - amount: "1", - data: "0xabc", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferFromRes2.result.queueId, false); - - balanceEnd = await getBalance(backendWalletB, "1"); - expect(balanceStart - balanceEnd).toEqual(1n); - }); -}); diff --git a/tests/e2e/tests/routes/erc20-transfer.test.ts b/tests/e2e/tests/routes/erc20-transfer.test.ts deleted file mode 100644 index 867e1d43b..000000000 --- a/tests/e2e/tests/routes/erc20-transfer.test.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { beforeAll, describe, expect, test } from "bun:test"; -import assert from "node:assert"; -import { ZERO_ADDRESS, toWei, type Address } from "thirdweb"; -import { CONFIG } from "../../config"; -import { getEngineBackendWalletB, type setupEngine } from "../../utils/engine"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -describe("ERC20 transfer", () => { - let tokenContractAddress: string; - let engine: ReturnType; - let backendWalletA: Address; - let backendWalletB: Address; - - beforeAll(async () => { - const setupRes = await setup(); - engine = setupRes.engine; - backendWalletA = setupRes.backendWallet; - backendWalletB = await getEngineBackendWalletB(engine); - - const deployRes = await engine.deploy.deployToken( - CONFIG.CHAIN.id.toString(), - backendWalletA, - { - contractMetadata: { - name: "test token", - platform_fee_basis_points: 0, - platform_fee_recipient: ZERO_ADDRESS, - symbol: "TT", - trusted_forwarders: [], - }, - }, - ); - assert(deployRes.result.queueId); - console.log("Waiting: deploying contract..."); - await pollTransactionStatus(engine, deployRes.result.queueId, false); - - assert(deployRes.result.deployedAddress, "deployedAddress must be defined"); - tokenContractAddress = deployRes.result.deployedAddress; - - const mintToResA = await engine.erc20.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - toAddress: backendWalletA, - amount: "10", - }, - ); - console.log("Waiting: minting tokens..."); - await pollTransactionStatus(engine, mintToResA.result.queueId, false); - - const mintToResB = await engine.erc20.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - toAddress: backendWalletB, - amount: "10", - }, - ); - console.log("Waiting: minting tokens..."); - await pollTransactionStatus(engine, mintToResB.result.queueId, false); - }); - - const getBalance = async (walletAddress: Address) => { - const balanceOfRes = await engine.erc20.balanceOf( - walletAddress, - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - ); - return balanceOfRes.result.value; - }; - - test("Calling transfer succeeds", async () => { - const balanceStart = await getBalance(backendWalletA); - - const transferRes = await engine.erc20.transfer( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - toAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - amount: "2.5", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletA); - expect(BigInt(balanceStart) - BigInt(balanceEnd)).toEqual(toWei("2.5")); - }); - - test("Calling transferFrom succeeds after allowance", async () => { - const setAllowanceRes = await engine.erc20.setAllowance( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletB, - { - spenderAddress: backendWalletA, - amount: "2.5", - }, - ); - await pollTransactionStatus(engine, setAllowanceRes.result.queueId, false); - - const balanceStart = await getBalance(backendWalletB); - const transferFromRes = await engine.erc20.transferFrom( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - fromAddress: backendWalletB, - toAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - amount: "2.5", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferFromRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletB); - expect(BigInt(balanceStart) - BigInt(balanceEnd)).toEqual(toWei("2.5")); - }); - - test("Calling transferFrom fails without allowance", async () => { - const balanceStart = await getBalance(backendWalletB); - // Expected to fail. - const transferFromRes = await engine.erc20.transferFrom( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - fromAddress: backendWalletB, - toAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - amount: "2.5", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferFromRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletB); - expect(BigInt(balanceStart) - BigInt(balanceEnd)).toEqual(0n); - }); -}); diff --git a/tests/e2e/tests/routes/erc721-transfer.test.ts b/tests/e2e/tests/routes/erc721-transfer.test.ts deleted file mode 100644 index c8844467a..000000000 --- a/tests/e2e/tests/routes/erc721-transfer.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { beforeAll, describe, expect, test } from "bun:test"; -import assert from "node:assert"; -import { ZERO_ADDRESS, type Address } from "thirdweb"; -import { CONFIG } from "../../config"; -import { getEngineBackendWalletB, type setupEngine } from "../../utils/engine"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -describe("ERC721 transfer", () => { - let tokenContractAddress: string; - let engine: ReturnType; - let backendWalletA: Address; - let backendWalletB: Address; - - beforeAll(async () => { - const setupRes = await setup(); - engine = setupRes.engine; - backendWalletA = setupRes.backendWallet; - backendWalletB = await getEngineBackendWalletB(engine); - - const deployRes = await engine.deploy.deployNftCollection( - CONFIG.CHAIN.id.toString(), - backendWalletA, - { - contractMetadata: { - name: "test token", - platform_fee_basis_points: 0, - platform_fee_recipient: ZERO_ADDRESS, - seller_fee_basis_points: 0, - fee_recipient: ZERO_ADDRESS, - symbol: "TT", - trusted_forwarders: [], - }, - }, - ); - assert(deployRes.result.queueId); - console.log("Waiting: deploying contract..."); - await pollTransactionStatus(engine, deployRes.result.queueId, false); - - assert(deployRes.result.deployedAddress, "deployedAddress must be defined"); - tokenContractAddress = deployRes.result.deployedAddress; - }); - - const getBalance = async (walletAddress: Address) => { - const balanceOfRes = await engine.erc721.balanceOf( - walletAddress, - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - ); - return balanceOfRes.result ? BigInt(balanceOfRes.result) : 0n; - }; - - test("Calling transfer succeeds", async () => { - const mintToRes = await engine.erc721.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - receiver: backendWalletA, - metadata: "ipfs://test", - }, - ); - console.log("Waiting: minting tokens..."); - await pollTransactionStatus(engine, mintToRes.result.queueId, false); - - const balanceStart = await getBalance(backendWalletA); - const transferRes = await engine.erc721.transfer( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - to: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - tokenId: "0", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletA); - expect(balanceStart - balanceEnd).toEqual(1n); - }); - - test("Calling transferFrom succeeds after allowance", async () => { - const mintToRes = await engine.erc721.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - receiver: backendWalletB, - metadata: "ipfs://test", - }, - ); - console.log("Waiting: minting tokens..."); - await pollTransactionStatus(engine, mintToRes.result.queueId, false); - - const balanceStart = await getBalance(backendWalletB); - const setAllowanceRes = await engine.erc721.setApprovalForToken( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletB, - { - operator: backendWalletA, - tokenId: "1", - }, - ); - await pollTransactionStatus(engine, setAllowanceRes.result.queueId, false); - - const transferFromRes = await engine.erc721.transferFrom( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - from: backendWalletB, - to: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - tokenId: "1", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferFromRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletB); - expect(balanceStart - balanceEnd).toEqual(1n); - }); - - test("Calling transferFrom fails without allowance", async () => { - const mintToRes = await engine.erc721.mintTo( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - receiver: backendWalletB, - metadata: "ipfs://test", - }, - ); - console.log("Waiting: minting tokens..."); - await pollTransactionStatus(engine, mintToRes.result.queueId, false); - - // Expected to fail. - const balanceStart = await getBalance(backendWalletB); - const transferFromRes = await engine.erc721.transferFrom( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWalletA, - { - from: backendWalletB, - to: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - tokenId: "2", - }, - ); - console.log("Waiting: transferring token..."); - await pollTransactionStatus(engine, transferFromRes.result.queueId, false); - - const balanceEnd = await getBalance(backendWalletB); - expect(balanceStart - balanceEnd).toEqual(0n); - }); -}); diff --git a/tests/e2e/tests/routes/sign-message.test.ts b/tests/e2e/tests/routes/sign-message.test.ts deleted file mode 100644 index 0690367d1..000000000 --- a/tests/e2e/tests/routes/sign-message.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { signMessage, toHex } from "thirdweb/utils"; -import { ANVIL_PKEY_A } from "../../utils/wallets"; -import { setup } from "../setup"; - -describe("signMessageRoute", () => { - test("Sign a message (string)", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signMessage(backendWallet, { - message: "hello world", - }); - - const expected = signMessage({ - message: "hello world", - privateKey: ANVIL_PKEY_A, - }); - - expect(res.result).toEqual(expected); - }); - - test("Sign a message (bytes)", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signMessage(backendWallet, { - message: toHex("hello world"), - isBytes: true, - }); - - const expected = signMessage({ - message: "hello world", - privateKey: ANVIL_PKEY_A, - }); - - expect(res.result).toEqual(expected); - }); -}); diff --git a/tests/e2e/tests/routes/signature-prepare.test.ts b/tests/e2e/tests/routes/signature-prepare.test.ts deleted file mode 100644 index 6146a5d96..000000000 --- a/tests/e2e/tests/routes/signature-prepare.test.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { setup } from "../setup"; - -describe("signaturePrepareRoute", () => { - test("Prepare a signature with upload, no uid, no royalty/sale recipients", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.erc721.signaturePrepare( - "84532", - "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4", - { - metadata: { - description: "Test description", - image: "ipfs://...", - name: "My NFT", - attributes: [ - { - trait_type: "test type", - value: "test value", - }, - ], - }, - validityEndTimestamp: 1729194714, - validityStartTimestamp: 1728589914, - to: backendWallet, - }, - ); - - const expected = { - result: { - mintPayload: { - uri: "DO_NOT_ASSERT", - to: backendWallet, - price: "0", - currency: "0x0000000000000000000000000000000000000000", - primarySaleRecipient: "0xa5B8492D8223D255dB279C7c3ebdA34Be5eC9D85", - royaltyRecipient: "0xa5B8492D8223D255dB279C7c3ebdA34Be5eC9D85", - royaltyBps: "0", - validityStartTimestamp: 1728589914, - validityEndTimestamp: 1729194714, - uid: "DO_NOT_ASSERT", - }, - typedDataPayload: { - domain: { - name: "TokenERC721", - version: "1", - chainId: 84532, - verifyingContract: "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4", - }, - types: { - EIP712Domain: [ - { - name: "name", - type: "string", - }, - { - name: "version", - type: "string", - }, - { - name: "chainId", - type: "uint256", - }, - { - name: "verifyingContract", - type: "address", - }, - ], - MintRequest: [ - { - name: "to", - type: "address", - }, - { - name: "royaltyRecipient", - type: "address", - }, - { - name: "royaltyBps", - type: "uint256", - }, - { - name: "primarySaleRecipient", - type: "address", - }, - { - name: "uri", - type: "string", - }, - { - name: "price", - type: "uint256", - }, - { - name: "currency", - type: "address", - }, - { - name: "validityStartTimestamp", - type: "uint128", - }, - { - name: "validityEndTimestamp", - type: "uint128", - }, - { - name: "uid", - type: "bytes32", - }, - ], - }, - message: { - uri: "DO_NOT_ASSERT", - to: backendWallet, - price: "0", - currency: "0x0000000000000000000000000000000000000000", - primarySaleRecipient: "0xa5B8492D8223D255dB279C7c3ebdA34Be5eC9D85", - royaltyRecipient: "0xa5B8492D8223D255dB279C7c3ebdA34Be5eC9D85", - royaltyBps: "0", - validityStartTimestamp: 1728589914, - validityEndTimestamp: 1729194714, - uid: "DO_NOT_ASSERT", - }, - primaryType: "MintRequest" as const, - }, - }, - }; - - // These fields are dynamic, do not assert them. - expected.result.mintPayload.uri = res.result.mintPayload.uri; - expected.result.typedDataPayload.message.uri = res.result.mintPayload.uri; - expected.result.mintPayload.uid = res.result.mintPayload.uid; - expected.result.typedDataPayload.message.uid = res.result.mintPayload.uid; - - expect(res).toEqual(expected); - }); - - test("Prepare a signature with provided hex uid", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.erc721.signaturePrepare( - "84532", - "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4", - { - metadata: "ipfs://...", - validityEndTimestamp: 1729194714, - validityStartTimestamp: 1728589914, - to: backendWallet, - uid: "0x25d29226fc7c310ed308c1eea8a3ed2d9f660d873ba6348b6649da4cae3877a4", - }, - ); - - expect(res.result.mintPayload.uid).toEqual( - "0x25d29226fc7c310ed308c1eea8a3ed2d9f660d873ba6348b6649da4cae3877a4", - ); - }); - - test("Prepare a signature with string uid", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.erc721.signaturePrepare( - "84532", - "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4", - { - metadata: "ipfs://...", - validityEndTimestamp: 1729194714, - validityStartTimestamp: 1728589914, - to: backendWallet, - uid: "my-really-long-test-uuid-my-really-long-test-uuid-my-really-long-test-uuid", - }, - ); - - expect(res.result.mintPayload.uid).toEqual( - "0xa74a3badce5090a5afead99c9d80e08169468a2442a6f79692001aed81acf2bc", - ); - }); - - test("Prepare a signature with invalid hex uid", async () => { - const { engine, backendWallet } = await setup(); - - let threw = false; - try { - await engine.erc721.signaturePrepare( - "84532", - "0x5002e3bF97F376Fe0480109e26c0208786bCDDd4", - { - metadata: "ipfs://...", - validityEndTimestamp: 1729194714, - validityStartTimestamp: 1728589914, - to: backendWallet, - uid: "0x25d29226fc7c310ed308c1eea8a3ed2d", - }, - ); - } catch { - threw = true; - } - - expect(threw).toBeTrue(); - }); -}); diff --git a/tests/e2e/tests/routes/write.test.ts b/tests/e2e/tests/routes/write.test.ts deleted file mode 100644 index 68e9db9de..000000000 --- a/tests/e2e/tests/routes/write.test.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { beforeAll, describe, expect, test } from "bun:test"; -import assert from "node:assert"; -import { stringToHex, type Address } from "thirdweb"; -import { zeroAddress } from "viem"; -import type { ApiError } from "../../../../sdk/dist/thirdweb-dev-engine.cjs.js"; -import { CONFIG } from "../../config.js"; -import type { setupEngine } from "../../utils/engine.js"; -import { pollTransactionStatus } from "../../utils/transactions.js"; -import { setup } from "../setup.js"; - -describe("/contract/write route", () => { - let tokenContractAddress: string; - let engine: ReturnType; - let backendWallet: Address; - - beforeAll(async () => { - const { engine: _engine, backendWallet: _backendWallet } = await setup(); - engine = _engine; - backendWallet = _backendWallet as Address; - - const res = await engine.deploy.deployToken( - CONFIG.CHAIN.id.toString(), - backendWallet, - { - contractMetadata: { - name: "test token", - platform_fee_basis_points: 0, - platform_fee_recipient: zeroAddress, - symbol: "TT", - trusted_forwarders: [], - }, - }, - ); - - expect(res.result.queueId).toBeDefined(); - assert(res.result.queueId, "queueId must be defined"); - expect(res.result.deployedAddress).toBeDefined(); - - const transactionStatus = await pollTransactionStatus( - engine, - res.result.queueId, - true, - ); - - expect(transactionStatus.minedAt).toBeDefined(); - assert(res.result.deployedAddress, "deployedAddress must be defined"); - tokenContractAddress = res.result.deployedAddress; - }); - - test("Write to a contract with function name", async () => { - const writeRes = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWallet, - { - functionName: "setContractURI", - args: ["https://test.com/"], - }, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Write to a contract with untyped args", async () => { - const res = await engine.deploy.deployNftDrop( - CONFIG.CHAIN.id.toString(), - backendWallet, - { - contractMetadata: { - name: "test token", - platform_fee_basis_points: 0, - platform_fee_recipient: zeroAddress, - symbol: "TT", - trusted_forwarders: [], - seller_fee_basis_points: 0, - fee_recipient: zeroAddress, - }, - }, - ); - - expect(res.result.queueId).toBeDefined(); - assert(res.result.queueId, "queueId must be defined"); - expect(res.result.deployedAddress).toBeDefined(); - const nftDropContractAddress = res.result.deployedAddress; - - if (!nftDropContractAddress) { - throw new Error("nftDropContractAddress must be defined"); - } - - const transactionStatus = await pollTransactionStatus( - engine, - res.result.queueId, - true, - ); - - expect(transactionStatus.minedAt).toBeDefined(); - const writeRes = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - nftDropContractAddress, - backendWallet, - { - functionName: "setApprovalForAll", - args: [ - "0x1234567890123456789012345678901234567890", - "true", // string instead of bool - ], - }, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - - const writeRes2 = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - nftDropContractAddress, - backendWallet, - { - functionName: "setClaimConditions", - args: [ - // stringified array of structs - JSON.stringify([ - { - startTimestamp: "0", - maxClaimableSupply: "100000", - supplyClaimed: "0", - quantityLimitPerWallet: "10", - merkleRoot: stringToHex("", { size: 32 }), - pricePerToken: "0", - currency: zeroAddress, - metadata: "", - }, - ]), - "false", - ], - }, - ); - - expect(writeRes2.result.queueId).toBeDefined(); - - const writeTransactionStatus2 = await pollTransactionStatus( - engine, - writeRes2.result.queueId, - true, - ); - - expect(writeTransactionStatus2.minedAt).toBeDefined(); - }); - - test("Write to a contract with function signature", async () => { - const writeRes = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWallet, - { - functionName: "function setContractURI(string uri)", - args: ["https://signature-test.com/"], - }, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Write to a contract with function signature without prefix", async () => { - const writeRes = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWallet, - { - functionName: "setContractURI(string uri)", - args: ["https://signature-test.com/"], - }, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Write to a contract with function abi", async () => { - const writeRes = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWallet, - { - functionName: "setContractURI", - args: ["https://abi-test.com/"], - abi: [ - { - inputs: [ - { - name: "uri", - type: "string", - }, - ], - name: "setContractURI", - stateMutability: "nonpayable", - type: "function", - outputs: [], - }, - ], - }, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Write to a contract with non-standard abi", async () => { - const writeRes = await engine.contract.write( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWallet, - { - functionName: "setContractURI", - args: ["https://abi-test.com/"], - abi: [ - { - inputs: [ - { - name: "uri", - type: "string", - }, - ], - name: "setContractURI", - stateMutability: "nonpayable", - type: "function", - // Omitted - // outputs: [], - }, - ], - }, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Should throw error if function name is not found", async () => { - try { - await engine.contract.write( - CONFIG.CHAIN.id.toString(), - tokenContractAddress, - backendWallet, - { - functionName: "nonExistentFunction", - args: [""], - }, - ); - } catch (e) { - expect((e as ApiError).body?.error?.message).toBe( - `could not find function with name "nonExistentFunction" in abi`, - ); - } - }); -}); diff --git a/tests/e2e/tests/setup.ts b/tests/e2e/tests/setup.ts deleted file mode 100644 index 0be24b7f7..000000000 --- a/tests/e2e/tests/setup.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { env, sleep } from "bun"; -import { afterAll, beforeAll } from "bun:test"; -import { - createChain, - getEngineBackendWallet, - setupEngine, -} from "../utils/engine"; - -import { createThirdwebClient, type Address } from "thirdweb"; -import { CONFIG } from "../config"; -import { startAnvil, stopAnvil } from "../utils/anvil"; - -type SetupResult = { - engine: ReturnType; - backendWallet: Address; - thirdwebClient: ReturnType; -}; - -let cachedSetup: SetupResult | null = null; - -export const setup = async (): Promise => { - if (cachedSetup) { - return cachedSetup; - } - - const engine = setupEngine(); - const backendWallet = await getEngineBackendWallet(engine); - await engine.backendWallet.resetNonces({}); - - if (!env.THIRDWEB_API_SECRET_KEY) - throw new Error("THIRDWEB_API_SECRET_KEY is not set"); - - const thirdwebClient = createThirdwebClient({ - secretKey: env.THIRDWEB_API_SECRET_KEY, - }); - - if (CONFIG.USE_LOCAL_CHAIN) { - startAnvil(); - - await createChain(engine); - await sleep(1000); // wait for chain to start producing blocks - } - - cachedSetup = { engine, backendWallet, thirdwebClient }; - return cachedSetup; -}; - -// Run setup once before all tests -beforeAll(async () => { - await setup(); -}); - -afterAll(async () => { - await stopAnvil(); -}); diff --git a/tests/e2e/tests/sign-transaction.test.ts b/tests/e2e/tests/sign-transaction.test.ts deleted file mode 100644 index 7dabab5d7..000000000 --- a/tests/e2e/tests/sign-transaction.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { setup } from "./setup"; - -describe("signTransaction route", () => { - test("Sign a legacy transaction", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signTransaction(backendWallet, { - transaction: { - type: 0, - chainId: 1, - to: "0x000000000000000000000000000000000000dead", - nonce: "42", - gasLimit: "88000", - gasPrice: "2000000000", - value: "100000000000000000", - }, - }); - - expect(res.result).toEqual( - "0xf86c2a8477359400830157c094152e208d08cd3ea1aa5d179b2e3eba7d1a733ef488016345785d8a00008026a05da3d31d9cfbb4026b6e187c81952199d567e182d9c2ecc72acf98e4e6ce4875a03b2815b79881092ab5a4f74e6725081d652becad8495b815c14abb56cc782041", - ); - }); - - test("Sign an eip-1559 transaction", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signTransaction(backendWallet, { - transaction: { - type: 1, - chainId: 137, - to: "0x000000000000000000000000000000000000dead", - nonce: "42", - gasLimit: "88000", - maxFeePerGas: "2000000000", - maxPriorityFeePerGas: "200000000", - value: "100000000000000000", - accessList: [ - { - address: "0x000000000000000000000000000000000000dead", - storageKeys: [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - }, - ], - }, - }); - - expect(res.result).toEqual( - "0x02f8ad81892a840bebc2008477359400830157c094152e208d08cd3ea1aa5d179b2e3eba7d1a733ef488016345785d8a000080f838f794152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4e1a0000000000000000000000000000000000000000000000000000000000000000180a050fd32589ec2e2b49b3bce79d9420474115490ea0693ada75a62d003c6ada1aaa06fbc93d08a7604fbca5c31af92a662ff6be3b5a9f75214b7cd5db5feab2fc444", - ); - }); - - test("Sign an eip-2930 transaction", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signTransaction(backendWallet, { - transaction: { - type: 2, - chainId: 137, - to: "0x000000000000000000000000000000000000dead", - nonce: "42", - gasLimit: "88000", - value: "100000000000000000", - accessList: [ - { - address: "0x000000000000000000000000000000000000dead", - storageKeys: [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - }, - ], - }, - }); - - expect(res.result).toEqual( - "0x01f8a481892a80830157c094152e208d08cd3ea1aa5d179b2e3eba7d1a733ef488016345785d8a000080f838f794152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4e1a0000000000000000000000000000000000000000000000000000000000000000101a0f690bdfb3b8431125dcb77933d3ebb0e5ae05bbd04ad83fa47b2f524013d4c0aa0096ca32df9a7586a4a11ebb72ce8e1902d633976a56ca184ae5009ae53c6bd16", - ); - }); - - test("Sign an eip-4844 transaction", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signTransaction(backendWallet, { - transaction: { - type: 3, - chainId: 137, - to: "0x000000000000000000000000000000000000dead", - nonce: "42", - gasLimit: "88000", - maxFeePerGas: "2000000000", - maxPriorityFeePerGas: "200000000", - value: "100000000000000000", - accessList: [ - { - address: "0x000000000000000000000000000000000000dead", - storageKeys: [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - }, - ], - }, - }); - - expect(res.result).toEqual( - "0x03f8af81892a840bebc2008477359400830157c094152e208d08cd3ea1aa5d179b2e3eba7d1a733ef488016345785d8a000080f838f794152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4e1a0000000000000000000000000000000000000000000000000000000000000000180c001a0ec4fd401847092409ffb584cc34e816a322d0bc20f3599b4fe0a0182947fe5bea048daaf620c8b765c07b16ba083c457a90fa54062039d5d1c484e81d1577cc642", - ); - }); - - test("Sign an eip-7702 transaction", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.signTransaction(backendWallet, { - transaction: { - type: 4, - chainId: 137, - to: "0x000000000000000000000000000000000000dead", - nonce: "42", - gasLimit: "88000", - maxFeePerGas: "2000000000", - maxPriorityFeePerGas: "200000000", - value: "100000000000000000", - accessList: [ - { - address: "0x000000000000000000000000000000000000dead", - storageKeys: [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - ], - }, - ], - customData: { - someCustomField: "customValue", - }, - }, - }); - - expect(res.result).toEqual( - "0x04f8ae81892a840bebc2008477359400830157c094152e208d08cd3ea1aa5d179b2e3eba7d1a733ef488016345785d8a000080f838f794152e208d08cd3ea1aa5d179b2e3eba7d1a733ef4e1a00000000000000000000000000000000000000000000000000000000000000001c080a028b866bcf94201d63d71d46505a17a9341d2c7c0f25f98f8e99d5a045b6dd342a03e8807e857830b3e09b300a87c7fedacecc81c3e2222a017be2e0573be011977", - ); - }); -}); diff --git a/tests/e2e/tests/smart-backend-wallet/smart-aws-wallet.test.ts b/tests/e2e/tests/smart-backend-wallet/smart-aws-wallet.test.ts deleted file mode 100644 index 398a1e253..000000000 --- a/tests/e2e/tests/smart-backend-wallet/smart-aws-wallet.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { ZERO_ADDRESS } from "thirdweb"; -import { arbitrumSepolia } from "thirdweb/chains"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -const chain = arbitrumSepolia.id.toString(); - -describe("smart aws-kms wallet", () => { - let smartWalletAddress: string | undefined; - let tokenAddress: string | undefined; - - const getSmartWalletAddress = () => { - if (!smartWalletAddress) { - throw new Error("Smart wallet address not set"); - } - return smartWalletAddress; - }; - - const getTokenAddress = () => { - if (!tokenAddress) { - throw new Error("Token address not set"); - } - return tokenAddress; - }; - - test("Create an aws-kms smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.create({ - type: "smart:aws-kms", - label: "test", - }); - - expect(res.result.status).toEqual("success"); - expect(res.result.type).toEqual("smart:aws-kms"); - expect(res.result.walletAddress).toBeDefined(); - - smartWalletAddress = res.result.walletAddress; - }); - - test("Send a SDK v5 Transaction (sendTransaction noop)", async () => { - const { engine } = await setup(); - const res = await engine.backendWallet.sendTransaction( - chain, - getSmartWalletAddress(), - { - data: "0x", - value: "0", - toAddress: ZERO_ADDRESS, - }, - ); - - await pollTransactionStatus(engine, res.result.queueId); - - const status = await engine.transaction.status(res.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - expect(status.result.status).toEqual("mined"); - }); - - test("Send a SDK v4 Transaction (deploy ERC20)", async () => { - const { engine } = await setup(); - - const deployRes = await engine.deploy.deployToken( - chain, - getSmartWalletAddress(), - { - contractMetadata: { - name: "Test", - symbol: "TST", - platform_fee_basis_points: 0, - platform_fee_recipient: getSmartWalletAddress(), - trusted_forwarders: [], - }, - }, - ); - - const { queueId: deployQueueId, deployedAddress } = deployRes.result; - - if (!deployedAddress || !deployQueueId) { - throw new Error("Deploy failed"); - } - - tokenAddress = deployedAddress; - await pollTransactionStatus(engine, deployQueueId); - - const mintRes = await engine.erc20.mintTo( - chain, - deployedAddress, - getSmartWalletAddress(), - { - amount: "1000", - toAddress: getSmartWalletAddress(), - }, - ); - - await pollTransactionStatus(engine, mintRes.result.queueId); - const status = await engine.transaction.status(mintRes.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const balance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chain, - deployedAddress, - ); - - expect(Number(balance.result.displayValue)).toEqual(1000); - }); - - test("Send a SDK v5 Transaction (transfer ERC20)", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.erc20.transfer( - chain, - getTokenAddress(), - getSmartWalletAddress(), - { - amount: "100", - toAddress: backendWallet, - }, - ); - - await pollTransactionStatus(engine, res.result.queueId); - const status = await engine.transaction.status(res.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const smartWalletBalance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chain, - getTokenAddress(), - ); - - const backendWalletBalance = await engine.erc20.balanceOf( - backendWallet, - chain, - getTokenAddress(), - ); - - expect(Number(smartWalletBalance.result.displayValue)).toEqual(900); - expect(Number(backendWalletBalance.result.displayValue)).toEqual(100); - }); - - test("Delete aws-kms smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.removeBackendWallet( - getSmartWalletAddress(), - ); - expect(res.result.status).toEqual("success"); - }); -}); diff --git a/tests/e2e/tests/smart-backend-wallet/smart-gcp-wallet.test.ts b/tests/e2e/tests/smart-backend-wallet/smart-gcp-wallet.test.ts deleted file mode 100644 index da45b0ba6..000000000 --- a/tests/e2e/tests/smart-backend-wallet/smart-gcp-wallet.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { ZERO_ADDRESS } from "thirdweb"; -import { arbitrumSepolia } from "thirdweb/chains"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -const chain = arbitrumSepolia.id.toString(); - -describe("smart gcp-kms wallet", () => { - let smartWalletAddress: string | undefined; - let tokenAddress: string | undefined; - - const getSmartWalletAddress = () => { - if (!smartWalletAddress) { - throw new Error("Smart wallet address not set"); - } - return smartWalletAddress; - }; - - const getTokenAddress = () => { - if (!tokenAddress) { - throw new Error("Token address not set"); - } - return tokenAddress; - }; - - test("Create a gcp-kms smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.create({ - type: "smart:gcp-kms", - label: "test", - }); - - expect(res.result.status).toEqual("success"); - expect(res.result.type).toEqual("smart:gcp-kms"); - expect(res.result.walletAddress).toBeDefined(); - - smartWalletAddress = res.result.walletAddress; - }); - - test("Send a SDK v5 Transaction (sendTransaction noop)", async () => { - const { engine } = await setup(); - const res = await engine.backendWallet.sendTransaction( - chain, - getSmartWalletAddress(), - { - data: "0x", - value: "0", - toAddress: ZERO_ADDRESS, - }, - ); - - await pollTransactionStatus(engine, res.result.queueId); - - const status = await engine.transaction.status(res.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - expect(status.result.status).toEqual("mined"); - }); - - test("Send a SDK v4 Transaction (deploy ERC20)", async () => { - const { engine } = await setup(); - - const deployRes = await engine.deploy.deployToken( - chain, - getSmartWalletAddress(), - { - contractMetadata: { - name: "Test", - symbol: "TST", - platform_fee_basis_points: 0, - platform_fee_recipient: getSmartWalletAddress(), - trusted_forwarders: [], - }, - }, - ); - - const { queueId: deployQueueId, deployedAddress } = deployRes.result; - - if (!deployedAddress || !deployQueueId) { - throw new Error("Deploy failed"); - } - - tokenAddress = deployedAddress; - await pollTransactionStatus(engine, deployQueueId); - - const mintRes = await engine.erc20.mintTo( - chain, - deployedAddress, - getSmartWalletAddress(), - { - amount: "1000", - toAddress: getSmartWalletAddress(), - }, - ); - - await pollTransactionStatus(engine, mintRes.result.queueId); - const status = await engine.transaction.status(mintRes.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const balance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chain, - deployedAddress, - ); - - expect(Number(balance.result.displayValue)).toEqual(1000); - }); - - test("Send a SDK v5 Transaction (transfer ERC20)", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.erc20.transfer( - chain, - getTokenAddress(), - getSmartWalletAddress(), - { - amount: "100", - toAddress: backendWallet, - }, - ); - - await pollTransactionStatus(engine, res.result.queueId); - const status = await engine.transaction.status(res.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const smartWalletBalance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chain, - getTokenAddress(), - ); - - const backendWalletBalance = await engine.erc20.balanceOf( - backendWallet, - chain, - getTokenAddress(), - ); - - expect(Number(smartWalletBalance.result.displayValue)).toEqual(900); - expect(Number(backendWalletBalance.result.displayValue)).toEqual(100); - }); - - test("Delete gcp-kms smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.removeBackendWallet( - getSmartWalletAddress(), - ); - expect(res.result.status).toEqual("success"); - }); -}); diff --git a/tests/e2e/tests/smart-backend-wallet/smart-local-wallet-sdk-v4.test.ts b/tests/e2e/tests/smart-backend-wallet/smart-local-wallet-sdk-v4.test.ts deleted file mode 100644 index 8ce0191a3..000000000 --- a/tests/e2e/tests/smart-backend-wallet/smart-local-wallet-sdk-v4.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { arbitrumSepolia } from "thirdweb/chains"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -const chain = arbitrumSepolia; -const chainId = chain.id.toString(); - -describe("smart local wallet (test succesfull deploy with SDKv4)", () => { - let smartWalletAddress: string | undefined; - - const getSmartWalletAddress = () => { - if (!smartWalletAddress) { - throw new Error("Smart wallet address not set"); - } - return smartWalletAddress; - }; - - test("Create a local smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.create({ - type: "smart:local", - label: "test", - }); - - expect(res.result.status).toEqual("success"); - expect(res.result.type).toEqual("smart:local"); - expect(res.result.walletAddress).toBeDefined(); - - smartWalletAddress = res.result.walletAddress; - }); - - test("Send a SDK v4 Transaction (deploy ERC20)", async () => { - const { engine } = await setup(); - - const deployRes = await engine.deploy.deployToken( - chainId, - getSmartWalletAddress(), - { - contractMetadata: { - name: "Test", - symbol: "TST", - platform_fee_basis_points: 0, - platform_fee_recipient: getSmartWalletAddress(), - trusted_forwarders: [], - }, - }, - ); - - const { queueId: deployQueueId, deployedAddress } = deployRes.result; - - if (!deployedAddress || !deployQueueId) { - throw new Error("Deploy failed"); - } - - await pollTransactionStatus(engine, deployQueueId); - - const mintRes = await engine.erc20.mintTo( - chainId, - deployedAddress, - getSmartWalletAddress(), - { - amount: "1000", - toAddress: getSmartWalletAddress(), - }, - ); - - await pollTransactionStatus(engine, mintRes.result.queueId); - const status = await engine.transaction.status(mintRes.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const balance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chainId, - deployedAddress, - ); - - expect(Number(balance.result.displayValue)).toEqual(1000); - }); - - test("Delete local smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.removeBackendWallet( - getSmartWalletAddress(), - ); - expect(res.result.status).toEqual("success"); - }); -}); diff --git a/tests/e2e/tests/smart-backend-wallet/smart-local-wallet.test.ts b/tests/e2e/tests/smart-backend-wallet/smart-local-wallet.test.ts deleted file mode 100644 index 6ed97a1f6..000000000 --- a/tests/e2e/tests/smart-backend-wallet/smart-local-wallet.test.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { ZERO_ADDRESS } from "thirdweb"; -import { verifyContractWalletSignature } from "thirdweb/auth"; -import { arbitrumSepolia } from "thirdweb/chains"; -import { pollTransactionStatus } from "../../utils/transactions"; -import { setup } from "../setup"; - -const chain = arbitrumSepolia; -const chainId = chain.id.toString(); -const message = "test"; - -describe("smart local wallet", () => { - let smartWalletAddress: string | undefined; - let tokenAddress: string | undefined; - - const getSmartWalletAddress = () => { - if (!smartWalletAddress) { - throw new Error("Smart wallet address not set"); - } - return smartWalletAddress; - }; - - const getTokenAddress = () => { - if (!tokenAddress) { - throw new Error("Token address not set"); - } - return tokenAddress; - }; - - test("Create a local smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.create({ - type: "smart:local", - label: "test", - }); - - expect(res.result.status).toEqual("success"); - expect(res.result.type).toEqual("smart:local"); - expect(res.result.walletAddress).toBeDefined(); - - smartWalletAddress = res.result.walletAddress; - }); - - test("Sign message", async () => { - const { engine, thirdwebClient } = await setup(); - - const res = await engine.backendWallet.signMessage( - getSmartWalletAddress(), - { - message, - isBytes: false, - chainId: chain.id, - }, - ); - - const signature = res.result; - - const valid = await verifyContractWalletSignature({ - address: getSmartWalletAddress(), - chain, - client: thirdwebClient, - message, - signature: signature, - }); - - expect(valid).toBeTruthy(); - }); - - test("Send a SDK v5 Transaction (sendTransaction noop)", async () => { - const { engine } = await setup(); - const res = await engine.backendWallet.sendTransaction( - chainId, - getSmartWalletAddress(), - { - data: "0x", - value: "0", - toAddress: ZERO_ADDRESS, - }, - ); - - await pollTransactionStatus(engine, res.result.queueId); - - const status = await engine.transaction.status(res.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - expect(status.result.status).toEqual("mined"); - }); - - test("Send a SDK v4 Transaction (deploy ERC20)", async () => { - const { engine } = await setup(); - - const deployRes = await engine.deploy.deployToken( - chainId, - getSmartWalletAddress(), - { - contractMetadata: { - name: "Test", - symbol: "TST", - platform_fee_basis_points: 0, - platform_fee_recipient: getSmartWalletAddress(), - trusted_forwarders: [], - }, - }, - ); - - const { queueId: deployQueueId, deployedAddress } = deployRes.result; - - if (!deployedAddress || !deployQueueId) { - throw new Error("Deploy failed"); - } - - tokenAddress = deployedAddress; - await pollTransactionStatus(engine, deployQueueId); - - const mintRes = await engine.erc20.mintTo( - chainId, - deployedAddress, - getSmartWalletAddress(), - { - amount: "1000", - toAddress: getSmartWalletAddress(), - }, - ); - - await pollTransactionStatus(engine, mintRes.result.queueId); - const status = await engine.transaction.status(mintRes.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const balance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chainId, - deployedAddress, - ); - - expect(Number(balance.result.displayValue)).toEqual(1000); - }); - - test("Send a SDK v5 Transaction (transfer ERC20)", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.erc20.transfer( - chainId, - getTokenAddress(), - getSmartWalletAddress(), - { - amount: "100", - toAddress: backendWallet, - }, - ); - - await pollTransactionStatus(engine, res.result.queueId); - const status = await engine.transaction.status(res.result.queueId); - expect(status.result.accountAddress).toEqual(getSmartWalletAddress()); - - const smartWalletBalance = await engine.erc20.balanceOf( - getSmartWalletAddress(), - chainId, - getTokenAddress(), - ); - - const backendWalletBalance = await engine.erc20.balanceOf( - backendWallet, - chainId, - getTokenAddress(), - ); - - expect(Number(smartWalletBalance.result.displayValue)).toEqual(900); - expect(Number(backendWalletBalance.result.displayValue)).toEqual(100); - }); - - test("Delete local smart backend wallet", async () => { - const { engine } = await setup(); - - const res = await engine.backendWallet.removeBackendWallet( - getSmartWalletAddress(), - ); - expect(res.result.status).toEqual("success"); - }); -}); diff --git a/tests/e2e/tests/smoke.test.ts b/tests/e2e/tests/smoke.test.ts deleted file mode 100644 index 2e1e1e31b..000000000 --- a/tests/e2e/tests/smoke.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { CONFIG } from "../config"; -import { pollTransactionStatus } from "../utils/transactions"; -import { setup } from "./setup"; - -describe("Smoke Test", () => { - test("Send NoOp Transaction", async () => { - const { engine, backendWallet } = await setup(); - - const res = await engine.backendWallet.transfer( - CONFIG.CHAIN.id.toString(), - backendWallet, - { - amount: "0", - to: backendWallet, - }, - ); - - const transactionStatus = await pollTransactionStatus( - engine, - res.result.queueId, - true, - ); - - expect(transactionStatus.minedAt).toBeDefined(); - console.log("Transaction mined"); - }); -}); diff --git a/tests/e2e/tests/userop.test.ts b/tests/e2e/tests/userop.test.ts deleted file mode 100644 index 875231e67..000000000 --- a/tests/e2e/tests/userop.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { beforeAll, describe, expect, test } from "bun:test"; -import { randomBytes } from "node:crypto"; -import { getAddress, type Address } from "thirdweb"; -import { sepolia } from "thirdweb/chains"; -import { DEFAULT_ACCOUNT_FACTORY_V0_6 } from "thirdweb/wallets/smart"; -import type { ApiError } from "../../../sdk/dist/declarations/src/core/ApiError"; -import type { setupEngine } from "../utils/engine"; -import { pollTransactionStatus } from "../utils/transactions"; -import { setup } from "./setup"; - -describe("Userop Tests", () => { - let engine: ReturnType; - let backendWallet: Address; - let accountAddress: Address; - - const accountFactoryAddress = DEFAULT_ACCOUNT_FACTORY_V0_6; - - beforeAll(async () => { - const { engine: _engine, backendWallet: _backendWallet } = await setup(); - engine = _engine; - backendWallet = _backendWallet as Address; - - const addr = await engine.accountFactory.predictAccountAddress( - backendWallet, - sepolia.id.toString(), - accountFactoryAddress, - ); - - accountAddress = getAddress(addr.result); - }); - - test("Should send a nft claim userop", async () => { - const writeRes = await engine.erc1155.claimTo( - sepolia.id.toString(), - "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8", - backendWallet, - { - quantity: "1", - receiver: accountAddress, - tokenId: "0", - }, - false, - undefined, - accountAddress, - accountFactoryAddress, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Should send a nft claim userop with undeployed account with salt", async () => { - const accountSalt = `user-${randomBytes(32).toString("hex")}`; - const predictedAddress = await engine.accountFactory.predictAccountAddress( - backendWallet, - sepolia.id.toString(), - accountFactoryAddress, - accountSalt, - ); - - const userAddress = getAddress(predictedAddress.result); - console.log("userAddress", userAddress); - - const writeRes = await engine.erc1155.claimTo( - sepolia.id.toString(), - "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8", - backendWallet, - { - quantity: "1", - receiver: userAddress, - tokenId: "0", - }, - false, - undefined, - userAddress, - accountFactoryAddress, - accountSalt, - ); - - expect(writeRes.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - writeRes.result.queueId, - true, - ); - - expect(writeTransactionStatus.minedAt).toBeDefined(); - }); - - test("Should throw decoded error with simulate false", async () => { - const res = await engine.contractRoles.grant( - sepolia.id.toString(), - "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8", - backendWallet, - { - address: accountAddress, - role: "minter", - }, - false, - undefined, - accountAddress, - accountFactoryAddress, - ); - - expect(res.result.queueId).toBeDefined(); - - const writeTransactionStatus = await pollTransactionStatus( - engine, - res.result.queueId, - true, - ); - - expect(writeTransactionStatus.errorMessage).toBe( - `Error - Permissions: account ${accountAddress.toLowerCase()} is missing role 0x0000000000000000000000000000000000000000000000000000000000000000`, - ); - }); - - test("Should throw decoded error with simulate true", async () => { - try { - await engine.contractRoles.grant( - sepolia.id.toString(), - "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8", - backendWallet, - { - address: accountAddress, - role: "minter", - }, - true, - undefined, - accountAddress, - accountFactoryAddress, - ); - } catch (e) { - expect((e as ApiError).body?.error?.message).toBe( - `Simulation failed: TransactionError: Error - Permissions: account ${accountAddress.toLowerCase()} is missing role 0x0000000000000000000000000000000000000000000000000000000000000000`, - ); - } - }); -}); diff --git a/tests/e2e/tests/utils/get-block-time.test.ts b/tests/e2e/tests/utils/get-block-time.test.ts deleted file mode 100644 index 1e8124bcd..000000000 --- a/tests/e2e/tests/utils/get-block-time.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, expect, test } from "bun:test"; -import { polygon } from "thirdweb/chains"; -import { getBlockTimeSeconds } from "../../../../src/utils/indexer/getBlockTime"; - -describe("getBlockTimeSeconds", () => { - test("Returns roughly 2 seconds for Polygon", async () => { - const result = await getBlockTimeSeconds(polygon.id, 100); - // May be off slightly due to not having subsecond granularity. - expect(Math.round(result)).toEqual(2); - }); -}); diff --git a/tests/e2e/tsconfig.json b/tests/e2e/tsconfig.json deleted file mode 100644 index 238655f2c..000000000 --- a/tests/e2e/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - // Enable latest features - "lib": ["ESNext", "DOM"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, - - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - - // Best practices - "strict": true, - "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false - } -} diff --git a/tests/e2e/utils/anvil.ts b/tests/e2e/utils/anvil.ts deleted file mode 100644 index 57f00be76..000000000 --- a/tests/e2e/utils/anvil.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createServer, type CreateServerReturnType } from "prool"; -import { anvil } from "prool/instances"; - -let server: CreateServerReturnType | undefined; - -export const startAnvil = async () => { - console.log("Starting Anvil server..."); - const server = createServer({ - instance: anvil(), - port: 8545, - }); - await server.start(); -}; - -export const stopAnvil = async () => { - if (server) { - console.log("Stopping Anvil server..."); - await server.stop(); - } -}; diff --git a/tests/e2e/utils/engine.ts b/tests/e2e/utils/engine.ts deleted file mode 100644 index b4bdede4f..000000000 --- a/tests/e2e/utils/engine.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { checksumAddress } from "thirdweb/utils"; -import { Engine } from "../../../sdk/dist/thirdweb-dev-engine.cjs"; -import { CONFIG } from "../config"; -import { ANVIL_PKEY_A, ANVIL_PKEY_B } from "./wallets"; - -export const setupEngine = () => { - return new Engine({ - accessToken: CONFIG.ACCESS_TOKEN, - url: CONFIG.URL, - }); -}; - -export const createChain = async (engine: Engine) => { - if (!CONFIG.USE_LOCAL_CHAIN) return; - - const chains = await engine.configuration.getChainsConfiguration(); - - if (chains.result) { - const parsedChains = chains.result; - if (parsedChains.find((chain) => chain.chainId === CONFIG.CHAIN.id)) { - console.log("Anvil chain already exists in engine"); - return; - } - } - - await engine.configuration.updateChainsConfiguration({ - chainOverrides: [ - { - chain: CONFIG.CHAIN.name || "Anvil", - chainId: CONFIG.CHAIN.id, - name: "Anvil", - nativeCurrency: { - decimals: 18, - name: "Anvil Ether", - symbol: "ETH", - }, - rpc: [CONFIG.CHAIN.rpc], - slug: "anvil", - }, - ], - }); - - console.log("Added anvil chain to engine"); -}; - -export const getEngineBackendWallet = async (engine: Engine) => { - const { result } = await engine.backendWallet.import({ - label: "Anvil test wallet A", - privateKey: ANVIL_PKEY_A, - }); - return checksumAddress(result.walletAddress); -}; - -export const getEngineBackendWalletB = async (engine: Engine) => { - const { result } = await engine.backendWallet.import({ - label: "Anvil test wallet B", - privateKey: ANVIL_PKEY_B, - }); - return checksumAddress(result.walletAddress); -}; diff --git a/tests/e2e/utils/statistics.ts b/tests/e2e/utils/statistics.ts deleted file mode 100644 index 3c4563a85..000000000 --- a/tests/e2e/utils/statistics.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const calculateStats = (times: number[]) => { - const filteredTimes = times.filter((time) => time > 0); - const sortedTimes = [...filteredTimes].sort((a, b) => a - b); - - return { - avg: filteredTimes.reduce((a, b) => a + b, 0) / filteredTimes.length, - min: Math.min(...filteredTimes), - max: Math.max(...filteredTimes), - p95: sortedTimes[Math.floor(sortedTimes.length * 0.95)], - }; -}; - -export const printStats = (minedTimes: number[], sentTimes: number[]) => { - const minedStats = calculateStats(minedTimes); - const sentStats = calculateStats(sentTimes); - - console.table({ - Mined: minedStats, - Sent: sentStats, - }); -}; diff --git a/tests/e2e/utils/transactions.ts b/tests/e2e/utils/transactions.ts deleted file mode 100644 index 4f889d3a9..000000000 --- a/tests/e2e/utils/transactions.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { sleep } from "bun"; -import type { Address } from "viem"; -import type { Engine } from "../../../sdk/dist/thirdweb-dev-engine.cjs"; -import { CONFIG } from "../config"; - -type Timing = { - queuedAt?: number; - sentAt?: number; - minedAt?: number; - errorMessage?: string; -}; - -export const sendNoOpTransaction = async ( - engine: Engine, - backendWallet: Address, -) => { - try { - const { - result: { queueId }, - } = await engine.backendWallet.transfer( - CONFIG.CHAIN.id.toString(), - backendWallet, - { - amount: "0", - currencyAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - to: backendWallet, - }, - ); - return queueId; - } catch (e) { - console.error("Error sending NoOp transaction:", e); - return undefined; - } -}; - -export const sendMintToTransaction = async ( - engine: Engine, - nftContractAddress: Address, - backendWallet: Address, -) => { - try { - const res = await engine.erc721.mintTo( - CONFIG.CHAIN.id.toString(), - nftContractAddress, - backendWallet, - { - receiver: backendWallet, - metadata: { - name: "My NFT", - description: "My NFT description", - image: - "ipfs://QmciR3WLJsf2BgzTSjbG5zCxsrEQ8PqsHK7JWGWsDSNo46/nft.png", - }, - }, - ); - return res.result.queueId; - } catch (e) { - console.error("Error sending MintTo transaction:", e); - return undefined; - } -}; - -export const pollTransactionStatus = async ( - engine: Engine, - queueId: string, - log = false, -) => { - let mined = false; - const timing: Timing = {}; - - while (!mined) { - await sleep(Math.random() * CONFIG.STAGGER_MAX); - const res = await engine.transaction.status(queueId); - // stagger some sleep - - if (log) { - console.log("Transaction status:", res.result.status); - } - - if (res.result.errorMessage) { - console.error("Transaction Error:", res.result.errorMessage); - timing.errorMessage = res.result.errorMessage; - return timing; - } - - if (res.result.minedAt) { - timing.minedAt = new Date(res.result.minedAt).getTime(); - mined = true; - } - - if (res.result.sentAt) { - timing.sentAt = new Date(res.result.sentAt).getTime(); - } - - if (res.result.queuedAt) { - timing.queuedAt = new Date(res.result.queuedAt).getTime(); - } - - if (res.result.status === "errored") { - console.error("Transaction errored:", res.result.errorMessage); - timing.errorMessage = res.result.errorMessage ?? undefined; - return timing; - } - - if (!mined) { - await sleep(CONFIG.POLLING_INTERVAL); - } - } - - return timing; -}; diff --git a/tests/e2e/utils/wallets.ts b/tests/e2e/utils/wallets.ts deleted file mode 100644 index ece4053b2..000000000 --- a/tests/e2e/utils/wallets.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createThirdwebClient } from "thirdweb"; -import { privateKeyToAccount } from "thirdweb/wallets"; - -export const ANVIL_PKEY_A = - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; -export const ANVIL_PKEY_B = - "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"; -export const ANVIL_PKEY_C = - "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"; -export const ANVIL_PKEY_D = - "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6"; - -export const client = createThirdwebClient({ - secretKey: process.env.THIRDWEB_API_SECRET_KEY as string, -}); - -export const TEST_ACCOUNT_A = privateKeyToAccount({ - client, - privateKey: ANVIL_PKEY_A, -}); - -export const TEST_ACCOUNT_B = privateKeyToAccount({ - client, - privateKey: ANVIL_PKEY_B, -}); diff --git a/tests/generate-accounts.ts b/tests/generate-accounts.ts new file mode 100644 index 000000000..b56bc09ff --- /dev/null +++ b/tests/generate-accounts.ts @@ -0,0 +1,55 @@ +// const engineUrl = "https://engine-v3-test-instance-yl1c.engine-aws-usw2.zeet.app/"; +// const AUTH_TOKEN = +// "Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIweEJEZjEyMzYwQjFDNWZiQmVGOUM1NDM4QTI4QTBEYzA0QzQ3MkVBMzgiLCJzdWIiOiIweEJEZjEyMzYwQjFDNWZiQmVGOUM1NDM4QTI4QTBEYzA0QzQ3MkVBMzgiLCJhdWQiOiJ0aGlyZHdlYi5jb20iLCJleHAiOjQ4OTQzMDAzNTYsIm5iZiI6MTc0MDcwMDM1NiwiaWF0IjoxNzQwNzAwMzU2LCJqdGkiOiI2NmU2YzczZi1lMzdjLTRhOWUtYWQ5OC0yZGEyMGRiYTg3ODQiLCJjdHgiOnsicGVybWlzc2lvbnMiOlsiQURNSU4iXX19.MHgyYzc3ZWEzZjIzNjE5YzVkZDIyNTdkMGE2OTljNzg3MDcwY2M0ZmJlZDVhNzA1ZDZhZjQxODVlOTZmZGZmZDU0MzNlMTA4ZTQxOWJmZDUwZjQ4MDAxNmU4ODk0ZmFjZDQ0OGM1MGY3YWQ1ZmZkZDM3NDU3NDhkODRjNzU3ZmMyZjFi"; +const engineUrl = "http://localhost:3005/"; +const AUTH_TOKEN = "Bearer ndnypk25YsSSenDFx30k7L3UlOqH8fdtuW9NAr9ydYWQPjHb0sDEgb_8d3SjLl6gy3ryovgl656P2tv52kR93g"; + + +// Configuration +const TOTAL_ACCOUNTS = 1000; +const BATCH_SIZE = 50; // Process 50 accounts at a time + +const accounts: unknown[] = []; + +// Simple sleep function +const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +// Warm up connection +await fetch(`${engineUrl}/system/health`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: AUTH_TOKEN, + }, +}); + +// Process in batches +for (let i = 0; i < TOTAL_ACCOUNTS; i += BATCH_SIZE) { + const batchSize = Math.min(BATCH_SIZE, TOTAL_ACCOUNTS - i); + const batchPromises = Array.from({ length: batchSize }, (_, j) => { + const index = i + j; + return fetch(`${engineUrl}/accounts`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: AUTH_TOKEN, + }, + body: JSON.stringify({ + type: "local", + label: `load-test-${index}`, + }), + }) + .then((res) => res.json()) + .then((data) => accounts.push(data)); + }); + + await Promise.all(batchPromises); + + // Small delay between batches + if (i + BATCH_SIZE < TOTAL_ACCOUNTS) { + await sleep(200); + } +} + +// Only output the accounts JSON +console.log(JSON.stringify(accounts, null, 2)); diff --git a/tests/k6.js b/tests/k6.js new file mode 100644 index 000000000..86bd20580 --- /dev/null +++ b/tests/k6.js @@ -0,0 +1,80 @@ +import http from 'k6/http'; +import { check, sleep } from 'k6'; +import { randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; + + +const HOST = "http://localhost:3005/"; +// const AUTH_TOKEN = +// "Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIweEJEZjEyMzYwQjFDNWZiQmVGOUM1NDM4QTI4QTBEYzA0QzQ3MkVBMzgiLCJzdWIiOiIweEJEZjEyMzYwQjFDNWZiQmVGOUM1NDM4QTI4QTBEYzA0QzQ3MkVBMzgiLCJhdWQiOiJ0aGlyZHdlYi5jb20iLCJleHAiOjQ4OTQzMDAzNTYsIm5iZiI6MTc0MDcwMDM1NiwiaWF0IjoxNzQwNzAwMzU2LCJqdGkiOiI2NmU2YzczZi1lMzdjLTRhOWUtYWQ5OC0yZGEyMGRiYTg3ODQiLCJjdHgiOnsicGVybWlzc2lvbnMiOlsiQURNSU4iXX19.MHgyYzc3ZWEzZjIzNjE5YzVkZDIyNTdkMGE2OTljNzg3MDcwY2M0ZmJlZDVhNzA1ZDZhZjQxODVlOTZmZGZmZDU0MzNlMTA4ZTQxOWJmZDUwZjQ4MDAxNmU4ODk0ZmFjZDQ0OGM1MGY3YWQ1ZmZkZDM3NDU3NDhkODRjNzU3ZmMyZjFi"; + +const AUTH_TOKEN = "Bearer ndnypk25YsSSenDFx30k7L3UlOqH8fdtuW9NAr9ydYWQPjHb0sDEgb_8d3SjLl6gy3ryovgl656P2tv52kR93g"; + +// Test configuration +export const options = { + // Standard load test configuration + stages: [ + { duration: '5s', target: 10 }, // Ramp up to 10 users + { duration: '10s', target: 50 }, // Ramp up to 50 users + { duration: '45s', target: 200 }, // Ramp up to 50 users + // { duration: '15s', target: 500 }, // Ramp up to 50 users + // { duration: '300s', target: 1000 }, // Ramp up to 50 users + { duration: '30s', target: 0 } // Ramp down to 0 users + ], + thresholds: { + http_req_failed: ['rate<0.01'], // Less than 1% of requests should fail + http_req_duration: ['p(95)<10000'] // 95% of requests should be below 2s + } +}; + +// Load wallet data from a file +const wallets = JSON.parse(open('./wallets_local.json')); + +export default function () { + // Pick a random wallet from the list + const wallet = wallets[randomIntBetween(0, wallets.length - 1)]; + + // Get the wallet address + const fromAddress = wallet.result.smartAccounts && wallet.result.smartAccounts.length > 0 + ? wallet.result.smartAccounts[0].address + : wallet.result.address; + + // Set up the request + const url = `${HOST}/contract/write`; + const payload = JSON.stringify({ + from: fromAddress, + transactionParams: [ + { + "method": "function safeMint(address to, uint256 tokenId, uint256 amount)", + "params": [fromAddress, "0", "1"], + "contractAddress": "0xd717CC9f5F68BBc4f0bEE120b26004bfd65f272e" + } + ], + chainId: "13337", + }); + + const params = { + headers: { + 'Content-Type': 'application/json', + 'Authorization': AUTH_TOKEN + } + }; + + // Make the request + const response = http.post(url, payload, params); + + // Check if request was successful + check(response, { + 'status is 200': (r) => r.status === 200, + 'transaction accepted': (r) => { + try { + const body = JSON.parse(r.body); + return body.result?.transactions[0]?.executionResult?.monitoringStatus === "WILL_MONITOR"; + } catch { + return false; + } + } + }); + + // Add a small sleep between iterations + sleep(1); +} \ No newline at end of file diff --git a/tests/shared/aws-kms.ts b/tests/shared/aws-kms.ts deleted file mode 100644 index 3dd664a45..000000000 --- a/tests/shared/aws-kms.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { assert } from "vitest"; - -const TEST_AWS_KMS_ACCESS_KEY_ID = process.env.TEST_AWS_KMS_ACCESS_KEY_ID; -const TEST_AWS_KMS_SECRET_ACCESS_KEY = - process.env.TEST_AWS_KMS_SECRET_ACCESS_KEY; -const TEST_AWS_KMS_KEY_ID = process.env.TEST_AWS_KMS_KEY_ID; -const TEST_AWS_KMS_REGION = process.env.TEST_AWS_KMS_REGION; - -assert(TEST_AWS_KMS_ACCESS_KEY_ID, "TEST_AWS_KMS_ACCESS_KEY_ID is required"); -assert( - TEST_AWS_KMS_SECRET_ACCESS_KEY, - "TEST_AWS_KMS_SECRET_ACCESS_KEY is required", -); -assert(TEST_AWS_KMS_KEY_ID, "TEST_AWS_KMS_KEY_ID is required"); -assert(TEST_AWS_KMS_REGION, "TEST_AWS_KMS_REGION is required"); - -export const TEST_AWS_KMS_CONFIG = { - accessKeyId: TEST_AWS_KMS_ACCESS_KEY_ID, - secretAccessKey: TEST_AWS_KMS_SECRET_ACCESS_KEY, - region: TEST_AWS_KMS_REGION, - keyId: TEST_AWS_KMS_KEY_ID, -}; diff --git a/tests/shared/chain.ts b/tests/shared/chain.ts deleted file mode 100644 index aed41dbdc..000000000 --- a/tests/shared/chain.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineChain } from "thirdweb"; -import { anvil } from "thirdweb/chains"; -import { createTestClient, http } from "viem"; - -export const ANVIL_CHAIN = defineChain({ - ...anvil, - rpc: "http://127.0.0.1:8645/1", -}); - -export const anvilTestClient = createTestClient({ - mode: "anvil", - transport: http(ANVIL_CHAIN.rpc), -}); diff --git a/tests/shared/client.ts b/tests/shared/client.ts deleted file mode 100644 index 72af98599..000000000 --- a/tests/shared/client.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createThirdwebClient } from "thirdweb"; - -const secretKey = process.env.TW_SECRET_KEY; -if (!secretKey) throw new Error("TW_SECRET_KEY is required"); -export const TEST_CLIENT = createThirdwebClient({ secretKey }); diff --git a/tests/shared/gcp-kms.ts b/tests/shared/gcp-kms.ts deleted file mode 100644 index a846632a3..000000000 --- a/tests/shared/gcp-kms.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { assert } from "vitest"; - -const TEST_GCP_KMS_RESOURCE_PATH = process.env.TEST_GCP_KMS_RESOURCE_PATH; -const TEST_GCP_KMS_EMAIL = process.env.TEST_GCP_KMS_EMAIL; -const TEST_GCP_KMS_PK = process.env.TEST_GCP_KMS_PK; - -assert(TEST_GCP_KMS_RESOURCE_PATH, "TEST_GCP_KMS_RESOURCE_PATH is required"); -assert(TEST_GCP_KMS_EMAIL, "TEST_GCP_KMS_EMAIL is required"); -assert(TEST_GCP_KMS_PK, "TEST_GCP_KMS_PK is required"); - -export const TEST_GCP_KMS_CONFIG = { - resourcePath: TEST_GCP_KMS_RESOURCE_PATH, - email: TEST_GCP_KMS_EMAIL, - pk: TEST_GCP_KMS_PK, -}; diff --git a/tests/shared/typed-data.ts b/tests/shared/typed-data.ts deleted file mode 100644 index 487a2d2d3..000000000 --- a/tests/shared/typed-data.ts +++ /dev/null @@ -1,86 +0,0 @@ -export const typedData = { - basic: { - domain: { - name: "Ether Mail", - version: "1", - chainId: 1, - verifyingContract: "0x0000000000000000000000000000000000000000", - }, - types: { - Person: [ - { name: "name", type: "string" }, - { name: "wallet", type: "address" }, - ], - Mail: [ - { name: "from", type: "Person" }, - { name: "to", type: "Person" }, - { name: "contents", type: "string" }, - ], - }, - message: { - from: { - name: "Cow", - wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", - }, - to: { - name: "Bob", - wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", - }, - contents: "Hello, Bob!", - }, - primaryType: "Mail", - }, - complex: { - domain: { - name: "Ether Mail 🥵", - version: "1.1.1", - chainId: 1, - verifyingContract: "0x0000000000000000000000000000000000000000", - }, - types: { - Name: [ - { name: "first", type: "string" }, - { name: "last", type: "string" }, - ], - Person: [ - { name: "name", type: "Name" }, - { name: "wallet", type: "address" }, - { name: "favoriteColors", type: "string[3]" }, - { name: "foo", type: "uint256" }, - { name: "age", type: "uint8" }, - { name: "isCool", type: "bool" }, - ], - Mail: [ - { name: "timestamp", type: "uint256" }, - { name: "from", type: "Person" }, - { name: "to", type: "Person" }, - { name: "contents", type: "string" }, - { name: "hash", type: "bytes" }, - ], - }, - message: { - timestamp: 1234567890n, - contents: "Hello, Bob! 🖤", - hash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - from: { - name: { - first: "Cow", - last: "Burns", - }, - wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", - age: 69, - foo: 123123123123123123n, - favoriteColors: ["red", "green", "blue"], - isCool: false, - }, - to: { - name: { first: "Bob", last: "Builder" }, - wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", - age: 70, - foo: 123123123123123123n, - favoriteColors: ["orange", "yellow", "green"], - isCool: true, - }, - }, - }, -} as const; diff --git a/tests/unit/auth.test.ts b/tests/unit/auth.test.ts deleted file mode 100644 index 7bf3ca1be..000000000 --- a/tests/unit/auth.test.ts +++ /dev/null @@ -1,960 +0,0 @@ -import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - -import { LocalWallet } from "@thirdweb-dev/wallets"; -import type { FastifyRequest } from "fastify/types/request"; -import jsonwebtoken from "jsonwebtoken"; -import { getPermissions } from "../../src/shared/db/permissions/get-permissions"; -import { WebhooksEventTypes } from "../../src/shared/schemas/webhooks"; -import { onRequest } from "../../src/server/middleware/auth"; -import { - THIRDWEB_DASHBOARD_ISSUER, - handleSiwe, -} from "../../src/shared/utils/auth"; -import { getAccessToken } from "../../src/shared/utils/cache/access-token"; -import { getAuthWallet } from "../../src/shared/utils/cache/auth-wallet"; -import { getConfig } from "../../src/shared/utils/cache/get-config"; -import { getWebhooksByEventType } from "../../src/shared/utils/cache/get-webhook"; -import { getKeypair } from "../../src/shared/utils/cache/keypair"; -import { sendWebhookRequest } from "../../src/shared/utils/webhook"; -import { Permission } from "../../src/shared/schemas/auth"; - -vi.mock("../utils/cache/accessToken"); -const mockGetAccessToken = vi.mocked(getAccessToken); - -vi.mock("../db/permissions/getPermissions"); -const mockGetPermissions = vi.mocked(getPermissions); - -vi.mock("../utils/cache/authWallet"); -const mockGetAuthWallet = vi.mocked(getAuthWallet); - -vi.mock("../utils/cache/getWebhook"); -const mockGetWebhook = vi.mocked(getWebhooksByEventType); -mockGetWebhook.mockResolvedValue([]); - -vi.mock("../utils/webhook"); -const mockSendWebhookRequest = vi.mocked(sendWebhookRequest); - -vi.mock("../utils/auth"); -const mockHandleSiwe = vi.mocked(handleSiwe); - -vi.mock("../utils/cache/keypair"); -const mockGetKeypair = vi.mocked(getKeypair); - -vi.mock("../utils/cache/getConfig"); -const mockGetConfig = vi.mocked(getConfig); - -let testAuthWallet: LocalWallet; -beforeAll(async () => { - // Initialize a local auth wallet. - testAuthWallet = new LocalWallet(); - await testAuthWallet.generate(); - mockGetAuthWallet.mockResolvedValue(testAuthWallet); - - const defaultConfig = await getConfig(); - - mockGetConfig.mockResolvedValue({ - ...defaultConfig, - accessControlAllowOrigin: "*", - ipAllowlist: [], - }); -}); - -describe("Static paths", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - - it("Static paths are authed", async () => { - const pathsToTest = [ - "/", - "/system/health", - "/json", - "/transaction/status/my-queue-id", - ]; - for (const path of pathsToTest) { - const req: FastifyRequest = { - method: "GET", - url: path, - headers: {}, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - } - }); -}); - -describe("Relayer endpoints", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - - it("The 'relay transaction' endpoint is authed", async () => { - const req: FastifyRequest = { - method: "POST", - url: "/relayer/be369f95-7bef-4e29-a016-3146fa394eb1", - headers: {}, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - }); - - it("Other relayer endpoints are not authed", async () => { - const pathsToTest = [ - "/relayer/getAll", - "/relayer/create", - "/relayer/revoke", - "/relayer/update", - ]; - for (const path of pathsToTest) { - const req: FastifyRequest = { - method: "POST", - url: path, - headers: {}, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - } - }); -}); - -describe("Websocket requests", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - - it("A websocket request with a valid access token is authed", async () => { - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: null, - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { permissions: Permission.Admin }, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { upgrade: "WEBSOCKET" }, - query: { token: "my-access-token" }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).not.toBeUndefined(); - }); - - it("A websocket request with a valid access token and non-admin permission is not authed", async () => { - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: null, - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ session: { permission: "none" } }); - - const mockSocket = { - write: vi.fn(), - destroy: vi.fn(), - }; - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { upgrade: "WEBSOCKET" }, - query: { token: "my-access-token" }, - // @ts-ignore - raw: { socket: mockSocket }, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(mockSocket.write).toHaveBeenCalledTimes(1); - expect(mockSocket.destroy).toHaveBeenCalledTimes(1); - }); - - it("A websocket request with a revoked access token is not authed", async () => { - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: new Date(), - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { - permission: Permission.Admin, - }, - }); - - const mockSocket = { - write: vi.fn(), - destroy: vi.fn(), - }; - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { upgrade: "WEBSOCKET" }, - query: { token: "my-access-token" }, - // @ts-ignore - raw: { socket: mockSocket }, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(mockSocket.write).toHaveBeenCalledTimes(1); - expect(mockSocket.destroy).toHaveBeenCalledTimes(1); - }); - - it("A websocket request with an invalid access token is not authed", async () => { - mockGetAccessToken.mockResolvedValue(null); - - const mockSocket = { - write: vi.fn(), - destroy: vi.fn(), - }; - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { upgrade: "WEBSOCKET" }, - query: { token: "my-access-token" }, - // @ts-ignore - raw: { socket: mockSocket }, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(mockSocket.write).toHaveBeenCalledTimes(1); - expect(mockSocket.destroy).toHaveBeenCalledTimes(1); - }); - - it("A websocket request with IP outside of IP Allowlist is not authed", async () => { - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: null, - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { permissions: Permission.Admin }, - }); - - const defaultConfig = await getConfig(); - mockGetConfig.mockResolvedValueOnce({ - ...defaultConfig, - accessControlAllowOrigin: "*", - ipAllowlist: ["123.123.1.1"], - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { upgrade: "WEBSOCKET" }, - query: { token: "my-access-token" }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(result.user).toBeUndefined(); - expect(result.error).toEqual( - "Unauthorized IP Address. See: https://portal.thirdweb.com/engine/features/security", - ); - }); -}); - -describe("Access tokens", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - - it("Valid access token with admin permissions is authed", async () => { - const jwt = jsonwebtoken.sign( - { iss: await testAuthWallet.getAddress() }, - "test", - ); - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: null, - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { permissions: Permission.Admin }, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).not.toBeUndefined(); - }); - - it("Valid access token with non-admin permissions is not authed", async () => { - const jwt = jsonwebtoken.sign( - { iss: await testAuthWallet.getAddress() }, - "test", - ); - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: null, - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { permissions: "none" }, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); - - it("Revoked access token is not authed", async () => { - const jwt = jsonwebtoken.sign( - { iss: await testAuthWallet.getAddress() }, - "test", - ); - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: new Date(), - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { permissions: Permission.Admin }, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); - - it("Invalid access token is not authed", async () => { - const jwt = jsonwebtoken.sign( - { iss: await testAuthWallet.getAddress() }, - "test", - ); - mockGetAccessToken.mockResolvedValue(null); - - mockGetUser.mockReturnValue({ - session: { permissions: Permission.Admin }, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); - - it("Request from IP outside allowlist is not authed", async () => { - const jwt = jsonwebtoken.sign( - { iss: await testAuthWallet.getAddress() }, - "test", - ); - - const defaultConfig = await getConfig(); - mockGetConfig.mockResolvedValueOnce({ - ...defaultConfig, - accessControlAllowOrigin: "*", - ipAllowlist: ["123.123.1.1"], - }); - - mockGetAccessToken.mockResolvedValue({ - id: "my-access-token", - tokenMask: "", - walletAddress: "0x0000000000000000000000000123", - createdAt: new Date(), - expiresAt: new Date(), - revokedAt: null, - isAccessToken: true, - label: "test access token", - }); - - mockGetUser.mockReturnValue({ - session: { permissions: Permission.Admin }, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(result.user).toBeUndefined(); - expect(result.error).toEqual( - "Unauthorized IP Address. See: https://portal.thirdweb.com/engine/features/security", - ); - }); -}); - -describe("Keypair auth JWT", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - // Example ES256 keypair used only for unit tests. - const testKeypair = { - public: `-----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKbqftPicYL3V+4gZHi16wUWSJ1gO -bsSyKJ/JW3qPUmL0fhdSNZz6C0cP9UNh7FQsLQ/l2BcOH8+G2xvh+8tjtQ== ------END PUBLIC KEY-----`, - private: `-----BEGIN EC PRIVATE KEY----- -MHcCAQEEICIJbkRowq93OJvo2Tk4eopRbU8dDqp1bh9xHDpF9b6boAoGCCqGSM49 -AwEHoUQDQgAEKbqftPicYL3V+4gZHi16wUWSJ1gObsSyKJ/JW3qPUmL0fhdSNZz6 -C0cP9UNh7FQsLQ/l2BcOH8+G2xvh+8tjtQ== ------END EC PRIVATE KEY-----`, - } as const; - - const mockGetUser = vi.fn(); - - it("Valid JWT signed by private key", async () => { - mockGetKeypair.mockResolvedValue({ - hash: "", - publicKey: testKeypair.public, - algorithm: "ES256", - label: null, - createdAt: new Date(), - updatedAt: new Date(), - }); - - // Sign a valid auth payload. - const jwt = jsonwebtoken.sign( - { iss: testKeypair.public }, - testKeypair.private, - { - algorithm: "ES256", - expiresIn: "20s", - }, - ); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).toBeUndefined(); - expect(result.error).toBeUndefined(); - }); - - it("Expired JWT signed by private key", async () => { - mockGetKeypair.mockResolvedValue({ - hash: "", - publicKey: testKeypair.public, - algorithm: "ES256", - label: null, - createdAt: new Date(), - updatedAt: new Date(), - }); - - // Sign an expired auth payload. - const jwt = jsonwebtoken.sign( - { iss: testKeypair.public }, - testKeypair.private, - { - algorithm: "ES256", - expiresIn: -3_000, - }, - ); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(result.user).toBeUndefined(); - expect(result.error).toEqual("Keypair token is expired."); - }); - - it("Unrecognized public key", async () => { - // Get keypair returns null for an unrecognized public key - mockGetKeypair.mockResolvedValueOnce(null); - - // Sign an expired auth payload. - const jwt = jsonwebtoken.sign( - { iss: "some_other_public_key" }, - testKeypair.private, - { - algorithm: "ES256", - expiresIn: "15s", - }, - ); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(result.user).toBeUndefined(); - expect(result.error).toEqual( - "The provided public key is incorrect or not added to Engine.", - ); - }); - - it("Invalid JWT signed by the wrong private key", async () => { - // Sign a valid auth payload with a different private key. - const WRONG_PRIVATE_KEY = `-----BEGIN EC PRIVATE KEY----- -MHcCAQEEIH719lhdn4CzboBQKr8E68htVNeQ2wwrxnsDhfLOgGNAoAoGCCqGSM49 -AwEHoUQDQgAE74w9+HXi/PCQZTu2AS4titehOFopNSrfqlFnFbtglPuwNB2ke53p -6sE9ABLmMjeNbKKz9ayyCGN/BC3MNikhfw== ------END EC PRIVATE KEY-----`; - const jwt = jsonwebtoken.sign( - { iss: testKeypair.public }, - WRONG_PRIVATE_KEY, - { - algorithm: "ES256", - expiresIn: "15s", - }, - ); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(result.user).toBeUndefined(); - expect(result.error).toEqual( - 'Error parsing "Authorization" header. See: https://portal.thirdweb.com/engine/features/access-tokens', - ); - }); - - it("IP outside of IP Allowlist", async () => { - const defaultConfig = await getConfig(); - mockGetConfig.mockResolvedValueOnce({ - ...defaultConfig, - accessControlAllowOrigin: "*", - ipAllowlist: ["123.123.1.1"], - }); - - mockGetKeypair.mockResolvedValue({ - hash: "", - publicKey: testKeypair.public, - algorithm: "ES256", - label: null, - createdAt: new Date(), - updatedAt: new Date(), - }); - - // Sign a valid auth payload. - const jwt = jsonwebtoken.sign( - { iss: testKeypair.public }, - testKeypair.private, - { - algorithm: "ES256", - expiresIn: "20s", - }, - ); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - expect(result.error).toEqual( - "Unauthorized IP Address. See: https://portal.thirdweb.com/engine/features/security", - ); - expect(result.user).toBeUndefined(); - }); -}); - -describe("Dashboard JWT", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - mockGetAccessToken.mockResolvedValue(null); - - it("Valid dashboard JWT with admin permission is authed", async () => { - const jwt = jsonwebtoken.sign({ iss: THIRDWEB_DASHBOARD_ISSUER }, "test"); - mockHandleSiwe.mockResolvedValue({ - address: "0x0000000000000000000000000123", - }); - mockGetPermissions.mockResolvedValue({ - walletAddress: "0x0000000000000000000000000123", - permissions: Permission.Admin, - label: null, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).not.toBeUndefined(); - }); - - it("Request with valid dashboard JWT but IP outside allowlist is still authed", async () => { - const jwt = jsonwebtoken.sign({ iss: THIRDWEB_DASHBOARD_ISSUER }, "test"); - mockHandleSiwe.mockResolvedValue({ - address: "0x0000000000000000000000000123", - }); - mockGetPermissions.mockResolvedValue({ - walletAddress: "0x0000000000000000000000000123", - permissions: Permission.Admin, - label: null, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const defaultConfig = await getConfig(); - - mockGetConfig.mockResolvedValueOnce({ - ...defaultConfig, - accessControlAllowOrigin: "*", - ipAllowlist: ["123.123.1.1"], - }); - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).not.toBeUndefined(); - }); - - it("Valid dashboard JWT with non-admin permission is not authed", async () => { - // Mock dashboard JWTs. - const jwt = jsonwebtoken.sign({ iss: THIRDWEB_DASHBOARD_ISSUER }, "test"); - mockHandleSiwe.mockResolvedValue({ - address: "0x0000000000000000000000000123", - }); - mockGetPermissions.mockResolvedValue({ - walletAddress: "0x0000000000000000000000000123", - permissions: "none", - label: null, - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); - - it("Dashboard JWT for an unknown user is not authed", async () => { - // Mock dashboard JWTs. - const jwt = jsonwebtoken.sign({ iss: THIRDWEB_DASHBOARD_ISSUER }, "test"); - mockHandleSiwe.mockResolvedValue({ - address: "0x0000000000000000000000000123", - }); - mockGetPermissions.mockResolvedValue(null); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); - - it("Invalid dashboard JWT is not authed", async () => { - // Mock dashboard JWTs. - const jwt = jsonwebtoken.sign({ iss: THIRDWEB_DASHBOARD_ISSUER }, "test"); - mockHandleSiwe.mockResolvedValue(null); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: `Bearer ${jwt}` }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); -}); - -describe("thirdweb secret key", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - - it("Valid thirdweb secret key is authed", async () => { - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: "Bearer my-thirdweb-secret-key" }, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).not.toBeUndefined(); - }); - - it("Request with valid thirdweb secret key but IP outside allowlist is still authed", async () => { - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: { authorization: "Bearer my-thirdweb-secret-key" }, - // @ts-ignore - raw: {}, - }; - - const defaultConfig = await getConfig(); - - mockGetConfig.mockResolvedValueOnce({ - ...defaultConfig, - accessControlAllowOrigin: "*", - ipAllowlist: ["123.123.1.1"], - }); - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).not.toBeUndefined(); - }); -}); - -describe("auth webhooks", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - const mockGetUser = vi.fn(); - - it("A request that gets a 2xx from all auth webhooks is authed", async () => { - mockGetWebhook.mockResolvedValue([ - { - id: 1, - url: "test-webhook-url", - name: "auth webhook 1", - eventType: WebhooksEventTypes.AUTH, - createdAt: new Date(), - updatedAt: new Date(), - revokedAt: null, - secret: "random-secret", - }, - { - id: 2, - url: "test-webhook-url", - name: "auth webhook 2", - eventType: WebhooksEventTypes.AUTH, - createdAt: new Date(), - updatedAt: new Date(), - revokedAt: null, - secret: "random-secret-2", - }, - ]); - - // Both auth webhooks return 2xx. - mockSendWebhookRequest.mockResolvedValueOnce({ - ok: true, - status: 200, - body: "test-1", - }); - mockSendWebhookRequest.mockResolvedValueOnce({ - ok: true, - status: 200, - body: "test-2", - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: {}, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeTruthy(); - expect(result.user).toBeUndefined(); - }); - - it("A request that gets a non-2xx from any auth webhooks is not authed", async () => { - mockGetWebhook.mockResolvedValue([ - { - id: 1, - url: "test-webhook-url", - name: "auth webhook 1", - eventType: WebhooksEventTypes.AUTH, - createdAt: new Date(), - updatedAt: new Date(), - revokedAt: null, - secret: "random-secret", - }, - { - id: 1, - url: "test-webhook-url", - name: "auth webhook 1", - eventType: WebhooksEventTypes.AUTH, - createdAt: new Date(), - updatedAt: new Date(), - revokedAt: null, - secret: "random-secret", - }, - ]); - - // Both auth webhooks return 4xx. - mockSendWebhookRequest.mockResolvedValueOnce({ - ok: false, - status: 400, - body: "error-1", - }); - mockSendWebhookRequest.mockResolvedValueOnce({ - ok: false, - status: 401, - body: "error-2", - }); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: {}, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); - - it("A request with no auth webhooks is not authed", async () => { - mockGetWebhook.mockResolvedValue([]); - - const req: FastifyRequest = { - method: "POST", - url: "/backend-wallets/get-all", - headers: {}, - // @ts-ignore - raw: {}, - }; - - const result = await onRequest({ req, getUser: mockGetUser }); - expect(result.isAuthed).toBeFalsy(); - }); -}); diff --git a/tests/unit/aws-arn.test.ts b/tests/unit/aws-arn.test.ts deleted file mode 100644 index 90bafed78..000000000 --- a/tests/unit/aws-arn.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { - getAwsKmsArn, - splitAwsKmsArn, -} from "../../src/server/utils/wallets/aws-kms-arn"; - -describe("splitAwsKmsArn", () => { - it("should correctly split a valid AWS KMS ARN", () => { - const arn = - "arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab"; - const result = splitAwsKmsArn(arn); - expect(result).toEqual({ - region: "us-west-2", - accountId: "123456789012", - keyId: "1234abcd-12ab-34cd-56ef-1234567890ab", - }); - }); - - it("should throw an error for an ARN without a key ID", () => { - const arn = "arn:aws:kms:us-west-2:123456789012:key/"; - expect(() => splitAwsKmsArn(arn)).toThrow("Invalid AWS KMS ARN"); - }); - - it("should throw an error for an ARN with insufficient parts", () => { - const arn = "arn:aws:kms:us-west-2:123456789012"; - expect(() => splitAwsKmsArn(arn)).toThrow("Invalid AWS KMS ARN"); - }); - - it("should handle ARNs with additional parts", () => { - const arn = "arn:aws:kms:us-west-2:123456789012:key/abcdef:extra:parts"; - const result = splitAwsKmsArn(arn); - expect(result).toEqual({ - region: "us-west-2", - accountId: "123456789012", - keyId: "abcdef:extra:parts", - }); - }); -}); - -describe("getAwsKmsArn", () => { - it("should correctly construct an AWS KMS ARN", () => { - const options = { - region: "eu-central-1", - accountId: "987654321098", - keyId: "9876fedc-ba98-7654-3210-fedcba9876543", - }; - const result = getAwsKmsArn(options); - expect(result).toBe( - "arn:aws:kms:eu-central-1:987654321098:key/9876fedc-ba98-7654-3210-fedcba9876543", - ); - }); - - it("should handle numeric account IDs", () => { - const options = { - region: "us-east-1", - accountId: "123456789012", - keyId: "abcdef", - }; - const result = getAwsKmsArn(options); - expect(result).toBe("arn:aws:kms:us-east-1:123456789012:key/abcdef"); - }); -}); diff --git a/tests/unit/aws-kms.test.ts b/tests/unit/aws-kms.test.ts deleted file mode 100644 index d4d95322b..000000000 --- a/tests/unit/aws-kms.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { beforeAll, expect, test, vi } from "vitest"; - -import { ANVIL_CHAIN, anvilTestClient } from "../shared/chain.ts"; -import { typedData } from "../shared/typed-data.ts"; -import { verifyTypedData } from "thirdweb"; -import { verifyEOASignature } from "thirdweb/auth"; -import { - prepareTransaction, - sendAndConfirmTransaction, -} from "thirdweb/transaction"; -import { toUnits, toWei } from "thirdweb/utils"; -import { getWalletBalance } from "thirdweb/wallets"; -import { TEST_CLIENT } from "../shared/client.ts"; -import { getAwsKmsAccount } from "../../src/server/utils/wallets/get-aws-kms-account"; -import { TEST_AWS_KMS_CONFIG } from "../shared/aws-kms.ts"; - -let account: Awaited>; - -vi.mock("../../utils/chain", () => ({ - getChain: async () => ANVIL_CHAIN, -})); - -beforeAll(async () => { - account = await getAwsKmsAccount({ - keyId: TEST_AWS_KMS_CONFIG.keyId, - client: TEST_CLIENT, - config: { - credentials: { - accessKeyId: TEST_AWS_KMS_CONFIG.accessKeyId, - secretAccessKey: TEST_AWS_KMS_CONFIG.secretAccessKey, - }, - region: TEST_AWS_KMS_CONFIG.region, - }, - }); -}); - -test("account address is valid", () => { - expect(account.address).toMatch(/^0x[a-fA-F0-9]{40}$/); -}); - -test("sign message", async () => { - const message = "hello world"; - const signature = await account.signMessage({ message }); - - expect(signature).toMatch(/^0x[a-fA-F0-9]{130}$/); - - const isValid = await verifyEOASignature({ - address: account.address, - message, - signature, - }); - expect(isValid).toBe(true); -}); - -test("sign transaction", async () => { - const tx = { - chainId: ANVIL_CHAIN.id, - maxFeePerGas: toUnits("20", 9), - gas: 21000n, - to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", - value: toUnits("1", 18), - }; - - expect(account.signTransaction).toBeDefined(); - - const signedTx = await account.signTransaction?.(tx); - expect(signedTx).toMatch(/^0x[a-fA-F0-9]+$/); -}); - -test("sign typed data", async () => { - const signature = await account.signTypedData({ - ...typedData.basic, - primaryType: "Mail", - }); - - expect(signature).toMatch(/^0x[a-fA-F0-9]{130}$/); - - const isValid = await verifyTypedData({ - address: account.address, - ...typedData.basic, - primaryType: "Mail", - signature, - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - }); - expect(isValid).toBe(true); -}); - -test("send transaction", async () => { - const recipient = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8"; - - await anvilTestClient.setBalance({ - address: account.address, - value: toWei("10"), - }); - - const startingBalance = await getWalletBalance({ - address: account.address, - chain: ANVIL_CHAIN, - client: TEST_CLIENT, - }); - - const startingBalanceRecipient = await getWalletBalance({ - address: recipient, - chain: ANVIL_CHAIN, - client: TEST_CLIENT, - }); - - const tx = prepareTransaction({ - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - to: recipient, - value: toUnits("1", 18), - }); - - const result = await sendAndConfirmTransaction({ - account, - transaction: tx, - }); - - expect(result.transactionHash).toMatch(/^0x[a-fA-F0-9]{64}$/); - - const endingBalance = await getWalletBalance({ - address: account.address, - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - }); - const endingBalanceRecipient = await getWalletBalance({ - address: recipient, - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - }); - - expect(endingBalance.value).toBeLessThan(startingBalance.value); - expect(endingBalanceRecipient.value).toBeGreaterThan( - startingBalanceRecipient.value, - ); -}); diff --git a/tests/unit/chain.test.ts b/tests/unit/chain.test.ts deleted file mode 100644 index 9db0fca24..000000000 --- a/tests/unit/chain.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { - getChainByChainIdAsync, - getChainBySlugAsync, -} from "@thirdweb-dev/chains"; -import { beforeEach, describe, expect, it, vi } from "vitest"; -import { getChainIdFromChain } from "../../src/server/utils/chain"; -import { getConfig } from "../../src/shared/utils/cache/get-config"; - -// Mock the external dependencies -vi.mock("../utils/cache/getConfig"); -vi.mock("@thirdweb-dev/chains"); - -const mockGetConfig = vi.mocked(getConfig); - -const mockGetChainByChainIdAsync = vi.mocked(getChainByChainIdAsync); -const mockGetChainBySlugAsync = vi.mocked(getChainBySlugAsync); - -describe("getChainIdFromChain", () => { - beforeEach(() => { - // Clear all mock calls before each test - vi.clearAllMocks(); - }); - - it("should return the chainId from chainOverrides if it exists by slug", async () => { - // @ts-ignore - mockGetConfig.mockResolvedValueOnce({ - chainOverrides: JSON.stringify([ - { - slug: "Polygon", - chainId: 137, - }, - ]), - }); - - const result = await getChainIdFromChain("Polygon"); - - expect(result).toBe(137); - expect(getChainByChainIdAsync).not.toHaveBeenCalled(); - expect(getChainBySlugAsync).not.toHaveBeenCalled(); - }); - - it("should return the chainId from chainOverrides if it exists by slug, case-insensitive", async () => { - // @ts-ignore - mockGetConfig.mockResolvedValueOnce({ - chainOverrides: JSON.stringify([ - { - slug: "Polygon", - chainId: 137, - }, - ]), - }); - - const result = await getChainIdFromChain("polygon"); - - expect(result).toBe(137); - expect(getChainByChainIdAsync).not.toHaveBeenCalled(); - expect(getChainBySlugAsync).not.toHaveBeenCalled(); - }); - - it("should return the chainId from chainOverrides if it exists", async () => { - // @ts-ignore - mockGetConfig.mockResolvedValueOnce({ - chainOverrides: JSON.stringify([ - { - slug: "Polygon", - chainId: 137, - }, - ]), - }); - - const result = await getChainIdFromChain("Polygon"); - - expect(result).toBe(137); - expect(getChainByChainIdAsync).not.toHaveBeenCalled(); - expect(getChainBySlugAsync).not.toHaveBeenCalled(); - }); - - it("should return the chainId from getChainByChainIdAsync if chain is a valid numeric string", async () => { - // @ts-ignore - mockGetChainByChainIdAsync.mockResolvedValueOnce({ - name: "Polygon", - chainId: 137, - }); - - const result = await getChainIdFromChain("137"); - - expect(result).toBe(137); - expect(getChainByChainIdAsync).not.toHaveBeenCalled(); - expect(getChainBySlugAsync).not.toHaveBeenCalled(); - }); - - it("should return the chainId from getChainBySlugAsync if chain is a valid string", async () => { - // @ts-ignore - mockGetConfig.mockResolvedValueOnce({}); - // @ts-ignore - mockGetChainBySlugAsync.mockResolvedValueOnce({ - name: "Polygon", - chainId: 137, - }); - - const result = await getChainIdFromChain("Polygon"); - - expect(result).toBe(137); - expect(getChainBySlugAsync).toHaveBeenCalledWith("polygon"); - expect(getChainByChainIdAsync).not.toHaveBeenCalled(); - }); - - it("should throw an error for an invalid chain", async () => { - // @ts-ignore - mockGetConfig.mockResolvedValueOnce({}); - - await expect(getChainIdFromChain("not_a_real_chain")).rejects.toEqual({ - message: "Chain not_a_real_chain is not found", - statusCode: 400, - code: "INVALID_CHAIN", - }); - }); -}); diff --git a/tests/unit/gcp-kms.test.ts b/tests/unit/gcp-kms.test.ts deleted file mode 100644 index fbb71bff8..000000000 --- a/tests/unit/gcp-kms.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { beforeAll, expect, test, vi } from "vitest"; - -import { ANVIL_CHAIN, anvilTestClient } from "../shared/chain.ts"; -import { typedData } from "../shared/typed-data.ts"; -import { verifyTypedData } from "thirdweb"; -import { verifyEOASignature } from "thirdweb/auth"; -import { - prepareTransaction, - sendAndConfirmTransaction, -} from "thirdweb/transaction"; -import { toUnits, toWei } from "thirdweb/utils"; -import { getWalletBalance } from "thirdweb/wallets"; -import { getGcpKmsAccount } from "../../src/server/utils/wallets/get-gcp-kms-account"; -import { TEST_GCP_KMS_CONFIG } from "../shared/gcp-kms"; -import { TEST_CLIENT } from "../shared/client"; - -let account: Awaited>; - -vi.mock("../../utils/chain", () => ({ - getChain: async () => ANVIL_CHAIN, -})); - -beforeAll(async () => { - account = await getGcpKmsAccount({ - client: TEST_CLIENT, - name: TEST_GCP_KMS_CONFIG.resourcePath, - clientOptions: { - credentials: { - client_email: TEST_GCP_KMS_CONFIG.email, - private_key: TEST_GCP_KMS_CONFIG.pk, - }, - }, - }); -}); - -test("account address is valid", () => { - expect(account.address).toMatch(/^0x[a-fA-F0-9]{40}$/); -}); - -test("sign message", async () => { - const message = "hello world"; - const signature = await account.signMessage({ message }); - - expect(signature).toMatch(/^0x[a-fA-F0-9]{130}$/); - - const isValid = await verifyEOASignature({ - address: account.address, - message, - signature, - }); - expect(isValid).toBe(true); -}); - -test("sign transaction", async () => { - const tx = { - chainId: ANVIL_CHAIN.id, - maxFeePerGas: toUnits("20", 9), - gas: 21000n, - to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", - value: toUnits("1", 18), - }; - - expect(account.signTransaction).toBeDefined(); - - const signedTx = await account.signTransaction?.(tx); - expect(signedTx).toMatch(/^0x[a-fA-F0-9]+$/); -}); - -test("sign typed data", async () => { - const signature = await account.signTypedData({ - ...typedData.basic, - primaryType: "Mail", - }); - expect(signature).toMatch(/^0x[a-fA-F0-9]{130}$/); - - const isValid = await verifyTypedData({ - address: account.address, - ...typedData.basic, - primaryType: "Mail", - signature, - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - }); - expect(isValid).toBe(true); -}); - -test("send transaction", async () => { - const recipient = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8"; - - await anvilTestClient.setBalance({ - address: account.address, - value: toWei("10"), - }); - - const startingBalance = await getWalletBalance({ - address: account.address, - chain: ANVIL_CHAIN, - client: TEST_CLIENT, - }); - - const startingBalanceRecipient = await getWalletBalance({ - address: recipient, - chain: ANVIL_CHAIN, - client: TEST_CLIENT, - }); - - const tx = prepareTransaction({ - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - to: recipient, - value: toUnits("1", 18), - }); - - const result = await sendAndConfirmTransaction({ - account, - transaction: tx, - }); - - expect(result.transactionHash).toMatch(/^0x[a-fA-F0-9]{64}$/); - - const endingBalance = await getWalletBalance({ - address: account.address, - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - }); - const endingBalanceRecipient = await getWalletBalance({ - address: recipient, - client: TEST_CLIENT, - chain: ANVIL_CHAIN, - }); - - expect(endingBalance.value).toBeLessThan(startingBalance.value); - expect(endingBalanceRecipient.value).toBeGreaterThan( - startingBalanceRecipient.value, - ); -}); diff --git a/tests/unit/gcp-resource-path.test.ts b/tests/unit/gcp-resource-path.test.ts deleted file mode 100644 index c7097868c..000000000 --- a/tests/unit/gcp-resource-path.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { - getGcpKmsResourcePath, - splitGcpKmsResourcePath, -} from "../../src/server/utils/wallets/gcp-kms-resource-path"; - -describe("splitGcpKmsResourcePath", () => { - it("should correctly split a valid GCP KMS resource path", () => { - const resourcePath = - "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key/cryptoKeyVersions/1"; - const result = splitGcpKmsResourcePath(resourcePath); - expect(result).toEqual({ - projectId: "my-project", - locationId: "us-central1", - keyRingId: "my-keyring", - cryptoKeyId: "my-key", - versionId: "1", - }); - }); - - it("should throw an error for a resource path with insufficient parts", () => { - const resourcePath = - "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key"; - expect(() => splitGcpKmsResourcePath(resourcePath)).toThrow( - "Invalid GCP KMS resource path", - ); - }); - - it("should handle resource paths with additional parts", () => { - const resourcePath = - "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key/cryptoKeyVersions/1/extra/parts"; - const result = splitGcpKmsResourcePath(resourcePath); - expect(result).toEqual({ - projectId: "my-project", - locationId: "us-central1", - keyRingId: "my-keyring", - cryptoKeyId: "my-key", - versionId: "1", - }); - }); - - it("should handle resource paths with hyphens and numbers in IDs", () => { - const resourcePath = - "projects/my-project-123/locations/us-east1-b/keyRings/key-ring-2/cryptoKeys/crypto-key-3/cryptoKeyVersions/2"; - const result = splitGcpKmsResourcePath(resourcePath); - expect(result).toEqual({ - projectId: "my-project-123", - locationId: "us-east1-b", - keyRingId: "key-ring-2", - cryptoKeyId: "crypto-key-3", - versionId: "2", - }); - }); -}); - -describe("getGcpKmsResourcePath", () => { - it("should correctly construct a GCP KMS resource path", () => { - const options = { - projectId: "my-project", - locationId: "us-central1", - keyRingId: "my-keyring", - cryptoKeyId: "my-key", - versionId: "1", - }; - const result = getGcpKmsResourcePath(options); - expect(result).toBe( - "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key/cryptoKeyVersions/1", - ); - }); - - it("should handle IDs with hyphens and numbers", () => { - const options = { - projectId: "my-project-123", - locationId: "us-east1-b", - keyRingId: "key-ring-2", - cryptoKeyId: "crypto-key-3", - versionId: "2", - }; - const result = getGcpKmsResourcePath(options); - expect(result).toBe( - "projects/my-project-123/locations/us-east1-b/keyRings/key-ring-2/cryptoKeys/crypto-key-3/cryptoKeyVersions/2", - ); - }); -}); diff --git a/tests/unit/math.test.ts b/tests/unit/math.test.ts deleted file mode 100644 index 3a27e56f7..000000000 --- a/tests/unit/math.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { BigIntMath, getPercentile } from "../../src/shared/utils/math"; - -describe("getPercentile", () => { - it("should correctly calculate the p50 (median) of a sorted array", () => { - const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - expect(getPercentile(numbers, 50)).toBe(5); - }); - - it("should correctly calculate the p90 of a sorted array", () => { - const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - expect(getPercentile(numbers, 90)).toBe(9); - }); - - it("should handle arrays with even number of elements", () => { - const numbers = [10, 20, 30, 40, 50, 60, 70, 80]; - expect(getPercentile(numbers, 50)).toBe(40); - }); - - it("should handle single element array", () => { - const numbers = [1]; - expect(getPercentile(numbers, 50)).toBe(1); - }); - - it("should handle empty array", () => { - const numbers: number[] = []; - expect(getPercentile(numbers, 50)).toBe(0); - }); -}); - -describe("BigIntMath", () => { - describe("min", () => { - it("should return the smaller of two positive numbers", () => { - const a = 5n; - const b = 10n; - expect(BigIntMath.min(a, b)).toBe(5n); - }); - - it("should return the smaller of two negative numbers", () => { - const a = -10n; - const b = -5n; - expect(BigIntMath.min(a, b)).toBe(-10n); - }); - - it("should handle equal numbers", () => { - const a = 5n; - const b = 5n; - expect(BigIntMath.min(a, b)).toBe(5n); - }); - - it("should handle zero and positive number", () => { - const a = 0n; - const b = 5n; - expect(BigIntMath.min(a, b)).toBe(0n); - }); - - it("should handle zero and negative number", () => { - const a = 0n; - const b = -5n; - expect(BigIntMath.min(a, b)).toBe(-5n); - }); - - it("should handle very large numbers", () => { - const a = BigInt(Number.MAX_SAFE_INTEGER) * 2n; - const b = BigInt(Number.MAX_SAFE_INTEGER); - expect(BigIntMath.min(a, b)).toBe(b); - }); - }); - - describe("max", () => { - it("should return the larger of two positive numbers", () => { - const a = 5n; - const b = 10n; - expect(BigIntMath.max(a, b)).toBe(10n); - }); - - it("should return the larger of two negative numbers", () => { - const a = -10n; - const b = -5n; - expect(BigIntMath.max(a, b)).toBe(-5n); - }); - - it("should handle equal numbers", () => { - const a = 5n; - const b = 5n; - expect(BigIntMath.max(a, b)).toBe(5n); - }); - - it("should handle zero and positive number", () => { - const a = 0n; - const b = 5n; - expect(BigIntMath.max(a, b)).toBe(5n); - }); - - it("should handle zero and negative number", () => { - const a = 0n; - const b = -5n; - expect(BigIntMath.max(a, b)).toBe(0n); - }); - - it("should handle very large numbers", () => { - const a = BigInt(Number.MAX_SAFE_INTEGER) * 2n; - const b = BigInt(Number.MAX_SAFE_INTEGER); - expect(BigIntMath.max(a, b)).toBe(a); - }); - }); -}); diff --git a/tests/unit/migrationV5.test.ts b/tests/unit/migrationV5.test.ts deleted file mode 100644 index e9d31d5b2..000000000 --- a/tests/unit/migrationV5.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { describe, expect, it } from "vitest"; - -import { getSdk } from "../../src/shared/utils/cache/get-sdk"; -import { getChain } from "../../src/shared/utils/chain"; -import { thirdwebClient } from "../../src/shared/utils/sdk"; -import { getWalletBalance } from "thirdweb/wallets"; -import { getBalance } from "thirdweb/extensions/erc20"; -import { getContractEvents } from "thirdweb"; -import { getContract as getContractV5 } from "thirdweb"; -import { getContract as getContractV4 } from "../../src/shared/utils/cache/get-contract"; -import { maybeBigInt } from "../../src/shared/utils/primitive-types"; -import { toContractEventV4Schema } from "../../src/server/schemas/event"; - -/** - * todo: remove all dependencies including tests after everything is migrated properly. - */ -describe("migration from v4 to v5", () => { - it("get-contract: check difference in contract interface", async () => { - const chainId = 137; - const contractAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"; - const walletAddress = "0xE52772e599b3fa747Af9595266b527A31611cebd"; - - // v4 - const sdk = await getSdk({ chainId }); - const contractV4 = await sdk.getContract(contractAddress); - const balV4 = await contractV4.erc20.balanceOf(walletAddress); - - /** - * v5 - * Doesnt have nested helper functions and is separated into individual "extensions" - */ - const contractV5 = getContractV5({ - client: thirdwebClient, - address: contractAddress, - chain: await getChain(chainId), - }); - const balV5 = await getBalance({ - contract: contractV5, - address: walletAddress, - }); - - expect(balV4.name).eq(balV5.name); - expect(balV4.symbol).eq(balV5.symbol); - expect(balV4.decimals).eq(balV5.decimals); - expect(balV4.displayValue).eq(balV5.displayValue); - expect(balV4.value.toString()).eq(balV5.value.toString()); - }); - - it("tests for get-balance(native token)", async () => { - const chainId = 137; - const walletAddress = "0xE52772e599b3fa747Af9595266b527A31611cebd"; - - // v4 - const sdk = await getSdk({ chainId }); - const balanceV4 = await sdk.getBalance(walletAddress); - - // v5. - const balanceV5 = await getWalletBalance({ - client: thirdwebClient, - address: walletAddress, - chain: await getChain(chainId), - }); - - expect(balanceV4.name).eq(balanceV5.name); - expect(balanceV4.symbol).eq(balanceV5.symbol); - expect(balanceV4.decimals).eq(balanceV5.decimals); - expect(balanceV4.displayValue).eq(balanceV5.displayValue); - expect(balanceV4.value.toString()).eq(balanceV5.value.toString()); - }); - - it("tests for events/get-all", async () => { - const chainId = 137; - const contractAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"; - const fromBlock = 65334800; - const toBlock = 65334801; - const order = Math.random() > 0.5 ? "asc" : "desc"; - - // v4 - const contractV4 = await getContractV4({ chainId, contractAddress }); - const eventsV4 = await contractV4.events.getAllEvents({ - fromBlock, - toBlock, - order, - }); - - // v5. - const contractV5 = getContractV5({ - client: thirdwebClient, - address: contractAddress, - chain: await getChain(chainId), - }); - const eventsV5Raw = await getContractEvents({ - contract: contractV5, - fromBlock: maybeBigInt(fromBlock?.toString()), - toBlock: maybeBigInt(toBlock?.toString()), - }); - - const eventsV5 = eventsV5Raw.map(toContractEventV4Schema).sort((a, b) => { - return order === "desc" - ? b.transaction.blockNumber - a.transaction.blockNumber - : a.transaction.blockNumber - b.transaction.blockNumber; - }); - - // check two array ordering is the same - expect(eventsV4.length).eq(eventsV5.length); - for (let i = 0; i < eventsV4.length; i++) { - expect(eventsV4[i].transaction.transactionHash).eq( - eventsV5[i].transaction.transactionHash, - ); - } - }); -}); diff --git a/tests/unit/schema.test.ts b/tests/unit/schema.test.ts deleted file mode 100644 index c1de80d36..000000000 --- a/tests/unit/schema.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Value } from "@sinclair/typebox/value"; -import { describe, expect, it } from "vitest"; -import { - AddressSchema, - HexSchema, - TransactionHashSchema, -} from "../../src/server/schemas/address"; -import { chainIdOrSlugSchema } from "../../src/server/schemas/chain"; - -// Test cases -describe("chainIdOrSlugSchema", () => { - it("should validate valid chain IDs", () => { - expect(Value.Check(chainIdOrSlugSchema, "137")).toBe(true); - expect(Value.Check(chainIdOrSlugSchema, "80002")).toBe(true); - }); - - it("should validate valid slugs", () => { - expect(Value.Check(chainIdOrSlugSchema, "polygon")).toBe(true); - expect(Value.Check(chainIdOrSlugSchema, "arbitrum-nova")).toBe(true); - expect(Value.Check(chainIdOrSlugSchema, "polygon-amoy-testnet")).toBe(true); - expect(Value.Check(chainIdOrSlugSchema, "some_slug_with_underscore")).toBe( - true, - ); - }); - - it("should validate valid mixed slugs", () => { - expect(Value.Check(chainIdOrSlugSchema, "polygon-test-123")).toBe(true); - expect(Value.Check(chainIdOrSlugSchema, "arbitrum-1-test")).toBe(true); - }); - - it("should invalidate invalid inputs", () => { - expect(Value.Check(chainIdOrSlugSchema, "")).toBe(false); // Empty string - expect(Value.Check(chainIdOrSlugSchema, "!invalid")).toBe(false); // Invalid characters - expect(Value.Check(chainIdOrSlugSchema, "space test")).toBe(false); // Spaces not allowed - expect( - Value.Check( - chainIdOrSlugSchema, - "too-long-slug-abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", - ), - ).toBe(false); // Exceeds length - expect(Value.Check(chainIdOrSlugSchema, "123-!@#")).toBe(false); // Special characters not allowed - }); -}); - -describe("AddressSchema", () => { - it("should validate valid addresses", () => { - expect( - Value.Check(AddressSchema, "0x000000000000000000000000000000000000dead"), - ).toBe(true); - }); - - it("should invalidate invalid addresses", () => { - expect( - Value.Check(AddressSchema, "0xG1234567890abcdef1234567890abcdef12345678"), - ).toBe(false); // Invalid character 'G' - expect( - Value.Check(AddressSchema, "1234567890abcdef1234567890abcdef12345678"), - ).toBe(false); // Missing '0x' prefix - expect(Value.Check(AddressSchema, "0x12345")).toBe(false); // Too short - expect( - Value.Check(AddressSchema, "0x1234567890abcdef1234567890abcdef123456789"), - ).toBe(false); // Too long - }); -}); - -describe("TransactionHashSchema", () => { - it("should validate valid transaction hashes", () => { - expect( - Value.Check( - TransactionHashSchema, - "0x1f31b57601a6f90312fd5e57a2924bc8333477de579ee37b197a0681ab438431", - ), - ).toBe(true); - expect( - Value.Check( - TransactionHashSchema, - "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - ), - ).toBe(true); - }); - - it("should invalidate invalid transaction hashes", () => { - expect( - Value.Check( - TransactionHashSchema, - "0xG1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - ), - ).toBe(false); // Invalid character 'G' - expect( - Value.Check( - TransactionHashSchema, - "0x1234567890abcdef1234567890abcdef12345678", - ), - ).toBe(false); // Too short - expect( - Value.Check( - TransactionHashSchema, - "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1", - ), - ).toBe(false); // Too long - }); -}); - -describe("HexSchema", () => { - it("should validate valid hex strings", () => { - expect(Value.Check(HexSchema, "0x68656c6c6f20776f726c64")).toBe(true); - expect(Value.Check(HexSchema, "0x")).toBe(true); // Empty hex string is valid - }); - - it("should invalidate invalid hex strings", () => { - expect(Value.Check(HexSchema, "0xG123")).toBe(false); // Invalid character 'G' - expect(Value.Check(HexSchema, "123456")).toBe(false); // Missing '0x' prefix - }); -}); diff --git a/tests/unit/send-transaction-worker.test.ts b/tests/unit/send-transaction-worker.test.ts deleted file mode 100644 index 5fb0a5dcb..000000000 --- a/tests/unit/send-transaction-worker.test.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { Hex } from "thirdweb"; -import { describe, expect, it } from "vitest"; -import { _updateGasFees } from "../worker/tasks/sendTransactionWorker"; - -describe("_updateGasFees", () => { - const base = { - // Irrelevant values for testing. - chainId: 1, - data: "0x0" as Hex, - gas: 21000n, - to: undefined, - nonce: undefined, - accessList: undefined, - value: undefined, - }; - - it("returns the original transaction on first send (resendCount = 0)", () => { - let result = _updateGasFees({ ...base, gasPrice: 100n }, 0, undefined); - expect(result.gasPrice).toEqual(100n); - - result = _updateGasFees( - { ...base, maxFeePerGas: 100n, maxPriorityFeePerGas: 10n }, - 0, - undefined, - ); - expect(result.maxFeePerGas).toEqual(100n); - expect(result.maxPriorityFeePerGas).toEqual(10n); - }); - - it("doubles gasPrice for legacy transactions", () => { - const result = _updateGasFees({ ...base, gasPrice: 100n }, 1, {}); - expect(result.gasPrice).toBe(200n); - }); - - it("caps gasPrice multiplier at 10x", () => { - const result = _updateGasFees({ ...base, gasPrice: 100n }, 10, {}); - expect(result.gasPrice).toBe(1000n); - }); - - it("updates maxPriorityFeePerGas and maxFeePerGas for EIP-1559 transactions", () => { - const result = _updateGasFees( - { ...base, maxFeePerGas: 100n, maxPriorityFeePerGas: 10n }, - 3, - {}, - ); - expect(result.maxPriorityFeePerGas).toBe(60n); - expect(result.maxFeePerGas).toBe(260n); - }); - - it("respects overrides for maxPriorityFeePerGas", () => { - const result = _updateGasFees( - { ...base, maxFeePerGas: 100n, maxPriorityFeePerGas: 10n }, - 3, - { maxPriorityFeePerGas: 10n }, - ); - expect(result.maxPriorityFeePerGas).toBe(10n); // matches override - expect(result.maxFeePerGas).toBe(210n); - }); - - it("respects overrides for maxFeePerGas", () => { - const result = _updateGasFees( - { ...base, maxFeePerGas: 100n, maxPriorityFeePerGas: 10n }, - 3, - { maxFeePerGas: 100n }, - ); - expect(result.maxPriorityFeePerGas).toBe(60n); - expect(result.maxFeePerGas).toBe(100n); // matches override - }); - - it("returns correct values when only maxPriorityFeePerGas is set", () => { - const result = _updateGasFees( - { ...base, maxPriorityFeePerGas: 10n }, - 3, - {}, - ); - expect(result.maxPriorityFeePerGas).toBe(60n); - expect(result.maxFeePerGas).toBeUndefined(); - }); - - it("returns correct values when only maxFeePerGas is set", () => { - const result = _updateGasFees({ ...base, maxFeePerGas: 80n }, 3, {}); - expect(result.maxFeePerGas).toBe(160n); - }); -}); diff --git a/tests/unit/swr.test.ts b/tests/unit/swr.test.ts deleted file mode 100644 index 33fb485ef..000000000 --- a/tests/unit/swr.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; -import { createSWRCache, type SWRCache } from "../../src/shared/lib/cache/swr"; - -describe("SWRCache", () => { - let cache: SWRCache; - let fetchCount: number; - let now: number; - - // Use vi.setSystemTime() instead of real timeouts - beforeEach(() => { - now = Date.now(); - vi.setSystemTime(now); - cache = createSWRCache({ ttlMs: 100 }); // 100ms TTL for tests - fetchCount = 0; - }); - - const createFetcher = () => { - return async () => { - fetchCount++; - return fetchCount; - }; - }; - - test("should fetch and cache new values", async () => { - const fetcher = createFetcher(); - const value = await cache.get("key1", fetcher); - - expect(value).toBe(1); - expect(fetchCount).toBe(1); - - // Second get should use cache - const cachedValue = await cache.get("key1", fetcher); - expect(cachedValue).toBe(1); - expect(fetchCount).toBe(1); - }); - - test("should handle multiple concurrent requests", async () => { - const fetcher = createFetcher(); - const results = await Promise.all([ - cache.get("key1", fetcher), - cache.get("key1", fetcher), - cache.get("key1", fetcher), - ]); - - expect(results).toEqual([1, 1, 1]); - expect(fetchCount).toBe(1); - }); - - test("should handle multiple concurrent failed requests", async () => { - let attempts = 0; - const errorFetcher = async () => { - attempts++; - throw new Error(`Attempt ${attempts} failed`); - }; - - const promises = Promise.all([ - expect(cache.get("key1", errorFetcher)).rejects.toThrow( - "Attempt 1 failed", - ), - expect(cache.get("key1", errorFetcher)).rejects.toThrow( - "Attempt 1 failed", - ), - expect(cache.get("key1", errorFetcher)).rejects.toThrow( - "Attempt 1 failed", - ), - ]); - - await promises; - expect(attempts).toBe(1); - }); - - test("should revalidate stale data in background", async () => { - const fetcher = createFetcher(); - - // Initial fetch - const initial = await cache.get("key1", fetcher); - expect(initial).toBe(1); - expect(fetchCount).toBe(1); - - // Move time forward past TTL - vi.setSystemTime(now + 200); - - // Should get stale data immediately while revalidating - const stalePromise = cache.get("key1", fetcher); - - // Value should be returned immediately (stale) - const stale = await stalePromise; - expect(stale).toBe(1); - - // Let revalidation complete - await new Promise((resolve) => setTimeout(resolve, 0)); - - // Should have fresh data now - const fresh = await cache.get("key1", fetcher); - expect(fresh).toBe(2); - expect(fetchCount).toBe(2); - }); - - test("should respect max entries", async () => { - const cache = createSWRCache({ maxEntries: 2 }); - const fetcher = createFetcher(); - - await cache.get("key1", fetcher); - await cache.get("key2", fetcher); - await cache.get("key3", fetcher); - - // Try to get first key (should trigger new fetch) - fetchCount = 0; - await cache.get("key1", fetcher); - expect(fetchCount).toBe(1); - }); - - test("should handle errors during background revalidation", async () => { - const fetcher = createFetcher(); - const errorFetcher = async () => { - throw new Error("Revalidation failed"); - }; - - // Initial successful fetch - const initial = await cache.get("key1", fetcher); - expect(initial).toBe(1); - - // Move time forward past TTL - vi.setSystemTime(now + 200); - - // Should return stale data even if revalidation fails - const stale = await cache.get("key1", errorFetcher); - expect(stale).toBe(1); - - // Let background revalidation attempt complete - await new Promise((resolve) => setTimeout(resolve, 0)); - - // Should still have stale data after failed revalidation - const stillStale = await cache.get("key1", errorFetcher); - expect(stillStale).toBe(1); - }); - - test("should handle rapid successive requests on stale data", async () => { - const fetcher = createFetcher(); - - // Initial fetch - await cache.get("key1", fetcher); - - // Move time forward past TTL - vi.setSystemTime(now + 200); - - // Create 10 rapid requests - const promises = Array.from({ length: 10 }, () => - cache.get("key1", fetcher), - ); - const results = await Promise.all(promises); - - // All should have same value - expect(results.every((r) => r === 1)).toBe(true); - // Should only trigger one background revalidation - expect(fetchCount).toBe(2); - }); - - afterEach(() => { - vi.useRealTimers(); - }); -}); diff --git a/tests/unit/validator.test.ts b/tests/unit/validator.test.ts deleted file mode 100644 index f15612258..000000000 --- a/tests/unit/validator.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { isValidWebhookUrl } from "../../src/server/utils/validator"; - -describe("isValidWebhookUrl", () => { - it("should return true for a valid HTTPS URL", () => { - expect(isValidWebhookUrl("https://example.com/")).toBe(true); - }); - - it("should return false for an HTTP URL", () => { - expect(isValidWebhookUrl("http://example.com/")).toBe(false); - }); - - it("should return false for a URL without protocol", () => { - expect(isValidWebhookUrl("example.com")).toBe(false); - }); - - it("should return false for an invalid URL", () => { - expect(isValidWebhookUrl("invalid-url")).toBe(false); - }); - - it("should return false for a URL with a different protocol", () => { - expect(isValidWebhookUrl("ftp://example.com")).toBe(false); - }); - - it("should return false for an empty string", () => { - expect(isValidWebhookUrl("")).toBe(false); - }); - - it("should return true for a http localhost", () => { - expect(isValidWebhookUrl("http://localhost:3000/")).toBe(true); - expect(isValidWebhookUrl("http://0.0.0.0:3000/")).toBe(true); - expect(isValidWebhookUrl("http://user:pass@127.0.0.1:3000/")).toBe(true); - }); -}); diff --git a/tests/unit/webhook.test.ts b/tests/unit/webhook.test.ts deleted file mode 100644 index adc0d5dc0..000000000 --- a/tests/unit/webhook.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Webhooks } from "@prisma/client"; -import { describe, expect, it } from "vitest"; -import { WebhooksEventTypes } from "../../src/shared/schemas/webhooks"; -import { generateRequestHeaders } from "../../src/shared/utils/webhook"; -import { generateSecretHmac256 } from "../../src/shared/utils/customAuthHeader"; - -describe("generateSecretHmac256", () => { - it("should generate a valid MAC header with correct structure and values", () => { - const timestamp = new Date("2024-01-01"); - const nonce = "6b98df0d-5f33-4121-96cb-77a0b9df2bbe"; - - const result = generateSecretHmac256({ - webhookUrl: "https://example.com/webhook", - body: { bodyArgName: "bodyArgValue" }, - timestamp, - nonce, - clientId: "testClientId", - clientSecret: "testClientSecret", - }); - - expect(result).toEqual( - `MAC id="testClientId" ts="1704067200000" nonce="6b98df0d-5f33-4121-96cb-77a0b9df2bbe" bodyhash="4Mknknli8NGCwC28djVf/Qa8vN3wtvfeRGKVha0MgjQ=" mac="Qbe9H5yeVvywoL3l1RFLBDC0YvDOCQnytNSlbTWXzEk="`, - ); - }); -}); - -describe("generateRequestHeaders", () => { - const webhook: Webhooks = { - id: 42, - name: "test webhook", - url: "https://www.example.com/webhook", - secret: "test-secret-string", - eventType: WebhooksEventTypes.SENT_TX, - createdAt: new Date(), - updatedAt: new Date(), - revokedAt: null, - }; - const body = { - name: "Alice", - age: 25, - occupation: ["Founder", "Developer"], - }; - const timestamp = new Date("2024-01-01"); - - it("Generate a consistent webhook header", () => { - const result = generateRequestHeaders({ webhook, body, timestamp }); - - expect(result).toEqual({ - Accept: "application/json", - Authorization: "Bearer test-secret-string", - "Content-Type": "application/json", - "x-engine-signature": - "ca272da65f1145b9cfadab6d55086ee458eccc03a2c5f7f5ea84094d95b219cc", - "x-engine-timestamp": "1704067200", - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index 6fb9b351a..7f0669608 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,29 +1,36 @@ { "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "node", - "outDir": "dist", + // Enable latest features + "lib": ["ESNext"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices "strict": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, "skipLibCheck": true, - "allowJs": true, - "resolveJsonModule": true - }, - "ts-node": { - "esm": true, - "experimentalSpecifierResolution": "node" - }, - "include": [ - "src/server/**/*.ts", - "src/server/**/*.d.ts", - "src/server/**/*.js", - "src/utils/env.ts", - "src/**/*.ts", - "src/**/*.js", - "src/**/*.d.ts" - ], - "exclude": ["node_modules", "tests/tests/**/*.ts"] + "noFallthroughCasesInSwitch": true, + + // Some stricter flags + "noUnusedLocals": true, + "noUnusedParameters": true, + + /* Base Options: */ + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + + /* Strictness */ + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + "noErrorTruncation": true + } } diff --git a/vitest.config.ts b/vitest.config.ts deleted file mode 100644 index d2f6a0cda..000000000 --- a/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: ["tests/unit/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], - exclude: ["tests/e2e/**/*"], - globalSetup: ["./vitest.global-setup.ts"], - mockReset: true, - }, -}); diff --git a/vitest.global-setup.ts b/vitest.global-setup.ts deleted file mode 100644 index c09752690..000000000 --- a/vitest.global-setup.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { config } from "dotenv"; -import path from "node:path"; - -config({ - path: [path.resolve(".env.test.local"), path.resolve(".env.test")], -}); - -// import { createServer } from "prool"; -// import { anvil } from "prool/instances"; - -// export async function setup() { -// const server = createServer({ -// instance: anvil(), -// port: 8645, // Choose an appropriate port -// }); -// await server.start(); -// // Return a teardown function that will be called after all tests are complete -// return async () => { -// await server.stop(); -// }; -// } - -export async function setup() {} diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 8e200fea4..000000000 --- a/yarn.lock +++ /dev/null @@ -1,11368 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@account-abstraction/contracts@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@account-abstraction/contracts/-/contracts-0.5.0.tgz#a089aee7b4c446251fbbce7df315bbf8f659e37f" - integrity sha512-CKyS9Zh5rcYUM+4B6TlaB9+THHzJ+6TY3tWF5QofqvFpqGNvIhF8ddy6wyCmqZw6TB74/yYv7cYD/RarVudfDg== - -"@adraffy/ens-normalize@1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" - integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== - -"@adraffy/ens-normalize@^1.10.1": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz#42cc67c5baa407ac25059fcd7d405cc5ecdb0c33" - integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== - -"@ampproject/remapping@^2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@apidevtools/json-schema-ref-parser@9.0.9": - version "9.0.9" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" - integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w== - dependencies: - "@jsdevtools/ono" "^7.1.3" - "@types/json-schema" "^7.0.6" - call-me-maybe "^1.0.1" - js-yaml "^4.1.0" - -"@aws-crypto/sha256-browser@5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" - integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== - dependencies: - "@aws-crypto/sha256-js" "^5.2.0" - "@aws-crypto/supports-web-crypto" "^5.2.0" - "@aws-crypto/util" "^5.2.0" - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.6.2" - -"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" - integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== - dependencies: - "@aws-crypto/util" "^5.2.0" - "@aws-sdk/types" "^3.222.0" - tslib "^2.6.2" - -"@aws-crypto/supports-web-crypto@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" - integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== - dependencies: - tslib "^2.6.2" - -"@aws-crypto/util@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" - integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== - dependencies: - "@aws-sdk/types" "^3.222.0" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.6.2" - -"@aws-sdk/client-kms@^3.28.0", "@aws-sdk/client-kms@^3.679.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-kms/-/client-kms-3.709.0.tgz#53dbd9bde3f184a11093fe44af3cb00dfdc1284a" - integrity sha512-0qx0Dmsx5JiV4swrBr55lYRIhw6kYQul5aBOnzoGCMx1SFixtBKdzeQYp9lyaU9RPhst6KCE8J6mxG0CxkSQGw== - dependencies: - "@aws-crypto/sha256-browser" "5.2.0" - "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/client-sso-oidc" "3.709.0" - "@aws-sdk/client-sts" "3.709.0" - "@aws-sdk/core" "3.709.0" - "@aws-sdk/credential-provider-node" "3.709.0" - "@aws-sdk/middleware-host-header" "3.709.0" - "@aws-sdk/middleware-logger" "3.709.0" - "@aws-sdk/middleware-recursion-detection" "3.709.0" - "@aws-sdk/middleware-user-agent" "3.709.0" - "@aws-sdk/region-config-resolver" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@aws-sdk/util-endpoints" "3.709.0" - "@aws-sdk/util-user-agent-browser" "3.709.0" - "@aws-sdk/util-user-agent-node" "3.709.0" - "@smithy/config-resolver" "^3.0.13" - "@smithy/core" "^2.5.5" - "@smithy/fetch-http-handler" "^4.1.2" - "@smithy/hash-node" "^3.0.11" - "@smithy/invalid-dependency" "^3.0.11" - "@smithy/middleware-content-length" "^3.0.13" - "@smithy/middleware-endpoint" "^3.2.5" - "@smithy/middleware-retry" "^3.0.30" - "@smithy/middleware-serde" "^3.0.11" - "@smithy/middleware-stack" "^3.0.11" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/node-http-handler" "^3.3.2" - "@smithy/protocol-http" "^4.1.8" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/url-parser" "^3.0.11" - "@smithy/util-base64" "^3.0.0" - "@smithy/util-body-length-browser" "^3.0.0" - "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.30" - "@smithy/util-defaults-mode-node" "^3.0.30" - "@smithy/util-endpoints" "^2.1.7" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-retry" "^3.0.11" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@aws-sdk/client-sso-oidc@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.709.0.tgz#959e4df4070f1d059d8d0cd5b9028d9a46ac7ecf" - integrity sha512-1w6egz17QQy661lNCRmZZlqIANEbD6g2VFAQIJbVwSiu7brg+GUns+mT1eLLLHAMQc1sL0Ds8/ybSK2SrgGgIA== - dependencies: - "@aws-crypto/sha256-browser" "5.2.0" - "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.709.0" - "@aws-sdk/credential-provider-node" "3.709.0" - "@aws-sdk/middleware-host-header" "3.709.0" - "@aws-sdk/middleware-logger" "3.709.0" - "@aws-sdk/middleware-recursion-detection" "3.709.0" - "@aws-sdk/middleware-user-agent" "3.709.0" - "@aws-sdk/region-config-resolver" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@aws-sdk/util-endpoints" "3.709.0" - "@aws-sdk/util-user-agent-browser" "3.709.0" - "@aws-sdk/util-user-agent-node" "3.709.0" - "@smithy/config-resolver" "^3.0.13" - "@smithy/core" "^2.5.5" - "@smithy/fetch-http-handler" "^4.1.2" - "@smithy/hash-node" "^3.0.11" - "@smithy/invalid-dependency" "^3.0.11" - "@smithy/middleware-content-length" "^3.0.13" - "@smithy/middleware-endpoint" "^3.2.5" - "@smithy/middleware-retry" "^3.0.30" - "@smithy/middleware-serde" "^3.0.11" - "@smithy/middleware-stack" "^3.0.11" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/node-http-handler" "^3.3.2" - "@smithy/protocol-http" "^4.1.8" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/url-parser" "^3.0.11" - "@smithy/util-base64" "^3.0.0" - "@smithy/util-body-length-browser" "^3.0.0" - "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.30" - "@smithy/util-defaults-mode-node" "^3.0.30" - "@smithy/util-endpoints" "^2.1.7" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-retry" "^3.0.11" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@aws-sdk/client-sso@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.709.0.tgz#b5b29161e07af6f82afd7a6e750c09b0158d19e3" - integrity sha512-Qxeo8cN0jNy6Wnbqq4wucffAGJM6sJjofoTgNtPA6cC7sPYx7aYC6OAAAo6NaMRY+WywOKdS9Wgjx2QYRxKx7w== - dependencies: - "@aws-crypto/sha256-browser" "5.2.0" - "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.709.0" - "@aws-sdk/middleware-host-header" "3.709.0" - "@aws-sdk/middleware-logger" "3.709.0" - "@aws-sdk/middleware-recursion-detection" "3.709.0" - "@aws-sdk/middleware-user-agent" "3.709.0" - "@aws-sdk/region-config-resolver" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@aws-sdk/util-endpoints" "3.709.0" - "@aws-sdk/util-user-agent-browser" "3.709.0" - "@aws-sdk/util-user-agent-node" "3.709.0" - "@smithy/config-resolver" "^3.0.13" - "@smithy/core" "^2.5.5" - "@smithy/fetch-http-handler" "^4.1.2" - "@smithy/hash-node" "^3.0.11" - "@smithy/invalid-dependency" "^3.0.11" - "@smithy/middleware-content-length" "^3.0.13" - "@smithy/middleware-endpoint" "^3.2.5" - "@smithy/middleware-retry" "^3.0.30" - "@smithy/middleware-serde" "^3.0.11" - "@smithy/middleware-stack" "^3.0.11" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/node-http-handler" "^3.3.2" - "@smithy/protocol-http" "^4.1.8" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/url-parser" "^3.0.11" - "@smithy/util-base64" "^3.0.0" - "@smithy/util-body-length-browser" "^3.0.0" - "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.30" - "@smithy/util-defaults-mode-node" "^3.0.30" - "@smithy/util-endpoints" "^2.1.7" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-retry" "^3.0.11" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@aws-sdk/client-sts@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.709.0.tgz#b9ad3c9c6419d0d149b28cdd6c115cc40c4e7906" - integrity sha512-cBAvlPg6yslXNL385UUGFPw+XY+lA9BzioNdIFkMo3fEUlTShogTtiWz4LsyLHoN6LhKojssP9DSmmWKWjCZIw== - dependencies: - "@aws-crypto/sha256-browser" "5.2.0" - "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/client-sso-oidc" "3.709.0" - "@aws-sdk/core" "3.709.0" - "@aws-sdk/credential-provider-node" "3.709.0" - "@aws-sdk/middleware-host-header" "3.709.0" - "@aws-sdk/middleware-logger" "3.709.0" - "@aws-sdk/middleware-recursion-detection" "3.709.0" - "@aws-sdk/middleware-user-agent" "3.709.0" - "@aws-sdk/region-config-resolver" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@aws-sdk/util-endpoints" "3.709.0" - "@aws-sdk/util-user-agent-browser" "3.709.0" - "@aws-sdk/util-user-agent-node" "3.709.0" - "@smithy/config-resolver" "^3.0.13" - "@smithy/core" "^2.5.5" - "@smithy/fetch-http-handler" "^4.1.2" - "@smithy/hash-node" "^3.0.11" - "@smithy/invalid-dependency" "^3.0.11" - "@smithy/middleware-content-length" "^3.0.13" - "@smithy/middleware-endpoint" "^3.2.5" - "@smithy/middleware-retry" "^3.0.30" - "@smithy/middleware-serde" "^3.0.11" - "@smithy/middleware-stack" "^3.0.11" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/node-http-handler" "^3.3.2" - "@smithy/protocol-http" "^4.1.8" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/url-parser" "^3.0.11" - "@smithy/util-base64" "^3.0.0" - "@smithy/util-body-length-browser" "^3.0.0" - "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.30" - "@smithy/util-defaults-mode-node" "^3.0.30" - "@smithy/util-endpoints" "^2.1.7" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-retry" "^3.0.11" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@aws-sdk/core@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.709.0.tgz#d2b3d5b90f6614e3afc109ebdcaaedbb54c2d68b" - integrity sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/core" "^2.5.5" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/property-provider" "^3.1.11" - "@smithy/protocol-http" "^4.1.8" - "@smithy/signature-v4" "^4.2.4" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/util-middleware" "^3.0.11" - fast-xml-parser "4.4.1" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-env@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.709.0.tgz#a7f75375d8a413f9ab2bc42f743b943da6d3362d" - integrity sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ== - dependencies: - "@aws-sdk/core" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/property-provider" "^3.1.11" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-http@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.709.0.tgz#a378cbcc4cf373cc277944f1e84e9952f3884f5d" - integrity sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ== - dependencies: - "@aws-sdk/core" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/fetch-http-handler" "^4.1.2" - "@smithy/node-http-handler" "^3.3.2" - "@smithy/property-provider" "^3.1.11" - "@smithy/protocol-http" "^4.1.8" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/util-stream" "^3.3.2" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-ini@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.709.0.tgz#b01c68d98ce4cc48f79405234e32a9de2f943ea1" - integrity sha512-qCF8IIGcPoUp+Ib3ANhbF5gElxFd+kIrtv2/1tKdvhudMANstQbMiWV0LTH47ZZR6c3as4iSrm09NZnpEoD/pA== - dependencies: - "@aws-sdk/core" "3.709.0" - "@aws-sdk/credential-provider-env" "3.709.0" - "@aws-sdk/credential-provider-http" "3.709.0" - "@aws-sdk/credential-provider-process" "3.709.0" - "@aws-sdk/credential-provider-sso" "3.709.0" - "@aws-sdk/credential-provider-web-identity" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/credential-provider-imds" "^3.2.8" - "@smithy/property-provider" "^3.1.11" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-node@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.709.0.tgz#270a31aae394e6c8fe7d3fdd0b92e7c3a863b933" - integrity sha512-4HRX9KYWPSjO5O/Vg03YAsebKpvTjTvpK1n7zHYBmlLMBLxUrVsL1nNKKC5p2/7OW3RL8XR1ki3QkoV7kGRxUQ== - dependencies: - "@aws-sdk/credential-provider-env" "3.709.0" - "@aws-sdk/credential-provider-http" "3.709.0" - "@aws-sdk/credential-provider-ini" "3.709.0" - "@aws-sdk/credential-provider-process" "3.709.0" - "@aws-sdk/credential-provider-sso" "3.709.0" - "@aws-sdk/credential-provider-web-identity" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/credential-provider-imds" "^3.2.8" - "@smithy/property-provider" "^3.1.11" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-process@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.709.0.tgz#2521f810590f0874c54cc842d3d56f455a728325" - integrity sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q== - dependencies: - "@aws-sdk/core" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/property-provider" "^3.1.11" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-sso@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.709.0.tgz#f0cb855eed86748ff0c9afa06b3a234fb04b3206" - integrity sha512-rYdTDOxazS2GdGScelsRK5CAkktRLCCdRjlwXaxrcW57j749hEqxcF5uTv9RD6WBwInfedcSywErNZB+hylQlg== - dependencies: - "@aws-sdk/client-sso" "3.709.0" - "@aws-sdk/core" "3.709.0" - "@aws-sdk/token-providers" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/property-provider" "^3.1.11" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/credential-provider-web-identity@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.709.0.tgz#c2b03541cb57ae4c7d6abdca98f99a6a56833ea6" - integrity sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA== - dependencies: - "@aws-sdk/core" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/property-provider" "^3.1.11" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/middleware-host-header@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.709.0.tgz#f44f5c62f9bd7e5a443603fed68143d2d9725219" - integrity sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/middleware-logger@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.709.0.tgz#b9a0b016b7ae09cb502cc4faf45964d4b5745824" - integrity sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/middleware-recursion-detection@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.709.0.tgz#d7dc253d4858d496caeb12dd6cddd87b250fb98b" - integrity sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/middleware-user-agent@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.709.0.tgz#2a467f14b3f4a9270bcdfde32e3d4e38701aaafe" - integrity sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw== - dependencies: - "@aws-sdk/core" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@aws-sdk/util-endpoints" "3.709.0" - "@smithy/core" "^2.5.5" - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/region-config-resolver@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.709.0.tgz#64547b333842e5804e1793e4d6d29578c0b34a68" - integrity sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/types" "^3.7.2" - "@smithy/util-config-provider" "^3.0.0" - "@smithy/util-middleware" "^3.0.11" - tslib "^2.6.2" - -"@aws-sdk/token-providers@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.709.0.tgz#56305ab187660a711fd172c329dc953ca754fa80" - integrity sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/property-provider" "^3.1.11" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/types@3.709.0", "@aws-sdk/types@^3.222.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.709.0.tgz#f8d7ab07e253d3ed0e3b360e09fc67c7430a73b9" - integrity sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@aws-sdk/util-endpoints@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.709.0.tgz#32dfe339d78b699ada68392bbb3bec25441bae5c" - integrity sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/types" "^3.7.2" - "@smithy/util-endpoints" "^2.1.7" - tslib "^2.6.2" - -"@aws-sdk/util-locate-window@^3.0.0": - version "3.693.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz#1160f6d055cf074ca198eb8ecf89b6311537ad6c" - integrity sha512-ttrag6haJLWABhLqtg1Uf+4LgHWIMOVSYL+VYZmAp2v4PUGOwWmWQH0Zk8RM7YuQcLfH/EoR72/Yxz6A4FKcuw== - dependencies: - tslib "^2.6.2" - -"@aws-sdk/util-user-agent-browser@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.709.0.tgz#ad6e867bdd348923ec10ddd6c37740ce0986cd8f" - integrity sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg== - dependencies: - "@aws-sdk/types" "3.709.0" - "@smithy/types" "^3.7.2" - bowser "^2.11.0" - tslib "^2.6.2" - -"@aws-sdk/util-user-agent-node@3.709.0": - version "3.709.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.709.0.tgz#7ff5a508bcad49963a550acadcced43d7af9960d" - integrity sha512-trBfzSCVWy7ILgqhEXgiuM7hfRCw4F4a8IK90tjk9YL0jgoJ6eJuOp7+DfCtHJaygoBxD3cdMFkOu+lluFmGBA== - dependencies: - "@aws-sdk/middleware-user-agent" "3.709.0" - "@aws-sdk/types" "3.709.0" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.2": - version "7.26.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" - integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== - dependencies: - "@babel/helper-validator-identifier" "^7.25.9" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/generator@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.3.tgz#ab8d4360544a425c90c248df7059881f4b2ce019" - integrity sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ== - dependencies: - "@babel/parser" "^7.26.3" - "@babel/types" "^7.26.3" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/helper-module-imports@^7.16.7": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" - integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== - dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== - -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== - -"@babel/parser@^7.20.15", "@babel/parser@^7.25.4", "@babel/parser@^7.25.9", "@babel/parser@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234" - integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA== - dependencies: - "@babel/types" "^7.26.3" - -"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" - integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" - integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== - dependencies: - "@babel/code-frame" "^7.25.9" - "@babel/parser" "^7.25.9" - "@babel/types" "^7.25.9" - -"@babel/traverse@^7.25.9": - version "7.26.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.4.tgz#ac3a2a84b908dde6d463c3bfa2c5fdc1653574bd" - integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/generator" "^7.26.3" - "@babel/parser" "^7.26.3" - "@babel/template" "^7.25.9" - "@babel/types" "^7.26.3" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.3": - version "7.26.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.3.tgz#37e79830f04c2b5687acc77db97fbc75fb81f3c0" - integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA== - dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@biomejs/biome@^1.9.2": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-1.9.4.tgz#89766281cbc3a0aae865a7ff13d6aaffea2842bf" - integrity sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog== - optionalDependencies: - "@biomejs/cli-darwin-arm64" "1.9.4" - "@biomejs/cli-darwin-x64" "1.9.4" - "@biomejs/cli-linux-arm64" "1.9.4" - "@biomejs/cli-linux-arm64-musl" "1.9.4" - "@biomejs/cli-linux-x64" "1.9.4" - "@biomejs/cli-linux-x64-musl" "1.9.4" - "@biomejs/cli-win32-arm64" "1.9.4" - "@biomejs/cli-win32-x64" "1.9.4" - -"@biomejs/cli-darwin-arm64@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz#dfa376d23a54a2d8f17133c92f23c1bf2e62509f" - integrity sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw== - -"@biomejs/cli-darwin-x64@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz#eafc2ce3849d385fc02238aad1ca4a73395a64d9" - integrity sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg== - -"@biomejs/cli-linux-arm64-musl@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz#d780c3e01758fc90f3268357e3f19163d1f84fca" - integrity sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA== - -"@biomejs/cli-linux-arm64@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz#8ed1dd0e89419a4b66a47f95aefb8c46ae6041c9" - integrity sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g== - -"@biomejs/cli-linux-x64-musl@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz#f36982b966bd671a36671e1de4417963d7db15fb" - integrity sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg== - -"@biomejs/cli-linux-x64@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz#a0a7f56680c76b8034ddc149dbf398bdd3a462e8" - integrity sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg== - -"@biomejs/cli-win32-arm64@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz#e2ef4e0084e76b7e26f0fc887c5ef1265ea56200" - integrity sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg== - -"@biomejs/cli-win32-x64@1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz#4c7afa90e3970213599b4095e62f87e5972b2340" - integrity sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA== - -"@blocto/sdk@0.10.2": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@blocto/sdk/-/sdk-0.10.2.tgz#d29c652d25ac367a3c8d5fabdcb770b5cbb07c1c" - integrity sha512-9gCIUKA7/7/hMHaa5n94+OYU/3tHd6vmBgTgv4o2h3z9SFueQXAJMO4aBggH9+EldgHQDI6wHsnvytEt9AWb6g== - dependencies: - buffer "^6.0.3" - eip1193-provider "^1.0.1" - js-sha3 "^0.8.0" - -"@bull-board/api@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.23.0.tgz#42a742e68bcfc4f547bee417e4b91745adfa40ea" - integrity sha512-ZZGsWJ+XBG49GAlNgAL9tTEV6Ms7gMkQnZDbzwUhjGChCKWy62RWuPoZSefNXau9QH9+QzlzHRUeFvt4xr5wiw== - dependencies: - redis-info "^3.0.8" - -"@bull-board/fastify@^5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@bull-board/fastify/-/fastify-5.23.0.tgz#bfd29a8536f6263fd9ab23cb2e48f450c7ae3505" - integrity sha512-woCnCAav4IByuo05D13MZtETzZp0ej1y0R+6IY33pqLKDRKa6Dor6OMx1l6/nMc/wXeng4SXC5rnrAck7Py70w== - dependencies: - "@bull-board/api" "5.23.0" - "@bull-board/ui" "5.23.0" - "@fastify/static" "^6.11.2" - "@fastify/view" "^8.1.0" - ejs "^3.1.10" - -"@bull-board/ui@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@bull-board/ui/-/ui-5.23.0.tgz#74c1ab638f7aed3596566702c1ddca5cc84ae445" - integrity sha512-iI/Ssl8T5ZEn9s899Qz67m92M6RU8thf/aqD7cUHB2yHmkCjqbw7s7NaODTsyArAsnyu7DGJMWm7EhbfFXDNgQ== - dependencies: - "@bull-board/api" "5.23.0" - -"@circle-fin/developer-controlled-wallets@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@circle-fin/developer-controlled-wallets/-/developer-controlled-wallets-7.0.0.tgz#520bbe54e050dbf9585b54bc61d372887d0dc149" - integrity sha512-GbouORrWpec27DIOVuWfdyP25inrGQUNj2Vwgp7pJm15Z09E9OQBQjB334rGCIM4MT4NVuKKDkbOHTIphoi7zg== - dependencies: - axios "^1.6.2" - -"@cloud-cryptographic-wallet/asn1-parser@^0.0.4": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@cloud-cryptographic-wallet/asn1-parser/-/asn1-parser-0.0.4.tgz#4494a8f46d2b3974731d6cc2f3f34cb8afeb0c78" - integrity sha512-2Mwc2TSJsBmZluvw4mPqtt5UdymDvGRA3DqNAMU6xifh8Ytms0UtAm0YHNpuD2O2LnQr19q2d7eDg0eaS5qIPg== - dependencies: - asn1js "^3.0.5" - -"@cloud-cryptographic-wallet/cloud-kms-signer@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@cloud-cryptographic-wallet/cloud-kms-signer/-/cloud-kms-signer-0.1.2.tgz#9419d45a4a3f9693c8690bb5b6a49cf4e923559b" - integrity sha512-A+d2nb9RfL2Tfkwoodga+arX5Yg2SX8UNE1dFK6QkQKDgr/fMHGuc994y2QHG+u6VAJsF+977T44FAR96Tx4CQ== - dependencies: - "@cloud-cryptographic-wallet/asn1-parser" "^0.0.4" - "@cloud-cryptographic-wallet/signer" "^0.0.5" - "@google-cloud/kms" "^3.0.1" - "@node-lightning/checksum" "^0.27.0" - -"@cloud-cryptographic-wallet/signer@^0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@cloud-cryptographic-wallet/signer/-/signer-0.0.5.tgz#28dc9dd6d222c6e1f06a3e8c52342c2141085cbc" - integrity sha512-CfD3o1PWN3JF1F7bsfgcIET+RpNHeb953TrlMhQ+4yqFzIKGbqTLk3TQT+IoTKdxCWGqo/bzXpLO7aqqzIpPbg== - dependencies: - bn.js "^5.2.0" - keccak "^3.0.2" - secp256k1 "^4.0.3" - -"@coinbase/wallet-sdk@4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.0.3.tgz#fd52dd4c168c35979c7b3294018a6f78d163a593" - integrity sha512-y/OGEjlvosikjfB+wk+4CVb9OxD1ob9cidEBLI5h8Hxaf/Qoob2XoVT1uvhtAzBx34KpGYSd+alKvh/GCRre4Q== - dependencies: - buffer "^6.0.3" - clsx "^1.2.1" - eventemitter3 "^5.0.1" - keccak "^3.0.3" - preact "^10.16.0" - sha.js "^2.4.11" - -"@coinbase/wallet-sdk@4.2.4": - version "4.2.4" - resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.2.4.tgz#aff3a95f50f9a26950052b53620828414bd2baab" - integrity sha512-wJ9QOXOhRdGermKAoJSr4JgGqZm/Um0m+ecywzEC9qSOu3TXuVcG3k0XXTXW11UBgjdoPRuf5kAwRX3T9BynFA== - dependencies: - "@noble/hashes" "^1.4.0" - clsx "^1.2.1" - eventemitter3 "^5.0.1" - preact "^10.24.2" - -"@coinbase/wallet-sdk@^3.9.0": - version "3.9.3" - resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.9.3.tgz#daf10cb0c85d0363315b7270cb3f02bedc408aab" - integrity sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw== - dependencies: - bn.js "^5.2.1" - buffer "^6.0.3" - clsx "^1.2.1" - eth-block-tracker "^7.1.0" - eth-json-rpc-filters "^6.0.0" - eventemitter3 "^5.0.1" - keccak "^3.0.3" - preact "^10.16.0" - sha.js "^2.4.11" - -"@colors/colors@1.6.0", "@colors/colors@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" - integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== - -"@dabh/diagnostics@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" - integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== - dependencies: - colorspace "1.1.x" - enabled "2.0.x" - kuler "^2.0.0" - -"@datadog/libdatadog@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@datadog/libdatadog/-/libdatadog-0.2.2.tgz#ac02c76ac9a38250dca740727c7cdf00244ce3d3" - integrity sha512-rTWo96mEPTY5UbtGoFj8/wY0uKSViJhsPg/Z6aoFWBFXQ8b45Ix2e/yvf92AAwrhG+gPLTxEqTXh3kef2dP8Ow== - -"@datadog/native-appsec@8.3.0": - version "8.3.0" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.3.0.tgz#91afd89d18d386be4da8a1b0e04500f2f8b5eb66" - integrity sha512-RYHbSJ/MwJcJaLzaCaZvUyNLUKFbMshayIiv4ckpFpQJDiq1T8t9iM2k7008s75g1vRuXfsRNX7MaLn4aoFuWA== - dependencies: - node-gyp-build "^3.9.0" - -"@datadog/native-iast-rewriter@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.5.0.tgz#b613defe86e78168f750d1f1662d4ffb3cf002e6" - integrity sha512-WRu34A3Wwp6oafX8KWNAbedtDaaJO+nzfYQht7pcJKjyC2ggfPeF7SoP+eDo9wTn4/nQwEOscSR4hkJqTRlpXQ== - dependencies: - lru-cache "^7.14.0" - node-gyp-build "^4.5.0" - -"@datadog/native-iast-taint-tracking@3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.2.0.tgz#9fb6823d82f934e12c06ea1baa7399ca80deb2ec" - integrity sha512-Mc6FzCoyvU5yXLMsMS9yKnEqJMWoImAukJXolNWCTm+JQYCMf2yMsJ8pBAm7KyZKliamM9rCn7h7Tr2H3lXwjA== - dependencies: - node-gyp-build "^3.9.0" - -"@datadog/native-metrics@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-3.0.1.tgz#dc276c93785c0377a048e316f23b7c8ff3acfa84" - integrity sha512-0GuMyYyXf+Qpb/F+Fcekz58f2mO37lit9U3jMbWY/m8kac44gCPABzL5q3gWbdH+hWgqYfQoEYsdNDGSrKfwoQ== - dependencies: - node-addon-api "^6.1.0" - node-gyp-build "^3.9.0" - -"@datadog/pprof@5.4.1": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.4.1.tgz#08c9bcf5d8efb2eeafdfc9f5bb5402f79fb41266" - integrity sha512-IvpL96e/cuh8ugP5O8Czdup7XQOLHeIDgM5pac5W7Lc1YzGe5zTtebKFpitvb1CPw1YY+1qFx0pWGgKP2kOfHg== - dependencies: - delay "^5.0.0" - node-gyp-build "<4.0" - p-limit "^3.1.0" - pprof-format "^2.1.0" - source-map "^0.7.4" - -"@datadog/sketches-js@^2.1.0": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@datadog/sketches-js/-/sketches-js-2.1.1.tgz#9ec2251b3c932b4f43e1d164461fa6cb6f28b7d0" - integrity sha512-d5RjycE+MObE/hU+8OM5Zp4VjTwiPLRa8299fj7muOmR16fb942z8byoMbCErnGh0lBevvgkGrLclQDvINbIyg== - -"@emotion/babel-plugin@^11.11.0", "@emotion/babel-plugin@^11.13.5": - version "11.13.5" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz#eab8d65dbded74e0ecfd28dc218e75607c4e7bc0" - integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ== - dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/runtime" "^7.18.3" - "@emotion/hash" "^0.9.2" - "@emotion/memoize" "^0.9.0" - "@emotion/serialize" "^1.3.3" - babel-plugin-macros "^3.1.0" - convert-source-map "^1.5.0" - escape-string-regexp "^4.0.0" - find-root "^1.1.0" - source-map "^0.5.7" - stylis "4.2.0" - -"@emotion/cache@^11.11.0", "@emotion/cache@^11.14.0": - version "11.14.0" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.14.0.tgz#ee44b26986eeb93c8be82bb92f1f7a9b21b2ed76" - integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA== - dependencies: - "@emotion/memoize" "^0.9.0" - "@emotion/sheet" "^1.4.0" - "@emotion/utils" "^1.4.2" - "@emotion/weak-memoize" "^0.4.0" - stylis "4.2.0" - -"@emotion/hash@^0.9.2": - version "0.9.2" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" - integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== - -"@emotion/is-prop-valid@^1.2.1", "@emotion/is-prop-valid@^1.3.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240" - integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw== - dependencies: - "@emotion/memoize" "^0.9.0" - -"@emotion/memoize@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" - integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== - -"@emotion/react@11.11.4": - version "11.11.4" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.4.tgz#3a829cac25c1f00e126408fab7f891f00ecc3c1d" - integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/cache" "^11.11.0" - "@emotion/serialize" "^1.1.3" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - "@emotion/weak-memoize" "^0.3.1" - hoist-non-react-statics "^3.3.1" - -"@emotion/react@11.14.0": - version "11.14.0" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.14.0.tgz#cfaae35ebc67dd9ef4ea2e9acc6cd29e157dd05d" - integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.13.5" - "@emotion/cache" "^11.14.0" - "@emotion/serialize" "^1.3.3" - "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0" - "@emotion/utils" "^1.4.2" - "@emotion/weak-memoize" "^0.4.0" - hoist-non-react-statics "^3.3.1" - -"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.3.tgz#d291531005f17d704d0463a032fe679f376509e8" - integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== - dependencies: - "@emotion/hash" "^0.9.2" - "@emotion/memoize" "^0.9.0" - "@emotion/unitless" "^0.10.0" - "@emotion/utils" "^1.4.2" - csstype "^3.0.2" - -"@emotion/sheet@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" - integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== - -"@emotion/styled@11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" - integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/is-prop-valid" "^1.2.1" - "@emotion/serialize" "^1.1.2" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - -"@emotion/styled@11.14.0": - version "11.14.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.14.0.tgz#f47ca7219b1a295186d7661583376fcea95f0ff3" - integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.13.5" - "@emotion/is-prop-valid" "^1.3.0" - "@emotion/serialize" "^1.3.3" - "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0" - "@emotion/utils" "^1.4.2" - -"@emotion/unitless@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745" - integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== - -"@emotion/use-insertion-effect-with-fallbacks@^1.0.1", "@emotion/use-insertion-effect-with-fallbacks@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz#8a8cb77b590e09affb960f4ff1e9a89e532738bf" - integrity sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg== - -"@emotion/utils@^1.2.1", "@emotion/utils@^1.4.2": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.2.tgz#6df6c45881fcb1c412d6688a311a98b7f59c1b52" - integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== - -"@emotion/weak-memoize@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" - integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== - -"@emotion/weak-memoize@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" - integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== - -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== - -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== - -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== - -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== - -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== - -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== - -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== - -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== - -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== - -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== - -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== - -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== - -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== - -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== - -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== - -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== - -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== - -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== - -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== - -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== - -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== - -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== - -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== - -"@eth-optimism/contracts@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@eth-optimism/contracts/-/contracts-0.6.0.tgz#15ae76222a9b4d958a550cafb1960923af613a31" - integrity sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w== - dependencies: - "@eth-optimism/core-utils" "0.12.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - -"@eth-optimism/core-utils@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.12.0.tgz#6337e4599a34de23f8eceb20378de2a2de82b0ea" - integrity sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/providers" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bufio "^1.0.7" - chai "^4.3.4" - -"@eth-optimism/core-utils@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@eth-optimism/core-utils/-/core-utils-0.13.2.tgz#c0187c3abf6d86dad039edf04ff81299253214fe" - integrity sha512-u7TOKm1RxH1V5zw7dHmfy91bOuEAZU68LT/9vJPkuWEjaTl+BgvPDRDTurjzclHzN0GbWdcpOqPZg4ftjkJGaw== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/web" "^5.7.1" - chai "^4.3.10" - ethers "^5.7.2" - node-fetch "^2.6.7" - -"@eth-optimism/sdk@3.3.2": - version "3.3.2" - resolved "https://registry.yarnpkg.com/@eth-optimism/sdk/-/sdk-3.3.2.tgz#68a5f6e77f9c85f6eeb9db8044b3b69199520eb0" - integrity sha512-+zhxT0YkBIEzHsuIayQGjr8g9NawZo6/HYfzg1NSEFsE2Yt0NyCWqVDFTuuak0T6AvIa2kNcl3r0Z8drdb2QmQ== - dependencies: - "@eth-optimism/contracts" "0.6.0" - "@eth-optimism/core-utils" "^0.13.2" - lodash "^4.17.21" - merkletreejs "^0.3.11" - rlp "^2.2.7" - semver "^7.6.0" - -"@ethereumjs/common@^2.4.0": - version "2.6.5" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" - integrity sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA== - dependencies: - crc-32 "^1.2.0" - ethereumjs-util "^7.1.5" - -"@ethereumjs/common@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-3.2.0.tgz#b71df25845caf5456449163012074a55f048e0a0" - integrity sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA== - dependencies: - "@ethereumjs/util" "^8.1.0" - crc-32 "^1.2.0" - -"@ethereumjs/rlp@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" - integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== - -"@ethereumjs/tx@^4.1.2", "@ethereumjs/tx@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-4.2.0.tgz#5988ae15daf5a3b3c815493bc6b495e76009e853" - integrity sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw== - dependencies: - "@ethereumjs/common" "^3.2.0" - "@ethereumjs/rlp" "^4.0.1" - "@ethereumjs/util" "^8.1.0" - ethereum-cryptography "^2.0.0" - -"@ethereumjs/util@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" - integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== - dependencies: - "@ethereumjs/rlp" "^4.0.1" - ethereum-cryptography "^2.0.0" - micro-ftch "^0.3.1" - -"@ethersproject/abi@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" - integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w== - dependencies: - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@5.5.1": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" - integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.0" - -"@ethersproject/abstract-provider@5.7.0", "@ethersproject/abstract-provider@^5.5.0", "@ethersproject/abstract-provider@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" - integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.5.0", "@ethersproject/abstract-signer@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" - integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.5.0", "@ethersproject/address@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" - integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - -"@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.5.0", "@ethersproject/base64@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" - integrity sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - -"@ethersproject/basex@5.7.0", "@ethersproject/basex@^5.5.0", "@ethersproject/basex@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" - integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - bn.js "^4.11.9" - -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.5.0", "@ethersproject/bignumber@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bytes@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" - integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== - dependencies: - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" - integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.5.0", "@ethersproject/constants@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" - integrity sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg== - dependencies: - "@ethersproject/abi" "^5.5.0" - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - -"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" - integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.5.0", "@ethersproject/hash@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" - integrity sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/basex" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/pbkdf2" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/wordlists" "^5.5.0" - -"@ethersproject/hdnode@5.7.0", "@ethersproject/hdnode@^5.5.0", "@ethersproject/hdnode@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" - integrity sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ== - dependencies: - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/hdnode" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/pbkdf2" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/json-wallets@5.7.0", "@ethersproject/json-wallets@^5.5.0", "@ethersproject/json-wallets@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" - integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - js-sha3 "0.8.0" - -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.5.0", "@ethersproject/keccak256@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/logger@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" - integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== - -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.5.0", "@ethersproject/logger@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/networks@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.0.tgz#babec47cab892c51f8dd652ce7f2e3e14283981a" - integrity sha512-KWfP3xOnJeF89Uf/FCJdV1a2aDJe5XTN2N52p4fcQ34QhDqQFkgQKZ39VGtiqUgHcLI8DfT0l9azC3KFTunqtA== - dependencies: - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/networks@5.7.1", "@ethersproject/networks@^5.5.0", "@ethersproject/networks@^5.7.0": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" - integrity sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - -"@ethersproject/pbkdf2@5.7.0", "@ethersproject/pbkdf2@^5.5.0", "@ethersproject/pbkdf2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" - integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== - dependencies: - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.5.0", "@ethersproject/properties@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.0.tgz#bc2876a8fe5e0053ed9828b1f3767ae46e43758b" - integrity sha512-xqMbDnS/FPy+J/9mBLKddzyLLAQFjrVff5g00efqxPzcAwXiR+SiCGVy6eJ5iAIirBOATjx7QLhDNPGV+AEQsw== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/basex" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.2": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.0.tgz#305ed9e033ca537735365ac12eed88580b0f81f9" - integrity sha512-egGYZwZ/YIFKMHcoBUo8t3a8Hb/TKYX8BCBoLjudVCZh892welR3jOxgOmb48xznc9bTcMm7Tpwc1gHC1PFNFQ== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/random@5.7.0", "@ethersproject/random@^5.5.0", "@ethersproject/random@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" - integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/rlp@5.7.0", "@ethersproject/rlp@^5.5.0", "@ethersproject/rlp@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" - integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - hash.js "1.1.7" - -"@ethersproject/sha2@5.7.0", "@ethersproject/sha2@^5.5.0", "@ethersproject/sha2@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" - integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.7.0", "@ethersproject/signing-key@^5.5.0", "@ethersproject/signing-key@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" - integrity sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" - integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.5.0", "@ethersproject/strings@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" - integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== - dependencies: - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - -"@ethersproject/transactions@5.7.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0", "@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" - integrity sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag== - dependencies: - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" - integrity sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/hdnode" "^5.5.0" - "@ethersproject/json-wallets" "^5.5.0" - "@ethersproject/keccak256" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/signing-key" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/wordlists" "^5.5.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.0.tgz#0e5bb21a2b58fb4960a705bfc6522a6acf461e28" - integrity sha512-BEgY0eL5oH4mAo37TNYVrFeHsIXLRxggCRG/ksRIxI2X5uj5IsjGmcNiRN/VirQOlBxcUhCgHhaDLG4m6XAVoA== - dependencies: - "@ethersproject/base64" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@ethersproject/web@5.7.1", "@ethersproject/web@^5.5.0", "@ethersproject/web@^5.7.0", "@ethersproject/web@^5.7.1": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" - integrity sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q== - dependencies: - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - -"@ethersproject/wordlists@5.7.0", "@ethersproject/wordlists@^5.5.0", "@ethersproject/wordlists@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@fastify/accept-negotiator@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz#c1c66b3b771c09742a54dd5bc87c582f6b0630ff" - integrity sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ== - -"@fastify/ajv-compiler@^3.5.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz#907497a0e62a42b106ce16e279cf5788848e8e79" - integrity sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ== - dependencies: - ajv "^8.11.0" - ajv-formats "^2.1.1" - fast-uri "^2.0.0" - -"@fastify/cookie@^9.3.1": - version "9.4.0" - resolved "https://registry.yarnpkg.com/@fastify/cookie/-/cookie-9.4.0.tgz#1be3bff03dbe746d3bbddbf31a37354076a190c1" - integrity sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg== - dependencies: - cookie-signature "^1.1.0" - fastify-plugin "^4.0.0" - -"@fastify/error@^3.3.0", "@fastify/error@^3.4.0": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@fastify/error/-/error-3.4.1.tgz#b14bb4cac3dd4ec614becbc643d1511331a6425c" - integrity sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ== - -"@fastify/fast-json-stringify-compiler@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz#5df89fa4d1592cbb8780f78998355feb471646d5" - integrity sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA== - dependencies: - fast-json-stringify "^5.7.0" - -"@fastify/merge-json-schemas@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz#3551857b8a17a24e8c799e9f51795edb07baa0bc" - integrity sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA== - dependencies: - fast-deep-equal "^3.1.3" - -"@fastify/send@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@fastify/send/-/send-2.1.0.tgz#1aa269ccb4b0940a2dadd1f844443b15d8224ea0" - integrity sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA== - dependencies: - "@lukeed/ms" "^2.0.1" - escape-html "~1.0.3" - fast-decode-uri-component "^1.0.1" - http-errors "2.0.0" - mime "^3.0.0" - -"@fastify/static@^6.11.2": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@fastify/static/-/static-6.12.0.tgz#f3d55dda201c072bae0593e5d45dde8fd235c288" - integrity sha512-KK1B84E6QD/FcQWxDI2aiUCwHxMJBI1KeCUzm1BwYpPY1b742+jeKruGHP2uOluuM6OkBPI8CIANrXcCRtC2oQ== - dependencies: - "@fastify/accept-negotiator" "^1.0.0" - "@fastify/send" "^2.0.0" - content-disposition "^0.5.3" - fastify-plugin "^4.0.0" - glob "^8.0.1" - p-limit "^3.1.0" - -"@fastify/swagger@^8.9.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@fastify/swagger/-/swagger-8.15.0.tgz#d13cadc1e7892e05c7c2bc0f24fd6cd723838b64" - integrity sha512-zy+HEEKFqPMS2sFUsQU5X0MHplhKJvWeohBwTCkBAJA/GDYGLGUWQaETEhptiqxK7Hs0fQB9B4MDb3pbwIiCwA== - dependencies: - fastify-plugin "^4.0.0" - json-schema-resolver "^2.0.0" - openapi-types "^12.0.0" - rfdc "^1.3.0" - yaml "^2.2.2" - -"@fastify/type-provider-typebox@^3.2.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@fastify/type-provider-typebox/-/type-provider-typebox-3.6.0.tgz#e7fdd9c1e8d3b326b61617d60b8f09678740a8a5" - integrity sha512-HTeOLvirfGg0u1KGao3iXn5rZpYNqlrOmyDnXSXAbWVPa+mDQTTBNs/x5uZzOB6vFAqr0Xcf7x1lxOamNSYKjw== - -"@fastify/view@^8.1.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@fastify/view/-/view-8.2.0.tgz#80ef9569198ca3a0f3207fa25b2dd6d0c12fc4c7" - integrity sha512-hBSiBofCnJNlPHEMZWpO1SL84eqOaqujJ1hR3jntFyZZCkweH5jMs12DKYyGesjVll7SJFRRxPUBB8kmUmneRQ== - dependencies: - fastify-plugin "^4.0.0" - hashlru "^2.3.0" - -"@fastify/websocket@^8.2.0": - version "8.3.1" - resolved "https://registry.yarnpkg.com/@fastify/websocket/-/websocket-8.3.1.tgz#a219e3090967673968b078fd6c36b0b6d424aaf6" - integrity sha512-hsQYHHJme/kvP3ZS4v/WMUznPBVeeQHHwAoMy1LiN6m/HuPfbdXq1MBJ4Nt8qX1YI+eVbog4MnOsU7MTozkwYA== - dependencies: - fastify-plugin "^4.0.0" - ws "^8.0.0" - -"@floating-ui/core@^1.6.0": - version "1.6.8" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.8.tgz#aa43561be075815879305965020f492cdb43da12" - integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA== - dependencies: - "@floating-ui/utils" "^0.2.8" - -"@floating-ui/dom@^1.0.0": - version "1.6.12" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.12.tgz#6333dcb5a8ead3b2bf82f33d6bc410e95f54e556" - integrity sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w== - dependencies: - "@floating-ui/core" "^1.6.0" - "@floating-ui/utils" "^0.2.8" - -"@floating-ui/react-dom@^2.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" - integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== - dependencies: - "@floating-ui/dom" "^1.0.0" - -"@floating-ui/utils@^0.2.8": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62" - integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig== - -"@google-cloud/kms@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@google-cloud/kms/-/kms-3.0.1.tgz#2e86889f2c08f13208afc5bd272a7f25326c9f17" - integrity sha512-xUrhzattC5mkNqbfMcIgBzwAab9eXCYrn1R1KYUNV5E96fK7ciT57bJESaUQvin7XKd18sQcLRD+uOJ6eTfXbg== - dependencies: - google-gax "^3.0.1" - -"@google-cloud/kms@^3.0.1": - version "3.8.0" - resolved "https://registry.yarnpkg.com/@google-cloud/kms/-/kms-3.8.0.tgz#165774725152fd73a2940667dfc7179843fab014" - integrity sha512-hE9np8VuMLe7npw16wCchcnkW0TDraP3zjD4+vzrxwDUKSTId8sWjlU/Pb69viUBQLyoLFE3mkH6nPhd8TWU3A== - dependencies: - google-gax "^3.5.8" - -"@google-cloud/kms@^4.4.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@google-cloud/kms/-/kms-4.5.0.tgz#c3336a13e54559cbe40e42ab803cc6cefc2aa3c7" - integrity sha512-i2vC0DI7bdfEhQszqASTw0KVvbB7HsO2CwTBod423NawAu7FWi+gVVa7NLfXVNGJaZZayFfci2Hu+om/HmyEjQ== - dependencies: - google-gax "^4.0.3" - -"@google/model-viewer@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@google/model-viewer/-/model-viewer-2.1.1.tgz#37c51143740c07c592d5cccbc8cfaa8be8b7ef82" - integrity sha512-5umyLoD5vMxlSVQwtmUXeNCNWs9dzmWykGm1qrHe/pCYrj/1lyJIgJRw+IxoMNodGqtcHEtfDhdNjRDM9yo/TA== - dependencies: - lit "^2.2.3" - three "^0.146.0" - -"@grpc/grpc-js@>=1.8.22", "@grpc/grpc-js@^1.10.9", "@grpc/grpc-js@~1.8.0": - version "1.12.4" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.12.4.tgz#3208808435ebf1e495f9a5c5c5a0bc3dc8c9e891" - integrity sha512-NBhrxEWnFh0FxeA0d//YP95lRFsSx2TNLEUQg4/W+5f/BMxcCjgOOIT24iD+ZB/tZw057j44DaIxja7w4XMrhg== - dependencies: - "@grpc/proto-loader" "^0.7.13" - "@js-sdsl/ordered-map" "^4.4.2" - -"@grpc/proto-loader@^0.7.0", "@grpc/proto-loader@^0.7.13": - version "0.7.13" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" - integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== - dependencies: - lodash.camelcase "^4.3.0" - long "^5.0.0" - protobufjs "^7.2.5" - yargs "^17.7.2" - -"@ioredis/commands@^1.1.1": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" - integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@isaacs/fs-minipass@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" - integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== - dependencies: - minipass "^7.0.4" - -"@isaacs/ttlcache@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" - integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@js-sdsl/ordered-map@^4.4.2": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c" - integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw== - -"@jsdevtools/ono@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" - integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== - -"@jsdoc/salty@^0.2.1": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@jsdoc/salty/-/salty-0.2.8.tgz#8d29923a9429694a437a50ab75004b576131d597" - integrity sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg== - dependencies: - lodash "^4.17.21" - -"@json-rpc-tools/provider@^1.5.5": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@json-rpc-tools/provider/-/provider-1.7.6.tgz#8a17c34c493fa892632e278fd9331104e8491ec6" - integrity sha512-z7D3xvJ33UfCGv77n40lbzOYjZKVM3k2+5cV7xS8G6SCvKTzMkhkUYuD/qzQUNT4cG/lv0e9mRToweEEVLVVmA== - dependencies: - "@json-rpc-tools/utils" "^1.7.6" - axios "^0.21.0" - safe-json-utils "^1.1.1" - ws "^7.4.0" - -"@json-rpc-tools/types@^1.7.6": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.7.6.tgz#5abd5fde01364a130c46093b501715bcce5bdc0e" - integrity sha512-nDSqmyRNEqEK9TZHtM15uNnDljczhCUdBmRhpNZ95bIPKEDQ+nTDmGMFd2lLin3upc5h2VVVd9tkTDdbXUhDIQ== - dependencies: - keyvaluestorage-interface "^1.0.0" - -"@json-rpc-tools/utils@^1.7.6": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.7.6.tgz#67f04987dbaa2e7adb6adff1575367b75a9a9ba1" - integrity sha512-HjA8x/U/Q78HRRe19yh8HVKoZ+Iaoo3YZjakJYxR+rw52NHo6jM+VE9b8+7ygkCFXl/EHID5wh/MkXaE/jGyYw== - dependencies: - "@json-rpc-tools/types" "^1.7.6" - "@pedrouid/environment" "^1.0.1" - -"@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz#2f3a8f1d688935c704dbc89132394a41029acbb8" - integrity sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ== - -"@lit/reactive-element@^1.3.0", "@lit/reactive-element@^1.6.0": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.6.3.tgz#25b4eece2592132845d303e091bad9b04cdcfe03" - integrity sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ== - dependencies: - "@lit-labs/ssr-dom-shim" "^1.0.0" - -"@lukeed/ms@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@lukeed/ms/-/ms-2.0.2.tgz#07f09e59a74c52f4d88c6db5c1054e819538e2a8" - integrity sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA== - -"@magic-ext/connect@^6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@magic-ext/connect/-/connect-6.7.2.tgz#9b479d2a3b0740e63915c7c7af461af5f3bfbf2a" - integrity sha512-b56mYYzgeXmRzZ8DgsUV6hFKFidaoRJvibUgcRwSuGElDdQxuhkz6FUyTLLS0zGbGdg4lfa7F1J/II1NrxA+lQ== - -"@magic-ext/oauth@^7.6.2": - version "7.6.2" - resolved "https://registry.yarnpkg.com/@magic-ext/oauth/-/oauth-7.6.2.tgz#fb779d76e2cdf39f452d14bb0efe81c81e327479" - integrity sha512-yqQBdtkMouD+owAJkPlevLbal/iCREH/D3PmDW9a7Dsfjy2xs557oIpGkLSZexTIHd3Cxga9hWNpdqFukUfzYg== - dependencies: - "@magic-sdk/types" "^11.6.2" - -"@magic-sdk/commons@^9.6.2": - version "9.6.2" - resolved "https://registry.yarnpkg.com/@magic-sdk/commons/-/commons-9.6.2.tgz#db03f98efb771481f4045a3877b6285600f0e96e" - integrity sha512-PgYznuO9GV5wiKgzP3bEQJTnAbvfHmAPTBmwbP/ESag3FrOyXxuk7PIWpeGmnFa/i6SSQUsmKp8sr/BN0dU5vg== - -"@magic-sdk/provider@^13.6.2": - version "13.6.2" - resolved "https://registry.yarnpkg.com/@magic-sdk/provider/-/provider-13.6.2.tgz#ae0772205952f65b32466396c81bfd695d23554f" - integrity sha512-ecrTyL4NaploZ/cX1b+NGiWYMSAWVseE7xa7tvmkejZgQCrcJQd8UXb3LPVPmF7kQPKGutJSdkeGJCDKwsGKIA== - dependencies: - "@magic-sdk/types" "^11.6.2" - eventemitter3 "^4.0.4" - web3-core "1.5.2" - -"@magic-sdk/types@^11.6.2": - version "11.6.2" - resolved "https://registry.yarnpkg.com/@magic-sdk/types/-/types-11.6.2.tgz#1fb6205b516c3f0c5787e82aecd0e667d2de1cd2" - integrity sha512-+Emd+9HeeVi2E0bktJ33YleA/ozEuKYCBfmSbGRxlntdyUvaojeC+WPf2jN1WH8FjUEiljAjrEJTTZyRGCL8SQ== - -"@metamask/eth-json-rpc-provider@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz#3fd5316c767847f4ca107518b611b15396a5a32c" - integrity sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA== - dependencies: - "@metamask/json-rpc-engine" "^7.0.0" - "@metamask/safe-event-emitter" "^3.0.0" - "@metamask/utils" "^5.0.1" - -"@metamask/eth-sig-util@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.0.tgz#11553ba06de0d1352332c1bde28c8edd00e0dcf6" - integrity sha512-LczOjjxY4A7XYloxzyxJIHONELmUxVZncpOLoClpEcTiebiVdM46KRPYXGuULro9oNNR2xdVx3yoKiQjdfWmoA== - dependencies: - ethereumjs-abi "^0.6.8" - ethereumjs-util "^6.2.1" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - -"@metamask/eth-sig-util@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" - integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== - dependencies: - ethereumjs-abi "^0.6.8" - ethereumjs-util "^6.2.1" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - -"@metamask/json-rpc-engine@^7.0.0": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz#f2b30a2164558014bfcca45db10f5af291d989af" - integrity sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg== - dependencies: - "@metamask/rpc-errors" "^6.2.1" - "@metamask/safe-event-emitter" "^3.0.0" - "@metamask/utils" "^8.3.0" - -"@metamask/rpc-errors@^6.2.1": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz#a7ce01c06c9a347ab853e55818ac5654a73bd006" - integrity sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg== - dependencies: - "@metamask/utils" "^9.0.0" - fast-safe-stringify "^2.0.6" - -"@metamask/safe-event-emitter@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" - integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q== - -"@metamask/safe-event-emitter@^3.0.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz#bfac8c7a1a149b5bbfe98f59fbfea512dfa3bad4" - integrity sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA== - -"@metamask/superstruct@^3.0.0", "@metamask/superstruct@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@metamask/superstruct/-/superstruct-3.1.0.tgz#148f786a674fba3ac885c1093ab718515bf7f648" - integrity sha512-N08M56HdOgBfRKkrgCMZvQppkZGcArEop3kixNEtVbJKm6P9Cfg0YkI6X0s1g78sNrj2fWUwvJADdZuzJgFttA== - -"@metamask/utils@^5.0.1": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-5.0.2.tgz#140ba5061d90d9dac0280c19cab101bc18c8857c" - integrity sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g== - dependencies: - "@ethereumjs/tx" "^4.1.2" - "@types/debug" "^4.1.7" - debug "^4.3.4" - semver "^7.3.8" - superstruct "^1.0.3" - -"@metamask/utils@^8.3.0": - version "8.5.0" - resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-8.5.0.tgz#ddd0d4012d5191809404c97648a837ea9962cceb" - integrity sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ== - dependencies: - "@ethereumjs/tx" "^4.2.0" - "@metamask/superstruct" "^3.0.0" - "@noble/hashes" "^1.3.1" - "@scure/base" "^1.1.3" - "@types/debug" "^4.1.7" - debug "^4.3.4" - pony-cause "^2.1.10" - semver "^7.5.4" - uuid "^9.0.1" - -"@metamask/utils@^9.0.0": - version "9.3.0" - resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-9.3.0.tgz#4726bd7f5d6a43ea8425b6d663ab9207f617c2d1" - integrity sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g== - dependencies: - "@ethereumjs/tx" "^4.2.0" - "@metamask/superstruct" "^3.1.0" - "@noble/hashes" "^1.3.1" - "@scure/base" "^1.1.3" - "@types/debug" "^4.1.7" - debug "^4.3.4" - pony-cause "^2.1.10" - semver "^7.5.4" - uuid "^9.0.1" - -"@motionone/animation@^10.15.1", "@motionone/animation@^10.18.0": - version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.18.0.tgz#868d00b447191816d5d5cf24b1cafa144017922b" - integrity sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw== - dependencies: - "@motionone/easing" "^10.18.0" - "@motionone/types" "^10.17.1" - "@motionone/utils" "^10.18.0" - tslib "^2.3.1" - -"@motionone/dom@^10.16.2", "@motionone/dom@^10.16.4": - version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.18.0.tgz#7fd25dac04cab72def6d2b92b8e0cdc091576527" - integrity sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A== - dependencies: - "@motionone/animation" "^10.18.0" - "@motionone/generators" "^10.18.0" - "@motionone/types" "^10.17.1" - "@motionone/utils" "^10.18.0" - hey-listen "^1.0.8" - tslib "^2.3.1" - -"@motionone/easing@^10.18.0": - version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.18.0.tgz#7b82f6010dfee3a1bb0ee83abfbaff6edae0c708" - integrity sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg== - dependencies: - "@motionone/utils" "^10.18.0" - tslib "^2.3.1" - -"@motionone/generators@^10.18.0": - version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.18.0.tgz#fe09ab5cfa0fb9a8884097feb7eb60abeb600762" - integrity sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg== - dependencies: - "@motionone/types" "^10.17.1" - "@motionone/utils" "^10.18.0" - tslib "^2.3.1" - -"@motionone/svelte@^10.16.2": - version "10.16.4" - resolved "https://registry.yarnpkg.com/@motionone/svelte/-/svelte-10.16.4.tgz#5daf117cf5b2576fc6dd487c5e0500938a742470" - integrity sha512-zRVqk20lD1xqe+yEDZhMYgftsuHc25+9JSo+r0a0OWUJFocjSV9D/+UGhX4xgJsuwB9acPzXLr20w40VnY2PQA== - dependencies: - "@motionone/dom" "^10.16.4" - tslib "^2.3.1" - -"@motionone/types@^10.15.1", "@motionone/types@^10.17.1": - version "10.17.1" - resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.17.1.tgz#cf487badbbdc9da0c2cb86ffc1e5d11147c6e6fb" - integrity sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A== - -"@motionone/utils@^10.15.1", "@motionone/utils@^10.18.0": - version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.18.0.tgz#a59ff8932ed9009624bca07c56b28ef2bb2f885e" - integrity sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw== - dependencies: - "@motionone/types" "^10.17.1" - hey-listen "^1.0.8" - tslib "^2.3.1" - -"@motionone/vue@^10.16.2": - version "10.16.4" - resolved "https://registry.yarnpkg.com/@motionone/vue/-/vue-10.16.4.tgz#07d09e3aa5115ca0bcc0076cb9e5322775277c09" - integrity sha512-z10PF9JV6SbjFq+/rYabM+8CVlMokgl8RFGvieSGNTmrkQanfHn+15XBrhG3BgUfvmTeSeyShfOHpG0i9zEdcg== - dependencies: - "@motionone/dom" "^10.16.4" - tslib "^2.3.1" - -"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz#9edec61b22c3082018a79f6d1c30289ddf3d9d11" - integrity sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw== - -"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz#33677a275204898ad8acbf62734fc4dc0b6a4855" - integrity sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw== - -"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz#19edf7cdc2e7063ee328403c1d895a86dd28f4bb" - integrity sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg== - -"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz#94fb0543ba2e28766c3fc439cabbe0440ae70159" - integrity sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw== - -"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz#4a0609ab5fe44d07c9c60a11e4484d3c38bbd6e3" - integrity sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg== - -"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz#0aa5502d547b57abfc4ac492de68e2006e417242" - integrity sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ== - -"@multiformats/base-x@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121" - integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw== - -"@noble/curves@1.2.0", "@noble/curves@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - -"@noble/curves@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" - integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== - dependencies: - "@noble/hashes" "1.4.0" - -"@noble/curves@1.4.2", "@noble/curves@~1.4.0": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" - integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== - dependencies: - "@noble/hashes" "1.4.0" - -"@noble/curves@1.7.0", "@noble/curves@^1.4.0", "@noble/curves@^1.6.0", "@noble/curves@~1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" - integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== - dependencies: - "@noble/hashes" "1.6.0" - -"@noble/hashes@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - -"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" - integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== - -"@noble/hashes@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" - integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== - -"@noble/hashes@1.6.1", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@~1.6.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" - integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== - -"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" - integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== - -"@node-lightning/checksum@^0.27.0": - version "0.27.4" - resolved "https://registry.yarnpkg.com/@node-lightning/checksum/-/checksum-0.27.4.tgz#493004e76aa76cdbab46f01bf445e4010c30a179" - integrity sha512-33DuXWqVVvHPnO7O38L2wtz9cSjCXeqi3+xUHZpPhZHpez4atw0JUcc1Fa1SJ4aEjDX81t6rLloMW083z9ZHYQ== - -"@opentelemetry/api@>=1.0.0 <1.9.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" - integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== - -"@opentelemetry/api@^1.4.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" - integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== - -"@opentelemetry/core@^1.14.0": - version "1.29.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.29.0.tgz#a9397dfd9a8b37b2435b5e44be16d39ec1c82bd9" - integrity sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA== - dependencies: - "@opentelemetry/semantic-conventions" "1.28.0" - -"@opentelemetry/semantic-conventions@1.28.0": - version "1.28.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz#337fb2bca0453d0726696e745f50064411f646d6" - integrity sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA== - -"@openzeppelin/contracts-upgradeable@^4.4.2", "@openzeppelin/contracts-upgradeable@^4.9.3": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.6.tgz#38b21708a719da647de4bb0e4802ee235a0d24df" - integrity sha512-m4iHazOsOCv1DgM7eD7GupTJ+NFVujRZt1wzddDPSVGpWdKq1SKkla5htKG7+IS4d2XOCtzkUNwRZ7Vq5aEUMA== - -"@openzeppelin/contracts@^4.9.3": - version "4.9.6" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677" - integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA== - -"@paperxyz/embedded-wallet-service-sdk@^1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@paperxyz/embedded-wallet-service-sdk/-/embedded-wallet-service-sdk-1.2.5.tgz#d635dd0a05d7b8231ca6ca6e692774cb5c791e25" - integrity sha512-FuAMdMmpB55K5jNS2Em6TtqJdXNLPdFxReITd2uS2lMgCtmlUP4aLLFsx+fDEVsAP3hg4FVueqGQWilII/7i0A== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/providers" "^5.7.2" - "@paperxyz/sdk-common-utilities" "*" - -"@paperxyz/sdk-common-utilities@*", "@paperxyz/sdk-common-utilities@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@paperxyz/sdk-common-utilities/-/sdk-common-utilities-0.1.1.tgz#dfddaf8880c82bd665368793ebe4d06a365bede7" - integrity sha512-RefjXB3d5Ub1I3GoIf/mfgTsvmAneWoeQwpmiuXYx1NmmSdbtBxDUk4POtSWUCnvoiJP0Y2frATnYMV30J1b1A== - -"@parcel/watcher-android-arm64@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz#e32d3dda6647791ee930556aee206fcd5ea0fb7a" - integrity sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ== - -"@parcel/watcher-darwin-arm64@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz#0d9e680b7e9ec1c8f54944f1b945aa8755afb12f" - integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw== - -"@parcel/watcher-darwin-x64@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz#f9f1d5ce9d5878d344f14ef1856b7a830c59d1bb" - integrity sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA== - -"@parcel/watcher-freebsd-x64@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz#2b77f0c82d19e84ff4c21de6da7f7d096b1a7e82" - integrity sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw== - -"@parcel/watcher-linux-arm-glibc@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz#92ed322c56dbafa3d2545dcf2803334aee131e42" - integrity sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA== - -"@parcel/watcher-linux-arm-musl@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz#cd48e9bfde0cdbbd2ecd9accfc52967e22f849a4" - integrity sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA== - -"@parcel/watcher-linux-arm64-glibc@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz#7b81f6d5a442bb89fbabaf6c13573e94a46feb03" - integrity sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA== - -"@parcel/watcher-linux-arm64-musl@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz#dcb8ff01077cdf59a18d9e0a4dff7a0cfe5fd732" - integrity sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q== - -"@parcel/watcher-linux-x64-glibc@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz#2e254600fda4e32d83942384d1106e1eed84494d" - integrity sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw== - -"@parcel/watcher-linux-x64-musl@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz#01fcea60fedbb3225af808d3f0a7b11229792eef" - integrity sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA== - -"@parcel/watcher-wasm@^2.4.1": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.5.0.tgz#81fad1e10957f08a532eb4fc0d4c353cd8901a50" - integrity sha512-Z4ouuR8Pfggk1EYYbTaIoxc+Yv4o7cGQnH0Xy8+pQ+HbiW+ZnwhcD2LPf/prfq1nIWpAxjOkQ8uSMFWMtBLiVQ== - dependencies: - is-glob "^4.0.3" - micromatch "^4.0.5" - napi-wasm "^1.1.0" - -"@parcel/watcher-win32-arm64@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz#87cdb16e0783e770197e52fb1dc027bb0c847154" - integrity sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig== - -"@parcel/watcher-win32-ia32@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz#778c39b56da33e045ba21c678c31a9f9d7c6b220" - integrity sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA== - -"@parcel/watcher-win32-x64@2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz#33873876d0bbc588aacce38e90d1d7480ce81cb7" - integrity sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw== - -"@parcel/watcher@^2.4.1": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.0.tgz#5c88818b12b8de4307a9d3e6dc3e28eba0dfbd10" - integrity sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ== - dependencies: - detect-libc "^1.0.3" - is-glob "^4.0.3" - micromatch "^4.0.5" - node-addon-api "^7.0.0" - optionalDependencies: - "@parcel/watcher-android-arm64" "2.5.0" - "@parcel/watcher-darwin-arm64" "2.5.0" - "@parcel/watcher-darwin-x64" "2.5.0" - "@parcel/watcher-freebsd-x64" "2.5.0" - "@parcel/watcher-linux-arm-glibc" "2.5.0" - "@parcel/watcher-linux-arm-musl" "2.5.0" - "@parcel/watcher-linux-arm64-glibc" "2.5.0" - "@parcel/watcher-linux-arm64-musl" "2.5.0" - "@parcel/watcher-linux-x64-glibc" "2.5.0" - "@parcel/watcher-linux-x64-musl" "2.5.0" - "@parcel/watcher-win32-arm64" "2.5.0" - "@parcel/watcher-win32-ia32" "2.5.0" - "@parcel/watcher-win32-x64" "2.5.0" - -"@passwordless-id/webauthn@^1.6.1": - version "1.6.2" - resolved "https://registry.yarnpkg.com/@passwordless-id/webauthn/-/webauthn-1.6.2.tgz#677e963280eac2a98eb3317b54c80f9f59d56d15" - integrity sha512-52Cna/kaJ6iuYgTko+LuHCY5NUgoJTQ+iLWbvCHWiI0pT+zUeKz1+g22mWGlSi/JDrFGwZTKG/PL2YDaQGo0qQ== - -"@passwordless-id/webauthn@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@passwordless-id/webauthn/-/webauthn-2.1.2.tgz#011d0d03a1e2dd9e560d7b305bd9c749a435d761" - integrity sha512-Ahj+A3O0gP3EsLV4FRXjfhbzzP895d8CnHKmhT1hkAz1zLSBCRE/iXJsasL1kwGoriDFLJ+YtO6x1rok4SZH2g== - -"@pedrouid/environment@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec" - integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug== - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@prisma/client@5.17.0": - version "5.17.0" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.17.0.tgz#9079947bd749689c2dabfb9ecc70a24ebefb1f43" - integrity sha512-N2tnyKayT0Zf7mHjwEyE8iG7FwTmXDHFZ1GnNhQp0pJUObsuel4ZZ1XwfuAYkq5mRIiC/Kot0kt0tGCfLJ70Jw== - -"@prisma/debug@5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.22.0.tgz#58af56ed7f6f313df9fb1042b6224d3174bbf412" - integrity sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ== - -"@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2": - version "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz#d534dd7235c1ba5a23bacd5b92cc0ca3894c28f4" - integrity sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ== - -"@prisma/engines@5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.22.0.tgz#28f3f52a2812c990a8b66eb93a0987816a5b6d84" - integrity sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA== - dependencies: - "@prisma/debug" "5.22.0" - "@prisma/engines-version" "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" - "@prisma/fetch-engine" "5.22.0" - "@prisma/get-platform" "5.22.0" - -"@prisma/fetch-engine@5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz#4fb691b483a450c5548aac2f837b267dd50ef52e" - integrity sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA== - dependencies: - "@prisma/debug" "5.22.0" - "@prisma/engines-version" "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" - "@prisma/get-platform" "5.22.0" - -"@prisma/get-platform@5.22.0": - version "5.22.0" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.22.0.tgz#fc675bc9d12614ca2dade0506c9c4a77e7dddacd" - integrity sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q== - dependencies: - "@prisma/debug" "5.22.0" - -"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" - integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== - -"@protobufjs/base64@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" - integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== - -"@protobufjs/codegen@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" - integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== - -"@protobufjs/eventemitter@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" - integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== - -"@protobufjs/fetch@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" - integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== - dependencies: - "@protobufjs/aspromise" "^1.1.1" - "@protobufjs/inquire" "^1.1.0" - -"@protobufjs/float@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" - integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== - -"@protobufjs/inquire@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" - integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== - -"@protobufjs/path@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" - integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== - -"@protobufjs/pool@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" - integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== - -"@protobufjs/utf8@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" - integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== - -"@radix-ui/primitive@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" - integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/primitive@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" - integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== - -"@radix-ui/react-arrow@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" - integrity sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" - -"@radix-ui/react-arrow@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz#2103721933a8bfc6e53bbfbdc1aaad5fc8ba0dd7" - integrity sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w== - dependencies: - "@radix-ui/react-primitive" "2.0.1" - -"@radix-ui/react-compose-refs@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" - integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-compose-refs@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" - integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== - -"@radix-ui/react-context@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" - integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-context@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" - integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== - -"@radix-ui/react-dialog@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" - integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.5" - "@radix-ui/react-focus-guards" "1.0.1" - "@radix-ui/react-focus-scope" "1.0.4" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-portal" "1.0.4" - "@radix-ui/react-presence" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-slot" "1.0.2" - "@radix-ui/react-use-controllable-state" "1.0.1" - aria-hidden "^1.1.1" - react-remove-scroll "2.5.5" - -"@radix-ui/react-dialog@1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz#d68e977acfcc0d044b9dab47b6dd2c179d2b3191" - integrity sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA== - dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.3" - "@radix-ui/react-focus-guards" "1.1.1" - "@radix-ui/react-focus-scope" "1.1.1" - "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-portal" "1.1.3" - "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-slot" "1.1.1" - "@radix-ui/react-use-controllable-state" "1.1.0" - aria-hidden "^1.1.1" - react-remove-scroll "^2.6.1" - -"@radix-ui/react-dismissable-layer@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4" - integrity sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-escape-keydown" "1.0.3" - -"@radix-ui/react-dismissable-layer@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.2.tgz#771594b202f32bc8ffeb278c565f10c513814aee" - integrity sha512-kEHnlhv7wUggvhuJPkyw4qspXLJOdYoAP4dO2c8ngGuXTq1w/HZp1YeVB+NQ2KbH1iEG+pvOCGYSqh9HZOz6hg== - dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-escape-keydown" "1.1.0" - -"@radix-ui/react-dismissable-layer@1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz#4ee0f0f82d53bf5bd9db21665799bb0d1bad5ed8" - integrity sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg== - dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-escape-keydown" "1.1.0" - -"@radix-ui/react-focus-guards@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" - integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-focus-guards@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" - integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== - -"@radix-ui/react-focus-scope@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz#2ac45fce8c5bb33eb18419cdc1905ef4f1906525" - integrity sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - -"@radix-ui/react-focus-scope@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz#5c602115d1db1c4fcfa0fae4c3b09bb8919853cb" - integrity sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA== - dependencies: - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-use-callback-ref" "1.1.0" - -"@radix-ui/react-icons@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.0.tgz#c61af8f323d87682c5ca76b856d60c2312dbcb69" - integrity sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw== - -"@radix-ui/react-icons@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.3.2.tgz#09be63d178262181aeca5fb7f7bc944b10a7f441" - integrity sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g== - -"@radix-ui/react-id@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" - integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.1" - -"@radix-ui/react-id@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" - integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== - dependencies: - "@radix-ui/react-use-layout-effect" "1.1.0" - -"@radix-ui/react-popper@1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.3.tgz#24c03f527e7ac348fabf18c89795d85d21b00b42" - integrity sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w== - dependencies: - "@babel/runtime" "^7.13.10" - "@floating-ui/react-dom" "^2.0.0" - "@radix-ui/react-arrow" "1.0.3" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-layout-effect" "1.0.1" - "@radix-ui/react-use-rect" "1.0.1" - "@radix-ui/react-use-size" "1.0.1" - "@radix-ui/rect" "1.0.1" - -"@radix-ui/react-popper@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.1.tgz#2fc66cfc34f95f00d858924e3bee54beae2dff0a" - integrity sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw== - dependencies: - "@floating-ui/react-dom" "^2.0.0" - "@radix-ui/react-arrow" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-layout-effect" "1.1.0" - "@radix-ui/react-use-rect" "1.1.0" - "@radix-ui/react-use-size" "1.1.0" - "@radix-ui/rect" "1.1.0" - -"@radix-ui/react-portal@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.4.tgz#df4bfd353db3b1e84e639e9c63a5f2565fb00e15" - integrity sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" - -"@radix-ui/react-portal@1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.3.tgz#b0ea5141103a1671b715481b13440763d2ac4440" - integrity sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw== - dependencies: - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-use-layout-effect" "1.1.0" - -"@radix-ui/react-presence@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" - integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-use-layout-effect" "1.0.1" - -"@radix-ui/react-presence@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" - integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg== - dependencies: - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-use-layout-effect" "1.1.0" - -"@radix-ui/react-primitive@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" - integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-slot" "1.0.2" - -"@radix-ui/react-primitive@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz#6d9efc550f7520135366f333d1e820cf225fad9e" - integrity sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg== - dependencies: - "@radix-ui/react-slot" "1.1.1" - -"@radix-ui/react-slot@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" - integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - -"@radix-ui/react-slot@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.1.tgz#ab9a0ffae4027db7dc2af503c223c978706affc3" - integrity sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g== - dependencies: - "@radix-ui/react-compose-refs" "1.1.1" - -"@radix-ui/react-tooltip@1.0.7": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz#8f55070f852e7e7450cc1d9210b793d2e5a7686e" - integrity sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.5" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-popper" "1.1.3" - "@radix-ui/react-portal" "1.0.4" - "@radix-ui/react-presence" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-slot" "1.0.2" - "@radix-ui/react-use-controllable-state" "1.0.1" - "@radix-ui/react-visually-hidden" "1.0.3" - -"@radix-ui/react-tooltip@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.5.tgz#402f4f7019159bf4a40be3f1fa01978339ea33cc" - integrity sha512-IucoQPcK5nwUuztaxBQvudvYwH58wtRcJlv1qvaMSyIbL9dEBfFN0vRf/D8xDbu6HmAJLlNGty4z8Na+vIqe9Q== - dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.2" - "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-popper" "1.2.1" - "@radix-ui/react-portal" "1.1.3" - "@radix-ui/react-presence" "1.1.2" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-slot" "1.1.1" - "@radix-ui/react-use-controllable-state" "1.1.0" - "@radix-ui/react-visually-hidden" "1.1.1" - -"@radix-ui/react-use-callback-ref@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" - integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-use-callback-ref@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" - integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== - -"@radix-ui/react-use-controllable-state@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" - integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.1" - -"@radix-ui/react-use-controllable-state@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" - integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== - dependencies: - "@radix-ui/react-use-callback-ref" "1.1.0" - -"@radix-ui/react-use-escape-keydown@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" - integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.1" - -"@radix-ui/react-use-escape-keydown@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" - integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== - dependencies: - "@radix-ui/react-use-callback-ref" "1.1.0" - -"@radix-ui/react-use-layout-effect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" - integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/react-use-layout-effect@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" - integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== - -"@radix-ui/react-use-rect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2" - integrity sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/rect" "1.0.1" - -"@radix-ui/react-use-rect@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" - integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== - dependencies: - "@radix-ui/rect" "1.1.0" - -"@radix-ui/react-use-size@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz#1c5f5fea940a7d7ade77694bb98116fb49f870b2" - integrity sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.1" - -"@radix-ui/react-use-size@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" - integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== - dependencies: - "@radix-ui/react-use-layout-effect" "1.1.0" - -"@radix-ui/react-visually-hidden@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac" - integrity sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" - -"@radix-ui/react-visually-hidden@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz#f7b48c1af50dfdc366e92726aee6d591996c5752" - integrity sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg== - dependencies: - "@radix-ui/react-primitive" "2.0.1" - -"@radix-ui/rect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.1.tgz#bf8e7d947671996da2e30f4904ece343bc4a883f" - integrity sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ== - dependencies: - "@babel/runtime" "^7.13.10" - -"@radix-ui/rect@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" - integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== - -"@rollup/rollup-android-arm-eabi@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz#7f4c4d8cd5ccab6e95d6750dbe00321c1f30791e" - integrity sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ== - -"@rollup/rollup-android-arm64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz#17ea71695fb1518c2c324badbe431a0bd1879f2d" - integrity sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA== - -"@rollup/rollup-darwin-arm64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz#dac0f0d0cfa73e7d5225ae6d303c13c8979e7999" - integrity sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ== - -"@rollup/rollup-darwin-x64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz#8f63baa1d31784904a380d2e293fa1ddf53dd4a2" - integrity sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ== - -"@rollup/rollup-freebsd-arm64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz#30ed247e0df6e8858cdc6ae4090e12dbeb8ce946" - integrity sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA== - -"@rollup/rollup-freebsd-x64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz#57846f382fddbb508412ae07855b8a04c8f56282" - integrity sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ== - -"@rollup/rollup-linux-arm-gnueabihf@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz#378ca666c9dae5e6f94d1d351e7497c176e9b6df" - integrity sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA== - -"@rollup/rollup-linux-arm-musleabihf@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz#a692eff3bab330d5c33a5d5813a090c15374cddb" - integrity sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg== - -"@rollup/rollup-linux-arm64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz#6b1719b76088da5ac1ae1feccf48c5926b9e3db9" - integrity sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA== - -"@rollup/rollup-linux-arm64-musl@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz#865baf5b6f5ff67acb32e5a359508828e8dc5788" - integrity sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A== - -"@rollup/rollup-linux-loongarch64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz#23c6609ba0f7fa7a7f2038b6b6a08555a5055a87" - integrity sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA== - -"@rollup/rollup-linux-powerpc64le-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz#652ef0d9334a9f25b9daf85731242801cb0fc41c" - integrity sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A== - -"@rollup/rollup-linux-riscv64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz#1eb6651839ee6ebca64d6cc64febbd299e95e6bd" - integrity sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA== - -"@rollup/rollup-linux-s390x-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz#015c52293afb3ff2a293cf0936b1d43975c1e9cd" - integrity sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg== - -"@rollup/rollup-linux-x64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz#b83001b5abed2bcb5e2dbeec6a7e69b194235c1e" - integrity sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw== - -"@rollup/rollup-linux-x64-musl@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz#6cc7c84cd4563737f8593e66f33b57d8e228805b" - integrity sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g== - -"@rollup/rollup-win32-arm64-msvc@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz#631ffeee094d71279fcd1fe8072bdcf25311bc11" - integrity sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A== - -"@rollup/rollup-win32-ia32-msvc@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz#06d1d60d5b9f718e8a6c4a43f82e3f9e3254587f" - integrity sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA== - -"@rollup/rollup-win32-x64-msvc@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz#4dff5c4259ebe6c5b4a8f2c5bc3829b7a8447ff0" - integrity sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA== - -"@safe-global/safe-core-sdk-types@^1.9.2": - version "1.10.1" - resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-1.10.1.tgz#94331b982671d2f2b8cc23114c58baf63d460c81" - integrity sha512-BKvuYTLOlY16Rq6qCXglmnL6KxInDuXMFqZMaCzwDKiEh+uoHu3xCumG5tVtWOkCgBF4XEZXMqwZUiLcon7IsA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@safe-global/safe-deployments" "^1.20.2" - web3-core "^1.8.1" - web3-utils "^1.8.1" - -"@safe-global/safe-core-sdk-utils@^1.7.4": - version "1.7.4" - resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-utils/-/safe-core-sdk-utils-1.7.4.tgz#810d36cf9629129a28eb1b9c6e690b163834b572" - integrity sha512-ITocwSWlFUA1K9VMP/eJiMfgbP/I9qDxAaFz7ukj5N5NZD3ihVQZkmqML6hjse5UhrfjCnfIEcLkNZhtB2XC2Q== - dependencies: - "@safe-global/safe-core-sdk-types" "^1.9.2" - semver "^7.3.8" - web3-utils "^1.8.1" - -"@safe-global/safe-core-sdk@^3.3.5": - version "3.3.5" - resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk/-/safe-core-sdk-3.3.5.tgz#30884639d368a9f50aa5fc96f78de87261ebdab3" - integrity sha512-ul+WmpxZOXgDIXrZ6MIHptThYbm0CVV3/rypMQEn4tZLkudh/yXK7EuWBFnx9prR3MePuku51Zcz9fu1vi7sfQ== - dependencies: - "@ethersproject/solidity" "^5.7.0" - "@safe-global/safe-core-sdk-types" "^1.9.2" - "@safe-global/safe-core-sdk-utils" "^1.7.4" - "@safe-global/safe-deployments" "^1.25.0" - ethereumjs-util "^7.1.5" - semver "^7.3.8" - web3-utils "^1.8.1" - zksync-web3 "^0.14.3" - -"@safe-global/safe-deployments@^1.20.2", "@safe-global/safe-deployments@^1.25.0": - version "1.37.21" - resolved "https://registry.yarnpkg.com/@safe-global/safe-deployments/-/safe-deployments-1.37.21.tgz#9b194c08a5605bb012d0bc321a74d322d107e361" - integrity sha512-Q5qvcxXjAIcKOO8e3uQ/iNOSE5vRI+5jCO6JW/id5tEwMBtfyj5Ec2Vkk6nz0AM0uo2pyGROYjNTTuefoTthvQ== - dependencies: - semver "^7.6.2" - -"@safe-global/safe-ethers-adapters@0.1.0-alpha.19": - version "0.1.0-alpha.19" - resolved "https://registry.yarnpkg.com/@safe-global/safe-ethers-adapters/-/safe-ethers-adapters-0.1.0-alpha.19.tgz#5c1286e44696639ed7ea379b16cab62f5116df21" - integrity sha512-FKd1XySR/FGfEY/HDGfQPByTnOPWE4m6HuH/Q4PgizsGdgYa6kjUy0/UWTb42bOdkqeVm2XffPxErHK/BaUhaQ== - dependencies: - "@safe-global/safe-core-sdk" "^3.3.5" - "@safe-global/safe-core-sdk-types" "^1.9.2" - "@safe-global/safe-deployments" "^1.25.0" - axios "^0.27.2" - -"@safe-global/safe-ethers-lib@^1.9.4": - version "1.9.4" - resolved "https://registry.yarnpkg.com/@safe-global/safe-ethers-lib/-/safe-ethers-lib-1.9.4.tgz#049989a302c6f2010c574cf3a834b0cfb9cf67c5" - integrity sha512-WhzcmNun0s0VxeVQKRqaapV0vEpdm76zZBR2Du+S+58u1r57OjZkOSL2Gru0tdwkt3FIZZtE3OhDu09M70pVkA== - dependencies: - "@safe-global/safe-core-sdk-types" "^1.9.2" - "@safe-global/safe-core-sdk-utils" "^1.7.4" - ethers "5.7.2" - -"@scure/base@^1.1.3", "@scure/base@~1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.1.tgz#dd0b2a533063ca612c17aa9ad26424a2ff5aa865" - integrity sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ== - -"@scure/base@~1.1.0", "@scure/base@~1.1.2", "@scure/base@~1.1.6": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" - integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== - -"@scure/bip32@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" - integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== - dependencies: - "@noble/curves" "~1.2.0" - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.2" - -"@scure/bip32@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" - integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== - dependencies: - "@noble/curves" "~1.4.0" - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" - -"@scure/bip32@1.6.0", "@scure/bip32@^1.5.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.0.tgz#6dbc6b4af7c9101b351f41231a879d8da47e0891" - integrity sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA== - dependencies: - "@noble/curves" "~1.7.0" - "@noble/hashes" "~1.6.0" - "@scure/base" "~1.2.1" - -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" - integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== - dependencies: - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" - -"@scure/bip39@1.5.0", "@scure/bip39@^1.4.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.0.tgz#c8f9533dbd787641b047984356531d84485f19be" - integrity sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A== - dependencies: - "@noble/hashes" "~1.6.0" - "@scure/base" "~1.2.1" - -"@sec-ant/readable-stream@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c" - integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== - -"@sinclair/typebox@^0.31.28": - version "0.31.28" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.31.28.tgz#b68831e7bc7d09daac26968ea32f42bedc968ede" - integrity sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ== - -"@sindresorhus/merge-streams@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz#abb11d99aeb6d27f1b563c38147a72d50058e339" - integrity sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ== - -"@smithy/abort-controller@^3.1.9": - version "3.1.9" - resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.9.tgz#47d323f754136a489e972d7fd465d534d72fcbff" - integrity sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/config-resolver@^3.0.13": - version "3.0.13" - resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.13.tgz#653643a77a33d0f5907a5e7582353886b07ba752" - integrity sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg== - dependencies: - "@smithy/node-config-provider" "^3.1.12" - "@smithy/types" "^3.7.2" - "@smithy/util-config-provider" "^3.0.0" - "@smithy/util-middleware" "^3.0.11" - tslib "^2.6.2" - -"@smithy/core@^2.5.5": - version "2.5.5" - resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.5.5.tgz#c75b15caee9e58c800db3e6b99e9e373532d394a" - integrity sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw== - dependencies: - "@smithy/middleware-serde" "^3.0.11" - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - "@smithy/util-body-length-browser" "^3.0.0" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-stream" "^3.3.2" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@smithy/credential-provider-imds@^3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz#27ed2747074c86a7d627a98e56f324a65cba88de" - integrity sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw== - dependencies: - "@smithy/node-config-provider" "^3.1.12" - "@smithy/property-provider" "^3.1.11" - "@smithy/types" "^3.7.2" - "@smithy/url-parser" "^3.0.11" - tslib "^2.6.2" - -"@smithy/fetch-http-handler@^4.1.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz#f034ff16416b37d92908a1381ef5fddbf4ef1879" - integrity sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA== - dependencies: - "@smithy/protocol-http" "^4.1.8" - "@smithy/querystring-builder" "^3.0.11" - "@smithy/types" "^3.7.2" - "@smithy/util-base64" "^3.0.0" - tslib "^2.6.2" - -"@smithy/hash-node@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.11.tgz#99e09ead3fc99c8cd7ca0f254ea0e35714f2a0d3" - integrity sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA== - dependencies: - "@smithy/types" "^3.7.2" - "@smithy/util-buffer-from" "^3.0.0" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@smithy/invalid-dependency@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz#8144d7b0af9d34ab5f672e1f674f97f8740bb9ae" - integrity sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/is-array-buffer@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" - integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== - dependencies: - tslib "^2.6.2" - -"@smithy/is-array-buffer@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz#9a95c2d46b8768946a9eec7f935feaddcffa5e7a" - integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== - dependencies: - tslib "^2.6.2" - -"@smithy/middleware-content-length@^3.0.13": - version "3.0.13" - resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz#6e08fe52739ac8fb3996088e0f8837e4b2ea187f" - integrity sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw== - dependencies: - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/middleware-endpoint@^3.2.5": - version "3.2.5" - resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz#bdcfdf1f342cf933b0b8a709996f9a8fbb8148f4" - integrity sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg== - dependencies: - "@smithy/core" "^2.5.5" - "@smithy/middleware-serde" "^3.0.11" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - "@smithy/url-parser" "^3.0.11" - "@smithy/util-middleware" "^3.0.11" - tslib "^2.6.2" - -"@smithy/middleware-retry@^3.0.30": - version "3.0.30" - resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.30.tgz#2580322d0d28ad782b5b8c07c150b14efdc3b2f9" - integrity sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ== - dependencies: - "@smithy/node-config-provider" "^3.1.12" - "@smithy/protocol-http" "^4.1.8" - "@smithy/service-error-classification" "^3.0.11" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-retry" "^3.0.11" - tslib "^2.6.2" - uuid "^9.0.1" - -"@smithy/middleware-serde@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz#c7d54e0add4f83e05c6878a011fc664e21022f12" - integrity sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/middleware-stack@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz#453af2096924e4064d9da4e053cfdf65d9a36acc" - integrity sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/node-config-provider@^3.1.12": - version "3.1.12" - resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz#1b1d674fc83f943dc7b3017e37f16f374e878a6c" - integrity sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ== - dependencies: - "@smithy/property-provider" "^3.1.11" - "@smithy/shared-ini-file-loader" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/node-http-handler@^3.3.2": - version "3.3.2" - resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz#b34685863b74dabdaf7860aa81b42d0d5437c7e0" - integrity sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA== - dependencies: - "@smithy/abort-controller" "^3.1.9" - "@smithy/protocol-http" "^4.1.8" - "@smithy/querystring-builder" "^3.0.11" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/property-provider@^3.1.11": - version "3.1.11" - resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.11.tgz#161cf1c2a2ada361e417382c57f5ba6fbca8acad" - integrity sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/protocol-http@^4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.8.tgz#0461758671335f65e8ff3fc0885ab7ed253819c9" - integrity sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/querystring-builder@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz#2ed04adbe725671824c5613d0d6f9376d791a909" - integrity sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg== - dependencies: - "@smithy/types" "^3.7.2" - "@smithy/util-uri-escape" "^3.0.0" - tslib "^2.6.2" - -"@smithy/querystring-parser@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz#9d3177ea19ce8462f18d9712b395239e1ca1f969" - integrity sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/service-error-classification@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz#d3d7fc0aacd2e60d022507367e55c7939e5bcb8a" - integrity sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog== - dependencies: - "@smithy/types" "^3.7.2" - -"@smithy/shared-ini-file-loader@^3.1.12": - version "3.1.12" - resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz#d98b1b663eb18935ce2cbc79024631d34f54042a" - integrity sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/signature-v4@^4.2.4": - version "4.2.4" - resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.4.tgz#3501d3d09fd82768867bfc00a7be4bad62f62f4d" - integrity sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA== - dependencies: - "@smithy/is-array-buffer" "^3.0.0" - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - "@smithy/util-hex-encoding" "^3.0.0" - "@smithy/util-middleware" "^3.0.11" - "@smithy/util-uri-escape" "^3.0.0" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@smithy/smithy-client@^3.5.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.5.0.tgz#65cff262801b009998c1196764ee69929ee06f8a" - integrity sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg== - dependencies: - "@smithy/core" "^2.5.5" - "@smithy/middleware-endpoint" "^3.2.5" - "@smithy/middleware-stack" "^3.0.11" - "@smithy/protocol-http" "^4.1.8" - "@smithy/types" "^3.7.2" - "@smithy/util-stream" "^3.3.2" - tslib "^2.6.2" - -"@smithy/types@^3.7.2": - version "3.7.2" - resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.2.tgz#05cb14840ada6f966de1bf9a9c7dd86027343e10" - integrity sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg== - dependencies: - tslib "^2.6.2" - -"@smithy/url-parser@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.11.tgz#e5f5ffabfb6230159167cf4cc970705fca6b8b2d" - integrity sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw== - dependencies: - "@smithy/querystring-parser" "^3.0.11" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/util-base64@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" - integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== - dependencies: - "@smithy/util-buffer-from" "^3.0.0" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@smithy/util-body-length-browser@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz#86ec2f6256310b4845a2f064e2f571c1ca164ded" - integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== - dependencies: - tslib "^2.6.2" - -"@smithy/util-body-length-node@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz#99a291bae40d8932166907fe981d6a1f54298a6d" - integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== - dependencies: - tslib "^2.6.2" - -"@smithy/util-buffer-from@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" - integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== - dependencies: - "@smithy/is-array-buffer" "^2.2.0" - tslib "^2.6.2" - -"@smithy/util-buffer-from@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz#559fc1c86138a89b2edaefc1e6677780c24594e3" - integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== - dependencies: - "@smithy/is-array-buffer" "^3.0.0" - tslib "^2.6.2" - -"@smithy/util-config-provider@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz#62c6b73b22a430e84888a8f8da4b6029dd5b8efe" - integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== - dependencies: - tslib "^2.6.2" - -"@smithy/util-defaults-mode-browser@^3.0.30": - version "3.0.30" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.30.tgz#6c0d95af3f15bef8f1fe3f6217cc4f5ba8df5554" - integrity sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg== - dependencies: - "@smithy/property-provider" "^3.1.11" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - bowser "^2.11.0" - tslib "^2.6.2" - -"@smithy/util-defaults-mode-node@^3.0.30": - version "3.0.30" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.30.tgz#33cdb02f90944b9ff221e2f8e0904a63ac1e335f" - integrity sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow== - dependencies: - "@smithy/config-resolver" "^3.0.13" - "@smithy/credential-provider-imds" "^3.2.8" - "@smithy/node-config-provider" "^3.1.12" - "@smithy/property-provider" "^3.1.11" - "@smithy/smithy-client" "^3.5.0" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/util-endpoints@^2.1.7": - version "2.1.7" - resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz#a088ebfab946a7219dd4763bfced82709894b82d" - integrity sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw== - dependencies: - "@smithy/node-config-provider" "^3.1.12" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/util-hex-encoding@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" - integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== - dependencies: - tslib "^2.6.2" - -"@smithy/util-middleware@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.11.tgz#2ab5c17266b42c225e62befcffb048afa682b5bf" - integrity sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow== - dependencies: - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/util-retry@^3.0.11": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.11.tgz#d267e5ccb290165cee69732547fea17b695a7425" - integrity sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ== - dependencies: - "@smithy/service-error-classification" "^3.0.11" - "@smithy/types" "^3.7.2" - tslib "^2.6.2" - -"@smithy/util-stream@^3.3.2": - version "3.3.2" - resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.3.2.tgz#daeea26397e8541cf2499ce65bf0b8d528cba421" - integrity sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg== - dependencies: - "@smithy/fetch-http-handler" "^4.1.2" - "@smithy/node-http-handler" "^3.3.2" - "@smithy/types" "^3.7.2" - "@smithy/util-base64" "^3.0.0" - "@smithy/util-buffer-from" "^3.0.0" - "@smithy/util-hex-encoding" "^3.0.0" - "@smithy/util-utf8" "^3.0.0" - tslib "^2.6.2" - -"@smithy/util-uri-escape@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" - integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== - dependencies: - tslib "^2.6.2" - -"@smithy/util-utf8@^2.0.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" - integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== - dependencies: - "@smithy/util-buffer-from" "^2.2.0" - tslib "^2.6.2" - -"@smithy/util-utf8@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-3.0.0.tgz#1a6a823d47cbec1fd6933e5fc87df975286d9d6a" - integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== - dependencies: - "@smithy/util-buffer-from" "^3.0.0" - tslib "^2.6.2" - -"@stablelib/aead@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/aead/-/aead-1.0.1.tgz#c4b1106df9c23d1b867eb9b276d8f42d5fc4c0c3" - integrity sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg== - -"@stablelib/binary@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" - integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== - dependencies: - "@stablelib/int" "^1.0.1" - -"@stablelib/bytes@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/bytes/-/bytes-1.0.1.tgz#0f4aa7b03df3080b878c7dea927d01f42d6a20d8" - integrity sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ== - -"@stablelib/chacha20poly1305@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz#de6b18e283a9cb9b7530d8767f99cde1fec4c2ee" - integrity sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA== - dependencies: - "@stablelib/aead" "^1.0.1" - "@stablelib/binary" "^1.0.1" - "@stablelib/chacha" "^1.0.1" - "@stablelib/constant-time" "^1.0.1" - "@stablelib/poly1305" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/chacha@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/chacha/-/chacha-1.0.1.tgz#deccfac95083e30600c3f92803a3a1a4fa761371" - integrity sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/constant-time@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/constant-time/-/constant-time-1.0.1.tgz#bde361465e1cf7b9753061b77e376b0ca4c77e35" - integrity sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg== - -"@stablelib/ed25519@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@stablelib/ed25519/-/ed25519-1.0.3.tgz#f8fdeb6f77114897c887bb6a3138d659d3f35996" - integrity sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg== - dependencies: - "@stablelib/random" "^1.0.2" - "@stablelib/sha512" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/hash@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/hash/-/hash-1.0.1.tgz#3c944403ff2239fad8ebb9015e33e98444058bc5" - integrity sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg== - -"@stablelib/hkdf@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/hkdf/-/hkdf-1.0.1.tgz#b4efd47fd56fb43c6a13e8775a54b354f028d98d" - integrity sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g== - dependencies: - "@stablelib/hash" "^1.0.1" - "@stablelib/hmac" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/hmac@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/hmac/-/hmac-1.0.1.tgz#3d4c1b8cf194cb05d28155f0eed8a299620a07ec" - integrity sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA== - dependencies: - "@stablelib/constant-time" "^1.0.1" - "@stablelib/hash" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/int@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" - integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== - -"@stablelib/keyagreement@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz#4612efb0a30989deb437cd352cee637ca41fc50f" - integrity sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg== - dependencies: - "@stablelib/bytes" "^1.0.1" - -"@stablelib/poly1305@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/poly1305/-/poly1305-1.0.1.tgz#93bfb836c9384685d33d70080718deae4ddef1dc" - integrity sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA== - dependencies: - "@stablelib/constant-time" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/random@1.0.2", "@stablelib/random@^1.0.1", "@stablelib/random@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" - integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/sha256@1.0.1", "@stablelib/sha256@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/sha256/-/sha256-1.0.1.tgz#77b6675b67f9b0ea081d2e31bda4866297a3ae4f" - integrity sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/hash" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/sha512@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/sha512/-/sha512-1.0.1.tgz#6da700c901c2c0ceacbd3ae122a38ac57c72145f" - integrity sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/hash" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/wipe@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" - integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== - -"@stablelib/x25519@1.0.3", "@stablelib/x25519@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@stablelib/x25519/-/x25519-1.0.3.tgz#13c8174f774ea9f3e5e42213cbf9fc68a3c7b7fd" - integrity sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw== - dependencies: - "@stablelib/keyagreement" "^1.0.1" - "@stablelib/random" "^1.0.2" - "@stablelib/wipe" "^1.0.1" - -"@t3-oss/env-core@^0.6.0": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@t3-oss/env-core/-/env-core-0.6.1.tgz#24d04c22f3e73732e69ac8ff8b13ed00732d20aa" - integrity sha512-KQD7qEDJtkWIWWmTVjNvk0wnHpkvAQ6CRbUxbWMFNG/fiosBQDQvtRpBNu6USxBscJCoC4z6y7P9MN52/mLOzw== - -"@tanstack/query-core@5.29.0": - version "5.29.0" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.29.0.tgz#d0b3d12c07d5a47f42ab0c1ed4f317106f3d4b20" - integrity sha512-WgPTRs58hm9CMzEr5jpISe8HXa3qKQ8CxewdYZeVnA54JrPY9B1CZiwsCoLpLkf0dGRZq+LcX5OiJb0bEsOFww== - -"@tanstack/query-core@5.62.16": - version "5.62.16" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.62.16.tgz#f7efc92b1562a054748bc00c7f8d9d833407503b" - integrity sha512-9Sgft7Qavcd+sN0V25xVyo0nfmcZXBuODy3FVG7BMWTg1HMLm8wwG5tNlLlmSic1u7l1v786oavn+STiFaPH2g== - -"@tanstack/react-query@5.29.2": - version "5.29.2" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.29.2.tgz#c55ffbfaf9d8cf34212428db2b6c61ca6b545188" - integrity sha512-nyuWILR4u7H5moLGSiifLh8kIqQDLNOHGuSz0rcp+J75fNc8aQLyr5+I2JCHU3n+nJrTTW1ssgAD8HiKD7IFBQ== - dependencies: - "@tanstack/query-core" "5.29.0" - -"@tanstack/react-query@5.62.16": - version "5.62.16" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.62.16.tgz#c267d52650a9e0b61017b04faa43c2e0d2e1de5d" - integrity sha512-XJIZNj65d2IdvU8VBESmrPakfIm6FSdHDzrS1dPrAwmq3ZX+9riMh/ZfbNQHAWnhrgmq7KoXpgZSRyXnqMYT9A== - dependencies: - "@tanstack/query-core" "5.62.16" - -"@thirdweb-dev/auth@^4.1.87": - version "4.1.97" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/auth/-/auth-4.1.97.tgz#520aa657adb09b69bba167648e89ae9d88f8de2d" - integrity sha512-uJgbJxkFleQKKQgifuW9fJNfpBWPzbqSYAOirj/t/+Cfg/yKgoRGjtng3J8F7axLIGMgVR58V39/JRrrXyKJbg== - dependencies: - "@fastify/cookie" "^9.3.1" - "@thirdweb-dev/wallets" "2.5.39" - cookie "^0.6.0" - fastify-type-provider-zod "^1.1.9" - uuid "^9.0.1" - zod "^3.22.4" - -"@thirdweb-dev/chains@0.1.120", "@thirdweb-dev/chains@^0.1.77": - version "0.1.120" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/chains/-/chains-0.1.120.tgz#bf5a1e16eb5ef9bf57c54c544f0c6cfa8844ef54" - integrity sha512-6wj8eIylLk8wSyTUeN70LD72yN+QIwyynDfKtVGJXTcrEN2K+vuqnRE20gvA2ayX7KMyDyy76JxPlyv6SZyLGw== - -"@thirdweb-dev/contracts-js@1.3.23": - version "1.3.23" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/contracts-js/-/contracts-js-1.3.23.tgz#6140115cfc570100e69c27bbf9ff8ce99b9bb79b" - integrity sha512-AC8VbiYCZlWhiJl+uzScvbPznZce0mMzVwAZdBFZcfX7QE1kpDssocWna70ksmfCFkWLOrZuzTLYUoLatvOiBQ== - dependencies: - "@thirdweb-dev/contracts" "3.15.0" - -"@thirdweb-dev/contracts@3.15.0": - version "3.15.0" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/contracts/-/contracts-3.15.0.tgz#2d8dd4f6f2ec93dc22ae5b60240379bcc2f7d37a" - integrity sha512-sIXPy6zNqW9K9h8xgCnsRQVrqmmMdxoDqut4eAZj1CJzMax5TyrNBoSYCfAX0et8KApvBeCVeJQhUHSWpBNIVw== - dependencies: - "@openzeppelin/contracts" "^4.9.3" - "@openzeppelin/contracts-upgradeable" "^4.9.3" - "@thirdweb-dev/dynamic-contracts" "^1.2.4" - erc721a-upgradeable "^3.3.0" - solady "0.0.180" - -"@thirdweb-dev/crypto@0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/crypto/-/crypto-0.2.6.tgz#f1cd053164c338aaf5c64e8b014b6a870e3c4fed" - integrity sha512-l9kuYAw0+S+ItvQR2c5k6y+qn+L6YT1I5+KN+cQNN848nPFGECVajED2fVLadkZW7xaGEyc+U6nj8Y1KB5bgNg== - dependencies: - "@noble/hashes" "^1.4.0" - js-sha3 "^0.9.3" - -"@thirdweb-dev/dynamic-contracts@^1.2.4": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/dynamic-contracts/-/dynamic-contracts-1.2.5.tgz#f9735c0d46198e7bf2f98c277f0a9a79c54da1e8" - integrity sha512-YVsz+jUWbwj+6aF2eTZGMfyw47a1HRmgNl4LQ3gW9gwYL5y5+OX/yOzv6aV5ibvoqCk/k10aIVK2eFrcpMubQA== - -"@thirdweb-dev/generated-abis@0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/generated-abis/-/generated-abis-0.0.2.tgz#d0e4f51011ba2ce2bbc266c8a295b04ffd523bab" - integrity sha512-FztTzU0KF5u8usNBN5/5s4Ys082p+HwsMI9DfFqOBILm4OwEueLY4B5DbXjF1KlTIuqjGeMGmFDG98MXHUt73A== - -"@thirdweb-dev/merkletree@0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/merkletree/-/merkletree-0.2.6.tgz#874f6d6d98988150785d51c3ce616a06ae2f7563" - integrity sha512-dLw8sxzHSsMxuxwBDzkhwl4ksBKuB3Em7W/u7/2S5Ag0DsBmrrOZQz/+3Nf88mxCvq435PqyQsMPYfY2zJ22QA== - dependencies: - buffer "^6.0.3" - buffer-reverse "^1.0.1" - treeify "^1.1.0" - -"@thirdweb-dev/sdk@4.0.99", "@thirdweb-dev/sdk@^4.0.89": - version "4.0.99" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/sdk/-/sdk-4.0.99.tgz#07c4e0a2f2ec80bdd79df1d6565e11d42336fa4f" - integrity sha512-Zm1K+tmzz5mnVBues68Bi6vRO6RIjeiblt8URGxoyXNtfLNOmDDZ4t8Znsjg/oegrvh5LyT1XnZfepBZdl0ZSw== - dependencies: - "@eth-optimism/sdk" "3.3.2" - "@thirdweb-dev/chains" "0.1.120" - "@thirdweb-dev/contracts-js" "1.3.23" - "@thirdweb-dev/crypto" "0.2.6" - "@thirdweb-dev/generated-abis" "0.0.2" - "@thirdweb-dev/merkletree" "0.2.6" - "@thirdweb-dev/storage" "2.0.15" - abitype "1.0.0" - bn.js "5.2.1" - bs58 "^5.0.0" - buffer "^6.0.3" - eventemitter3 "^5.0.1" - fast-deep-equal "^3.1.3" - thirdweb "5.29.6" - tiny-invariant "^1.3.3" - tweetnacl "^1.0.3" - uuid "^9.0.1" - yaml "^2.4.1" - zod "^3.22.4" - -"@thirdweb-dev/service-utils@^0.4.28": - version "0.4.52" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/service-utils/-/service-utils-0.4.52.tgz#6473ab0fabf7e9ee138776855c5bb4729f88efdb" - integrity sha512-24g+juzurNBRQ4llwQBbfQE/msQplFTbnDsp2ihxkb9KThTwI5+d/jWvEoXumFDWm3Ji+FDBJIbNaY9H2Fz6AQ== - dependencies: - aws4fetch "1.0.20" - zod "3.23.8" - -"@thirdweb-dev/storage@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/storage/-/storage-2.0.15.tgz#12f0c9a61d752c118322d2410fd2efe4ba95d2a6" - integrity sha512-6E5ZlUCTPTMThpUvrPf1XASsfAmSHK/UZXPV5xLc7V66Qq5RTphQYUPoLDsvSNXECo65Jegj0LTIvRFFb30Z4w== - dependencies: - "@thirdweb-dev/crypto" "0.2.6" - cid-tool "^3.0.0" - form-data "^4.0.0" - uuid "^9.0.1" - -"@thirdweb-dev/wallets@2.5.39": - version "2.5.39" - resolved "https://registry.yarnpkg.com/@thirdweb-dev/wallets/-/wallets-2.5.39.tgz#8bc4db581a7651a320c738401bc6f284d7ec618b" - integrity sha512-VcPnpTHZZwdCap+o3mD8xngC2NV8s0DiQD0BdAuEEhQv+664gLsVRUxZKvW7h/lBXxkyEvSnSOgRwQ3zTVSPvw== - dependencies: - "@account-abstraction/contracts" "^0.5.0" - "@blocto/sdk" "0.10.2" - "@coinbase/wallet-sdk" "^3.9.0" - "@google-cloud/kms" "^4.4.0" - "@magic-ext/connect" "^6.7.2" - "@magic-ext/oauth" "^7.6.2" - "@magic-sdk/provider" "^13.6.2" - "@metamask/eth-sig-util" "^4.0.1" - "@paperxyz/embedded-wallet-service-sdk" "^1.2.5" - "@paperxyz/sdk-common-utilities" "^0.1.1" - "@safe-global/safe-core-sdk" "^3.3.5" - "@safe-global/safe-ethers-adapters" "0.1.0-alpha.19" - "@safe-global/safe-ethers-lib" "^1.9.4" - "@thirdweb-dev/chains" "0.1.120" - "@thirdweb-dev/contracts-js" "1.3.23" - "@thirdweb-dev/crypto" "0.2.6" - "@thirdweb-dev/sdk" "4.0.99" - "@walletconnect/core" "^2.13.2" - "@walletconnect/ethereum-provider" "2.12.2" - "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/modal" "^2.6.2" - "@walletconnect/types" "^2.13.2" - "@walletconnect/utils" "^2.13.2" - "@walletconnect/web3wallet" "^1.12.2" - asn1.js "5.4.1" - bn.js "5.2.1" - buffer "^6.0.3" - eth-provider "^0.13.6" - ethereumjs-util "^7.1.5" - eventemitter3 "^5.0.1" - key-encoder "2.0.3" - magic-sdk "^13.6.2" - web3-core "1.5.2" - -"@tootallnate/once@2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" - integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== - -"@types/base-64@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/base-64/-/base-64-1.0.2.tgz#f7bc80d242306f20c57f076d79d1efe2d31032ca" - integrity sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw== - -"@types/bn.js@*", "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": - version "5.1.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.6.tgz#9ba818eec0c85e4d3c679518428afdf611d03203" - integrity sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w== - dependencies: - "@types/node" "*" - -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/caseless@*": - version "0.12.5" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.5.tgz#db9468cb1b1b5a925b8f34822f1669df0c5472f5" - integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg== - -"@types/cli-progress@^3.11.3": - version "3.11.6" - resolved "https://registry.yarnpkg.com/@types/cli-progress/-/cli-progress-3.11.6.tgz#94b334ebe4190f710e51c1bf9b4fedb681fa9e45" - integrity sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA== - dependencies: - "@types/node" "*" - -"@types/crypto-js@^4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.2.2.tgz#771c4a768d94eb5922cc202a3009558204df0cea" - integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ== - -"@types/debug@^4.1.7": - version "4.1.12" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" - integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== - dependencies: - "@types/ms" "*" - -"@types/elliptic@^6.4.9": - version "6.4.18" - resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.18.tgz#bc96e26e1ccccbabe8b6f0e409c85898635482e1" - integrity sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw== - dependencies: - "@types/bn.js" "*" - -"@types/estree@1.0.6", "@types/estree@^1.0.0": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== - -"@types/glob@*": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" - integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== - dependencies: - "@types/minimatch" "^5.1.2" - "@types/node" "*" - -"@types/json-schema@^7.0.6": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/jsonwebtoken@^9.0.6": - version "9.0.7" - resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz#e49b96c2b29356ed462e9708fc73b833014727d2" - integrity sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg== - dependencies: - "@types/node" "*" - -"@types/linkify-it@^5": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" - integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q== - -"@types/long@^4.0.0": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" - integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== - -"@types/markdown-it@^14.1.1": - version "14.1.2" - resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61" - integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog== - dependencies: - "@types/linkify-it" "^5" - "@types/mdurl" "^2" - -"@types/mdurl@^2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" - integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg== - -"@types/minimatch@^5.1.2": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" - integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== - -"@types/ms@*": - version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" - integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== - -"@types/node-cron@^3.0.8": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@types/node-cron/-/node-cron-3.0.11.tgz#70b7131f65038ae63cfe841354c8aba363632344" - integrity sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg== - -"@types/node@*", "@types/node@>=13.7.0": - version "22.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" - integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== - dependencies: - undici-types "~6.20.0" - -"@types/node@^12.12.6": - version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" - integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== - -"@types/node@^18.15.4": - version "18.19.68" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.68.tgz#f4f10d9927a7eaf3568c46a6d739cc0967ccb701" - integrity sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw== - dependencies: - undici-types "~5.26.4" - -"@types/parse-json@^4.0.0": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" - integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== - -"@types/pbkdf2@^3.0.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.2.tgz#2dc43808e9985a2c69ff02e2d2027bd4fe33e8dc" - integrity sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew== - dependencies: - "@types/node" "*" - -"@types/pg@^8.6.6": - version "8.11.10" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.10.tgz#b8fb2b2b759d452fe3ec182beadd382563b63291" - integrity sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg== - dependencies: - "@types/node" "*" - pg-protocol "*" - pg-types "^4.0.1" - -"@types/request@^2.48.8": - version "2.48.12" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30" - integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw== - dependencies: - "@types/caseless" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - form-data "^2.5.0" - -"@types/rimraf@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.2.tgz#a63d175b331748e5220ad48c901d7bbf1f44eef8" - integrity sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ== - dependencies: - "@types/glob" "*" - "@types/node" "*" - -"@types/secp256k1@^4.0.1": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.6.tgz#d60ba2349a51c2cbc5e816dcd831a42029d376bf" - integrity sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ== - dependencies: - "@types/node" "*" - -"@types/tough-cookie@*": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" - integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== - -"@types/triple-beam@^1.3.2": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" - integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== - -"@types/trusted-types@^2.0.2": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" - integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== - -"@types/uuid@^9.0.1": - version "9.0.8" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" - integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== - -"@types/ws@^8.5.5": - version "8.5.13" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.13.tgz#6414c280875e2691d0d1e080b05addbf5cb91e20" - integrity sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA== - dependencies: - "@types/node" "*" - -"@vitest/coverage-v8@^2.0.3": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-2.1.8.tgz#738527e6e79cef5004248452527e272e0df12284" - integrity sha512-2Y7BPlKH18mAZYAW1tYByudlCYrQyl5RGvnnDYJKW5tCiO5qg3KSAy3XAxcxKz900a0ZXxWtKrMuZLe3lKBpJw== - dependencies: - "@ampproject/remapping" "^2.3.0" - "@bcoe/v8-coverage" "^0.2.3" - debug "^4.3.7" - istanbul-lib-coverage "^3.2.2" - istanbul-lib-report "^3.0.1" - istanbul-lib-source-maps "^5.0.6" - istanbul-reports "^3.1.7" - magic-string "^0.30.12" - magicast "^0.3.5" - std-env "^3.8.0" - test-exclude "^7.0.1" - tinyrainbow "^1.2.0" - -"@vitest/expect@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.8.tgz#13fad0e8d5a0bf0feb675dcf1d1f1a36a1773bc1" - integrity sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw== - dependencies: - "@vitest/spy" "2.1.8" - "@vitest/utils" "2.1.8" - chai "^5.1.2" - tinyrainbow "^1.2.0" - -"@vitest/mocker@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.8.tgz#51dec42ac244e949d20009249e033e274e323f73" - integrity sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA== - dependencies: - "@vitest/spy" "2.1.8" - estree-walker "^3.0.3" - magic-string "^0.30.12" - -"@vitest/pretty-format@2.1.8", "@vitest/pretty-format@^2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.8.tgz#88f47726e5d0cf4ba873d50c135b02e4395e2bca" - integrity sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ== - dependencies: - tinyrainbow "^1.2.0" - -"@vitest/runner@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.8.tgz#b0e2dd29ca49c25e9323ea2a45a5125d8729759f" - integrity sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg== - dependencies: - "@vitest/utils" "2.1.8" - pathe "^1.1.2" - -"@vitest/snapshot@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.8.tgz#d5dc204f4b95dc8b5e468b455dfc99000047d2de" - integrity sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg== - dependencies: - "@vitest/pretty-format" "2.1.8" - magic-string "^0.30.12" - pathe "^1.1.2" - -"@vitest/spy@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.8.tgz#bc41af3e1e6a41ae3b67e51f09724136b88fa447" - integrity sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg== - dependencies: - tinyspy "^3.0.2" - -"@vitest/utils@2.1.8": - version "2.1.8" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.8.tgz#f8ef85525f3362ebd37fd25d268745108d6ae388" - integrity sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA== - dependencies: - "@vitest/pretty-format" "2.1.8" - loupe "^3.1.2" - tinyrainbow "^1.2.0" - -"@walletconnect/auth-client@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@walletconnect/auth-client/-/auth-client-2.1.2.tgz#cee304fb0cdca76f6bf4aafac96ef9301862a7e8" - integrity sha512-ubJLn+vGb8sTdBFX6xAh4kjR5idrtS3RBngQWaJJJpEPBQmxMb8pM2q0FIRs8Is4K6jKy+uEhusMV+7ZBmTzjw== - dependencies: - "@ethersproject/hash" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@stablelib/random" "^1.0.2" - "@stablelib/sha256" "^1.0.1" - "@walletconnect/core" "^2.10.1" - "@walletconnect/events" "^1.0.1" - "@walletconnect/heartbeat" "^1.2.1" - "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/logger" "^2.0.1" - "@walletconnect/time" "^1.0.2" - "@walletconnect/utils" "^2.10.1" - events "^3.3.0" - isomorphic-unfetch "^3.1.0" - -"@walletconnect/core@2.12.2": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.12.2.tgz#12bd568b90daed876e58ebcc098c12843a3321e6" - integrity sha512-7Adv/b3pp9F42BkvReaaM4KS8NEvlkS7AMtwO3uF/o6aRMKtcfTJq9/jgWdKJh4RP8pPRTRFjCw6XQ/RZtT4aQ== - dependencies: - "@walletconnect/heartbeat" "1.2.1" - "@walletconnect/jsonrpc-provider" "1.0.13" - "@walletconnect/jsonrpc-types" "1.0.3" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "1.0.14" - "@walletconnect/keyvaluestorage" "^1.1.1" - "@walletconnect/logger" "^2.1.2" - "@walletconnect/relay-api" "^1.0.9" - "@walletconnect/relay-auth" "^1.0.4" - "@walletconnect/safe-json" "^1.0.2" - "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.12.2" - "@walletconnect/utils" "2.12.2" - events "^3.3.0" - isomorphic-unfetch "3.1.0" - lodash.isequal "4.5.0" - uint8arrays "^3.1.0" - -"@walletconnect/core@2.17.1": - version "2.17.1" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.17.1.tgz#8ee51d630068e4450014fe62a76af895ab1d349d" - integrity sha512-SMgJR5hEyEE/tENIuvlEb4aB9tmMXPzQ38Y61VgYBmwAFEhOHtpt8EDfnfRWqEhMyXuBXG4K70Yh8c67Yry+Xw== - dependencies: - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "1.0.14" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.1" - "@walletconnect/utils" "2.17.1" - "@walletconnect/window-getters" "1.0.1" - events "3.3.0" - lodash.isequal "4.5.0" - uint8arrays "3.1.0" - -"@walletconnect/core@2.17.2", "@walletconnect/core@^2.10.1", "@walletconnect/core@^2.13.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.17.2.tgz#877dc03f190d7b262bff8ce346330fdf1019cd83" - integrity sha512-O9VUsFg78CbvIaxfQuZMsHcJ4a2Z16DRz/O4S+uOAcGKhH/i/ln8hp864Tb+xRvifWSzaZ6CeAVxk657F+pscA== - dependencies: - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "1.0.14" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/utils" "2.17.2" - "@walletconnect/window-getters" "1.0.1" - events "3.3.0" - lodash.isequal "4.5.0" - uint8arrays "3.1.0" - -"@walletconnect/core@2.17.3": - version "2.17.3" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.17.3.tgz#e59045a666951e9fc2e8420130c4f93221bd2492" - integrity sha512-57uv0FW4L6H/tmkb1kS2nG41MDguyDgZbGR58nkDUd1TO/HydyiTByVOhFzIxgN331cnY/1G1rMaKqncgdnOFA== - dependencies: - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/jsonrpc-ws-connection" "1.0.16" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.3" - "@walletconnect/utils" "2.17.3" - "@walletconnect/window-getters" "1.0.1" - events "3.3.0" - lodash.isequal "4.5.0" - uint8arrays "3.1.0" - -"@walletconnect/environment@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" - integrity sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg== - dependencies: - tslib "1.14.1" - -"@walletconnect/ethereum-provider@2.12.2": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.12.2.tgz#43195a14cd43f928b2fcbba6b1a08e17e7838c4f" - integrity sha512-vBl2zCnNm2iPaomJdr5YT16cT7aa8cH2WFs6879XPngU5i7HXS3bU6TamhyhKKl13sdIfifmCkCC+RWn5GdPMw== - dependencies: - "@walletconnect/jsonrpc-http-connection" "^1.0.7" - "@walletconnect/jsonrpc-provider" "^1.0.13" - "@walletconnect/jsonrpc-types" "^1.0.3" - "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/modal" "^2.6.2" - "@walletconnect/sign-client" "2.12.2" - "@walletconnect/types" "2.12.2" - "@walletconnect/universal-provider" "2.12.2" - "@walletconnect/utils" "2.12.2" - events "^3.3.0" - -"@walletconnect/ethereum-provider@2.17.3": - version "2.17.3" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.17.3.tgz#53c546c56cb5033258cf4070677d0ba1208a0d6a" - integrity sha512-fgoT+dT9M1P6IIUtBl66ddD+4IJYqdhdAYkW+wa6jbctxKlHYSXf9HsgF/Vvv9lMnxHdAIz0W9VN4D/m20MamA== - dependencies: - "@walletconnect/jsonrpc-http-connection" "1.0.8" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/modal" "2.7.0" - "@walletconnect/sign-client" "2.17.3" - "@walletconnect/types" "2.17.3" - "@walletconnect/universal-provider" "2.17.3" - "@walletconnect/utils" "2.17.3" - events "3.3.0" - -"@walletconnect/events@1.0.1", "@walletconnect/events@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c" - integrity sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ== - dependencies: - keyvaluestorage-interface "^1.0.0" - tslib "1.14.1" - -"@walletconnect/heartbeat@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz#afaa3a53232ae182d7c9cff41c1084472d8f32e9" - integrity sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q== - dependencies: - "@walletconnect/events" "^1.0.1" - "@walletconnect/time" "^1.0.2" - tslib "1.14.1" - -"@walletconnect/heartbeat@1.2.2", "@walletconnect/heartbeat@^1.2.1": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz#e8dc5179db7769950c6f9cf59b23516d9b95227d" - integrity sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw== - dependencies: - "@walletconnect/events" "^1.0.1" - "@walletconnect/time" "^1.0.2" - events "^3.3.0" - -"@walletconnect/jsonrpc-http-connection@1.0.8", "@walletconnect/jsonrpc-http-connection@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz#2f4c3948f074960a3edd07909560f3be13e2c7ae" - integrity sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw== - dependencies: - "@walletconnect/jsonrpc-utils" "^1.0.6" - "@walletconnect/safe-json" "^1.0.1" - cross-fetch "^3.1.4" - events "^3.3.0" - -"@walletconnect/jsonrpc-provider@1.0.13": - version "1.0.13" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b" - integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g== - dependencies: - "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/safe-json" "^1.0.2" - tslib "1.14.1" - -"@walletconnect/jsonrpc-provider@1.0.14", "@walletconnect/jsonrpc-provider@^1.0.13": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz#696f3e3b6d728b361f2e8b853cfc6afbdf2e4e3e" - integrity sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow== - dependencies: - "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/safe-json" "^1.0.2" - events "^3.3.0" - -"@walletconnect/jsonrpc-types@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz#65e3b77046f1a7fa8347ae02bc1b841abe6f290c" - integrity sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw== - dependencies: - keyvaluestorage-interface "^1.0.0" - tslib "1.14.1" - -"@walletconnect/jsonrpc-types@1.0.4", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz#ce1a667d79eadf2a2d9d002c152ceb68739c230c" - integrity sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ== - dependencies: - events "^3.3.0" - keyvaluestorage-interface "^1.0.0" - -"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@walletconnect/jsonrpc-utils@^1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" - integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== - dependencies: - "@walletconnect/environment" "^1.0.1" - "@walletconnect/jsonrpc-types" "^1.0.3" - tslib "1.14.1" - -"@walletconnect/jsonrpc-ws-connection@1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz#eec700e74766c7887de2bd76c91a0206628732aa" - integrity sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA== - dependencies: - "@walletconnect/jsonrpc-utils" "^1.0.6" - "@walletconnect/safe-json" "^1.0.2" - events "^3.3.0" - ws "^7.5.1" - -"@walletconnect/jsonrpc-ws-connection@1.0.16": - version "1.0.16" - resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz#666bb13fbf32a2d4f7912d5b4d0bdef26a1d057b" - integrity sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q== - dependencies: - "@walletconnect/jsonrpc-utils" "^1.0.6" - "@walletconnect/safe-json" "^1.0.2" - events "^3.3.0" - ws "^7.5.1" - -"@walletconnect/keyvaluestorage@1.1.1", "@walletconnect/keyvaluestorage@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" - integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== - dependencies: - "@walletconnect/safe-json" "^1.0.1" - idb-keyval "^6.2.1" - unstorage "^1.9.0" - -"@walletconnect/logger@2.1.2", "@walletconnect/logger@^2.0.1", "@walletconnect/logger@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.1.2.tgz#813c9af61b96323a99f16c10089bfeb525e2a272" - integrity sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw== - dependencies: - "@walletconnect/safe-json" "^1.0.2" - pino "7.11.0" - -"@walletconnect/modal-core@2.7.0": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.7.0.tgz#73c13c3b7b0abf9ccdbac9b242254a86327ce0a4" - integrity sha512-oyMIfdlNdpyKF2kTJowTixZSo0PGlCJRdssUN/EZdA6H6v03hZnf09JnwpljZNfir2M65Dvjm/15nGrDQnlxSA== - dependencies: - valtio "1.11.2" - -"@walletconnect/modal-ui@2.7.0": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@walletconnect/modal-ui/-/modal-ui-2.7.0.tgz#dbbb7ee46a5a25f7d39db622706f2d197b268cbb" - integrity sha512-gERYvU7D7K1ANCN/8vUgsE0d2hnRemfAFZ2novm9aZBg7TEd/4EgB+AqbJ+1dc7GhOL6dazckVq78TgccHb7mQ== - dependencies: - "@walletconnect/modal-core" "2.7.0" - lit "2.8.0" - motion "10.16.2" - qrcode "1.5.3" - -"@walletconnect/modal@2.7.0", "@walletconnect/modal@^2.6.2": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.7.0.tgz#55f969796d104cce1205f5f844d8f8438b79723a" - integrity sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw== - dependencies: - "@walletconnect/modal-core" "2.7.0" - "@walletconnect/modal-ui" "2.7.0" - -"@walletconnect/relay-api@1.0.11", "@walletconnect/relay-api@^1.0.9": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.11.tgz#80ab7ef2e83c6c173be1a59756f95e515fb63224" - integrity sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q== - dependencies: - "@walletconnect/jsonrpc-types" "^1.0.2" - -"@walletconnect/relay-auth@1.0.4", "@walletconnect/relay-auth@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz#0b5c55c9aa3b0ef61f526ce679f3ff8a5c4c2c7c" - integrity sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ== - dependencies: - "@stablelib/ed25519" "^1.0.2" - "@stablelib/random" "^1.0.1" - "@walletconnect/safe-json" "^1.0.1" - "@walletconnect/time" "^1.0.2" - tslib "1.14.1" - uint8arrays "^3.0.0" - -"@walletconnect/safe-json@1.0.2", "@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" - integrity sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA== - dependencies: - tslib "1.14.1" - -"@walletconnect/sign-client@2.12.2": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.12.2.tgz#10cddcba3740f726149c33ef1a9040a808d65e08" - integrity sha512-cM0ualXj6nVvLqS4BDNRk+ZWR+lubcsz/IHreH+3wYrQ2sV+C0fN6ctrd7MMGZss0C0qacWCx0pm62ZBuoKvqA== - dependencies: - "@walletconnect/core" "2.12.2" - "@walletconnect/events" "^1.0.1" - "@walletconnect/heartbeat" "1.2.1" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "^2.1.2" - "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.12.2" - "@walletconnect/utils" "2.12.2" - events "^3.3.0" - -"@walletconnect/sign-client@2.17.1": - version "2.17.1" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.17.1.tgz#0777536427eba1b725c111ecc08eb301e05a8c55" - integrity sha512-6rLw6YNy0smslH9wrFTbNiYrGsL3DrOsS5FcuU4gIN6oh8pGYOFZ5FiSyTTroc5tngOk3/Sd7dlGY9S7O4nveg== - dependencies: - "@walletconnect/core" "2.17.1" - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.1" - "@walletconnect/utils" "2.17.1" - events "3.3.0" - -"@walletconnect/sign-client@2.17.3": - version "2.17.3" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.17.3.tgz#86c116bc927946bffa8415ca8d92d3ef412082e1" - integrity sha512-OzOWxRTfVGCHU3OOF6ibPkgPfDpivFJjuknfcOUt9PYWpTAv6YKOmT4cyfBPhc7llruyHpV44fYbykMcLIvEcg== - dependencies: - "@walletconnect/core" "2.17.3" - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.3" - "@walletconnect/utils" "2.17.3" - events "3.3.0" - -"@walletconnect/sign-client@^2.13.1": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.17.2.tgz#b8bd125d7c34a67916745ebbdbbc834db5518c8b" - integrity sha512-/wigdCIQjlBXSWY43Id0IPvZ5biq4HiiQZti8Ljvx408UYjmqcxcBitbj2UJXMYkid7704JWAB2mw32I1HgshQ== - dependencies: - "@walletconnect/core" "2.17.2" - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/utils" "2.17.2" - events "3.3.0" - -"@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" - integrity sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g== - dependencies: - tslib "1.14.1" - -"@walletconnect/types@2.12.2": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.12.2.tgz#8b64a2015a0a96972d28acb2ff317a9a994abfdb" - integrity sha512-9CmwTlPbrFTzayTL9q7xM7s3KTJkS6kYFtH2m1/fHFgALs6pIUjf1qAx1TF2E4tv7SEzLAIzU4NqgYUt2vWXTg== - dependencies: - "@walletconnect/events" "^1.0.1" - "@walletconnect/heartbeat" "1.2.1" - "@walletconnect/jsonrpc-types" "1.0.3" - "@walletconnect/keyvaluestorage" "^1.1.1" - "@walletconnect/logger" "^2.0.1" - events "^3.3.0" - -"@walletconnect/types@2.17.1": - version "2.17.1" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.17.1.tgz#425dedbe5853231252d081f61448c55ecd341c96" - integrity sha512-aiUeBE3EZZTsZBv5Cju3D0PWAsZCMks1g3hzQs9oNtrbuLL6pKKU0/zpKwk4vGywszxPvC3U0tBCku9LLsH/0A== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - events "3.3.0" - -"@walletconnect/types@2.17.2", "@walletconnect/types@^2.13.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.17.2.tgz#f9afff242563be33f377de689b03b482f5b20aee" - integrity sha512-j/+0WuO00lR8ntu7b1+MKe/r59hNwYLFzW0tTmozzhfAlDL+dYwWasDBNq4AH8NbVd7vlPCQWmncH7/6FVtOfQ== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - events "3.3.0" - -"@walletconnect/types@2.17.3": - version "2.17.3" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.17.3.tgz#906f25cf0c9691704b9161eaa305262b0e7626d0" - integrity sha512-5eFxnbZGJJx0IQyCS99qz+OvozpLJJYfVG96dEHGgbzZMd+C9V1eitYqVClx26uX6V+WQVqVwjpD2Dyzie++Wg== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/heartbeat" "1.2.2" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - events "3.3.0" - -"@walletconnect/universal-provider@2.12.2": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.12.2.tgz#0c855bbb5584fd11bdf2318344fe6f42fa3e91cb" - integrity sha512-0k5ZgSkABopQLVhkiwl2gRGG7dAP4SWiI915pIlyN5sRvWV+qX1ALhWAmRcdv0TXWlKHDcDgPJw/q2sCSAHuMQ== - dependencies: - "@walletconnect/jsonrpc-http-connection" "^1.0.7" - "@walletconnect/jsonrpc-provider" "1.0.13" - "@walletconnect/jsonrpc-types" "^1.0.2" - "@walletconnect/jsonrpc-utils" "^1.0.7" - "@walletconnect/logger" "^2.1.2" - "@walletconnect/sign-client" "2.12.2" - "@walletconnect/types" "2.12.2" - "@walletconnect/utils" "2.12.2" - events "^3.3.0" - -"@walletconnect/universal-provider@2.17.3": - version "2.17.3" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.17.3.tgz#2a1aaabe796d056911c5bf10dbd8fa5dd1395016" - integrity sha512-Aen8h+vWTN57sv792i96vaTpN06WnpFUWhACY5gHrpL2XgRKmoXUgW7793p252QdgyofNAOol7wJEs1gX8FjgQ== - dependencies: - "@walletconnect/events" "1.0.1" - "@walletconnect/jsonrpc-http-connection" "1.0.8" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-types" "1.0.4" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/logger" "2.1.2" - "@walletconnect/sign-client" "2.17.3" - "@walletconnect/types" "2.17.3" - "@walletconnect/utils" "2.17.3" - events "3.3.0" - lodash "4.17.21" - -"@walletconnect/utils@2.12.2": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.12.2.tgz#a2c349d4effef7c1c5e72e74a5483d8dfbb10918" - integrity sha512-zf50HeS3SfoLv1N9GPl2IXTZ9TsXfet4usVAsZmX9P6/Xzq7d/7QakjVQCHH/Wk1O9XkcsfeoZoUhRxoMJ5uJw== - dependencies: - "@stablelib/chacha20poly1305" "1.0.1" - "@stablelib/hkdf" "1.0.1" - "@stablelib/random" "^1.0.2" - "@stablelib/sha256" "1.0.1" - "@stablelib/x25519" "^1.0.3" - "@walletconnect/relay-api" "^1.0.9" - "@walletconnect/safe-json" "^1.0.2" - "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.12.2" - "@walletconnect/window-getters" "^1.0.1" - "@walletconnect/window-metadata" "^1.0.1" - detect-browser "5.3.0" - query-string "7.1.3" - uint8arrays "^3.1.0" - -"@walletconnect/utils@2.17.1": - version "2.17.1" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.17.1.tgz#fc57ffb89fc101fa1bf015de016ea01091d10ae0" - integrity sha512-KL7pPwq7qUC+zcTmvxGqIyYanfHgBQ+PFd0TEblg88jM7EjuDLhjyyjtkhyE/2q7QgR7OanIK7pCpilhWvBsBQ== - dependencies: - "@ethersproject/hash" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@stablelib/chacha20poly1305" "1.0.1" - "@stablelib/hkdf" "1.0.1" - "@stablelib/random" "1.0.2" - "@stablelib/sha256" "1.0.1" - "@stablelib/x25519" "1.0.3" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.1" - "@walletconnect/window-getters" "1.0.1" - "@walletconnect/window-metadata" "1.0.1" - detect-browser "5.3.0" - elliptic "6.5.7" - query-string "7.1.3" - uint8arrays "3.1.0" - -"@walletconnect/utils@2.17.2", "@walletconnect/utils@^2.10.1", "@walletconnect/utils@^2.13.2": - version "2.17.2" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.17.2.tgz#b4b12e3f5ebbfd883b2a5c87fb818e53501dc7ea" - integrity sha512-T7eLRiuw96fgwUy2A5NZB5Eu87ukX8RCVoO9lji34RFV4o2IGU9FhTEWyd4QQKI8OuQRjSknhbJs0tU0r0faPw== - dependencies: - "@ethersproject/hash" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@stablelib/chacha20poly1305" "1.0.1" - "@stablelib/hkdf" "1.0.1" - "@stablelib/random" "1.0.2" - "@stablelib/sha256" "1.0.1" - "@stablelib/x25519" "1.0.3" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.2" - "@walletconnect/window-getters" "1.0.1" - "@walletconnect/window-metadata" "1.0.1" - detect-browser "5.3.0" - elliptic "6.6.0" - query-string "7.1.3" - uint8arrays "3.1.0" - -"@walletconnect/utils@2.17.3": - version "2.17.3" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.17.3.tgz#a22938567febc3e3771efae8eb351adf3d499a8d" - integrity sha512-tG77UpZNeLYgeOwViwWnifpyBatkPlpKSSayhN0gcjY1lZAUNqtYslpm4AdTxlrA3pL61MnyybXgWYT5eZjarw== - dependencies: - "@ethersproject/hash" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@stablelib/chacha20poly1305" "1.0.1" - "@stablelib/hkdf" "1.0.1" - "@stablelib/random" "1.0.2" - "@stablelib/sha256" "1.0.1" - "@stablelib/x25519" "1.0.3" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/keyvaluestorage" "1.1.1" - "@walletconnect/relay-api" "1.0.11" - "@walletconnect/relay-auth" "1.0.4" - "@walletconnect/safe-json" "1.0.2" - "@walletconnect/time" "1.0.2" - "@walletconnect/types" "2.17.3" - "@walletconnect/window-getters" "1.0.1" - "@walletconnect/window-metadata" "1.0.1" - detect-browser "5.3.0" - elliptic "6.6.1" - query-string "7.1.3" - uint8arrays "3.1.0" - -"@walletconnect/web3wallet@^1.12.2": - version "1.16.1" - resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.16.1.tgz#53abb98fea6f1ac77704d4e4c91288e0300f2fb9" - integrity sha512-l6jVoLEh/UtRfvYUDs52fN+LYXsBgx3F9WfErJuCSCFfpbxDKIzM2Y9sI0WI1/5dWN5sh24H1zNCXnQ4JJltZw== - dependencies: - "@walletconnect/auth-client" "2.1.2" - "@walletconnect/core" "2.17.1" - "@walletconnect/jsonrpc-provider" "1.0.14" - "@walletconnect/jsonrpc-utils" "1.0.8" - "@walletconnect/logger" "2.1.2" - "@walletconnect/sign-client" "2.17.1" - "@walletconnect/types" "2.17.1" - "@walletconnect/utils" "2.17.1" - -"@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" - integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== - dependencies: - tslib "1.14.1" - -"@walletconnect/window-metadata@1.0.1", "@walletconnect/window-metadata@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" - integrity sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA== - dependencies: - "@walletconnect/window-getters" "^1.0.1" - tslib "1.14.1" - -abitype@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" - integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== - -abitype@1.0.7, abitype@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.7.tgz#876a0005d211e1c9132825d45bcee7b46416b284" - integrity sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -abortcontroller-polyfill@^1.7.5: - version "1.7.8" - resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz#fe8d4370403f02e2aa37e3d2b0b178bae9d83f49" - integrity sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ== - -abstract-logging@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" - integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== - -acorn-import-attributes@^1.9.5: - version "1.9.5" - resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" - integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.14.0, acorn@^8.8.2, acorn@^8.9.0: - version "8.14.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -agent-base@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" - integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-formats@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" - integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== - dependencies: - ajv "^8.0.0" - -ajv@^8.0.0, ajv@^8.10.0, ajv@^8.11.0: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" - integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -anymatch@^3.1.3, anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-hidden@^1.1.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" - integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== - dependencies: - tslib "^2.0.0" - -arrify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - -asn1.js@5.4.1, asn1.js@^5.0.1, asn1.js@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -asn1.js@^4.10.1: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1js@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38" - integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ== - dependencies: - pvtsutils "^1.3.2" - pvutils "^1.1.3" - tslib "^2.4.0" - -assert@^1.1.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.1.tgz#038ab248e4ff078e7bc2485ba6e6388466c78f76" - integrity sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A== - dependencies: - object.assign "^4.1.4" - util "^0.10.4" - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assertion-error@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" - integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== - -async-mutex@^0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.2.6.tgz#0d7a3deb978bc2b984d5908a2038e1ae2e54ff40" - integrity sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw== - dependencies: - tslib "^2.0.0" - -async@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -atomic-sleep@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" - integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -avvio@^8.3.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/avvio/-/avvio-8.4.0.tgz#7cbd5bca74f0c9effa944ced601f94ffd8afc5ed" - integrity sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA== - dependencies: - "@fastify/error" "^3.3.0" - fastq "^1.17.1" - -aws-kms-signer@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/aws-kms-signer/-/aws-kms-signer-0.5.3.tgz#02f9c3122ba79c6bf28e43f2cf3fad1db06afcf9" - integrity sha512-NUtftorrEcO+ODBfL4S/IIxNJMljaM/l233TRCFK0L0sOY/nOjbm2BLqLQOK/EUZ5i0pP1HK/32Lp6APdY9nCg== - dependencies: - "@aws-sdk/client-kms" "^3.28.0" - asn1js "^3.0.5" - bn.js "^5.2.0" - keccak "^3.0.2" - secp256k1 "4.0" - -aws-sdk@^2.922.0: - version "2.1692.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1692.0.tgz#9dac5f7bfcc5ab45825cc8591b12753aa7d2902c" - integrity sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.6.2" - -aws4fetch@1.0.20: - version "1.0.20" - resolved "https://registry.yarnpkg.com/aws4fetch/-/aws4fetch-1.0.20.tgz#090d6c65e32c6df645dd5e5acf04cc56da575cbe" - integrity sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g== - -axios@>=1.7.8, axios@^0.21.0, axios@^0.27.2, axios@^1.6.2: - version "1.7.9" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" - integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== - dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -babel-plugin-macros@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" - integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== - dependencies: - "@babel/runtime" "^7.12.5" - cosmiconfig "^7.0.0" - resolve "^1.19.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base-64@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a" - integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg== - -base-x@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" - integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== - dependencies: - safe-buffer "^5.0.1" - -base-x@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" - integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== - -base64-js@^1.0.2, base64-js@^1.3.0, base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -bignumber.js@^9.0.0, bignumber.js@^9.0.1: - version "9.1.2" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" - integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== - -binary-extensions@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" - integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== - -bintrees@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8" - integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw== - -blakejs@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" - integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== - -bluebird@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -bn.js@5.2.1, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: - version "4.12.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" - integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== - -body-parser@>=1.20.3: - version "1.20.3" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" - integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.13.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -bowser@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" - integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3, braces@~3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browserify-aes@^1.0.4, browserify-aes@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.1.tgz#06e530907fe2949dc21fc3c2e2302e10b1437238" - integrity sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ== - dependencies: - bn.js "^5.2.1" - randombytes "^2.1.0" - safe-buffer "^5.2.1" - -browserify-sign@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" - integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== - dependencies: - bn.js "^5.2.1" - browserify-rsa "^4.1.0" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.5" - hash-base "~3.0" - inherits "^2.0.4" - parse-asn1 "^5.1.7" - readable-stream "^2.3.8" - safe-buffer "^5.2.1" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== - dependencies: - base-x "^3.0.2" - -bs58@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" - integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== - dependencies: - base-x "^4.0.0" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - -buffer-reverse@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-reverse/-/buffer-reverse-1.0.1.tgz#49283c8efa6f901bc01fa3304d06027971ae2f60" - integrity sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -buffer@4.9.2, buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - -bufferutil@^4.0.1: - version "4.0.8" - resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" - integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== - dependencies: - node-gyp-build "^4.3.0" - -bufio@^1.0.7: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.2.tgz#60a1b21e176cc9d432d4a6c52a01312e735d1753" - integrity sha512-sTsA0ka7sjge/bGUfjk00O/8kNfyeAvJjXXeyvgbXefIrf5GTp99W71qfmCP6FGHWbr4A0IjjM7dFj6bHXVMlw== - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== - -bullmq@^5.11.0: - version "5.34.0" - resolved "https://registry.yarnpkg.com/bullmq/-/bullmq-5.34.0.tgz#66252d9931ac973fe2d028d57564ea7a5157b2be" - integrity sha512-TyzeYDkIGkooYUn/P1CeiJW3Am1TboC3unwhlg1cJIwKksoyuRp97TkHyCZcwLchXbYCUtsGBZFUYf/lTAhdSg== - dependencies: - cron-parser "^4.6.0" - ioredis "^5.4.1" - msgpackr "^1.11.2" - node-abort-controller "^3.1.1" - semver "^7.5.4" - tslib "^2.0.0" - uuid "^9.0.0" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -cac@^6.7.14: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - -call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" - integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.7, call-bind@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" - integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== - dependencies: - call-bind-apply-helpers "^1.0.0" - es-define-property "^1.0.0" - get-intrinsic "^1.2.4" - set-function-length "^1.2.2" - -call-bound@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.2.tgz#9dbd4daf9f5f753bec3e4c8fbb8a2ecc4de6c39b" - integrity sha512-0lk0PHFe/uz0vl527fG9CgdE9WdafjDbCXvBbs+LUv000TVt2Jjhqbs4Jwm8gz070w8xXyEAxrPOMullsxXeGg== - dependencies: - call-bind "^1.0.8" - get-intrinsic "^1.2.5" - -call-me-maybe@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" - integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ== - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -catharsis@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" - integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A== - dependencies: - lodash "^4.17.15" - -chai@^4.3.10, chai@^4.3.4: - version "4.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" - integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.3" - deep-eql "^4.1.3" - get-func-name "^2.0.2" - loupe "^2.3.6" - pathval "^1.1.1" - type-detect "^4.1.0" - -chai@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d" - integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw== - dependencies: - assertion-error "^2.0.1" - check-error "^2.1.1" - deep-eql "^5.0.1" - loupe "^3.1.0" - pathval "^2.0.0" - -chalk@^4.0.0, chalk@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -change-case@5.4.4: - version "5.4.4" - resolved "https://registry.yarnpkg.com/change-case/-/change-case-5.4.4.tgz#0d52b507d8fb8f204343432381d1a6d7bff97a02" - integrity sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w== - -check-error@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" - integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== - dependencies: - get-func-name "^2.0.2" - -check-error@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" - integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== - -chokidar@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" - integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chownr@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" - integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== - -cid-tool@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cid-tool/-/cid-tool-3.0.0.tgz#557540c5896d204503ef0ece848b88bbb350b90a" - integrity sha512-rgpV/LzuxUsGCJvUHe9+OuOAENVCiTn+mgGT8Nee1qDLS3xFGBUvZQdsY9MEpUi0YOFy6oz1pybHErcvE4SlGw== - dependencies: - cids "^1.0.0" - explain-error "^1.0.4" - multibase "^4.0.2" - multihashes "^4.0.2" - split2 "^3.1.1" - uint8arrays "^2.1.3" - yargs "^16.2.0" - -cids@^1.0.0: - version "1.1.9" - resolved "https://registry.yarnpkg.com/cids/-/cids-1.1.9.tgz#402c26db5c07059377bcd6fb82f2a24e7f2f4a4f" - integrity sha512-l11hWRfugIcbGuTZwAM5PwpjPPjyb6UZOGwlHSnOBV5o07XhQ4gNpBN67FbODvpjyHtd+0Xs6KNvUcGBiDRsdg== - dependencies: - multibase "^4.0.1" - multicodec "^3.0.1" - multihashes "^4.0.1" - uint8arrays "^3.0.0" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7" - integrity sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw== - dependencies: - inherits "^2.0.4" - safe-buffer "^5.2.1" - -citty@^0.1.5, citty@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.6.tgz#0f7904da1ed4625e1a9ea7e0fa780981aab7c5e4" - integrity sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ== - dependencies: - consola "^3.2.3" - -cjs-module-lexer@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" - integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== - -clipboardy@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1" - integrity sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w== - dependencies: - execa "^8.0.1" - is-wsl "^3.1.0" - is64bit "^2.0.0" - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clsx@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - -cluster-key-slot@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" - integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== - -color-convert@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.6.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" - integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.1.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" - integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== - dependencies: - color-convert "^1.9.3" - color-string "^1.6.0" - -colorette@2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== - -colorspace@1.1.x: - version "1.1.4" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" - integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== - dependencies: - color "^3.1.3" - text-hex "1.0.x" - -combined-stream@^1.0.6, combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -commander@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" - integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -confbox@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" - integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== - -consola@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" - integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== - -content-disposition@^0.5.3: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -convert-source-map@^1.5.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" - integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== - -cookie-es@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.2.2.tgz#18ceef9eb513cac1cb6c14bcbf8bdb2679b34821" - integrity sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg== - -cookie-signature@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" - integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== - -cookie@>=0.7.0, cookie@^0.6.0, cookie@^0.7.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610" - integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA== - -cookiejar@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - -copy-anything@^3.0.2: - version "3.0.5" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0" - integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== - dependencies: - is-what "^4.1.8" - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cosmiconfig@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" - integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -create-ecdh@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cron-parser@^4.6.0, cron-parser@^4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.9.0.tgz#0340694af3e46a0894978c6f52a6dbb5c0f11ad5" - integrity sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q== - dependencies: - luxon "^3.2.1" - -cross-fetch@^3.1.4: - version "3.1.8" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" - integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== - dependencies: - node-fetch "^2.6.12" - -cross-fetch@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" - integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== - dependencies: - node-fetch "^2.6.12" - -cross-spawn@7.0.6, cross-spawn@>=7.0.6, cross-spawn@^7.0.0, cross-spawn@^7.0.3: - version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" - integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -"crossws@>=0.2.0 <0.4.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/crossws/-/crossws-0.3.1.tgz#7980e0b6688fe23286661c3ab8deeccbaa05ca86" - integrity sha512-HsZgeVYaG+b5zA+9PbIPGq4+J/CJynJuearykPsXx4V/eMhyQ5EDVg3Ak2FBZtVXCiOLu/U7IiwDHTr9MA+IKw== - dependencies: - uncrypto "^0.1.3" - -crypto-browserify@^3.11.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.1.tgz#bb8921bec9acc81633379aa8f52d69b0b69e0dac" - integrity sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ== - dependencies: - browserify-cipher "^1.0.1" - browserify-sign "^4.2.3" - create-ecdh "^4.0.4" - create-hash "^1.2.0" - create-hmac "^1.1.7" - diffie-hellman "^5.0.3" - hash-base "~3.0.4" - inherits "^2.0.4" - pbkdf2 "^3.1.2" - public-encrypt "^4.0.3" - randombytes "^2.1.0" - randomfill "^1.0.4" - -crypto-js@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" - integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== - -crypto-randomuuid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-randomuuid/-/crypto-randomuuid-1.0.0.tgz#acf583e5e085e867ae23e107ff70279024f9e9e7" - integrity sha512-/RC5F4l1SCqD/jazwUF6+t34Cd8zTSAGZ7rvvZu1whZUhD2a5MOGKjSGowoGcpj/cbVZk1ZODIooJEQQq3nNAA== - -crypto@1.0.1, crypto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" - integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -d@1, d@^1.0.1, d@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" - integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== - dependencies: - es5-ext "^0.10.64" - type "^2.7.2" - -dc-polyfill@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" - integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== - -dd-trace@^5.23.0: - version "5.28.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.28.0.tgz#70d10d9b6372fe7f54d539026a53f8a1b10ea8d3" - integrity sha512-jyF7JLx2Yw16MHcD97sYKXbVd7ZT1hKJ5/NkRRGeG9cgen5+d/ilIvfzgh2qRjeow+9a5ligoZoUOYJ3nYn9hw== - dependencies: - "@datadog/libdatadog" "^0.2.2" - "@datadog/native-appsec" "8.3.0" - "@datadog/native-iast-rewriter" "2.5.0" - "@datadog/native-iast-taint-tracking" "3.2.0" - "@datadog/native-metrics" "^3.0.1" - "@datadog/pprof" "5.4.1" - "@datadog/sketches-js" "^2.1.0" - "@isaacs/ttlcache" "^1.4.1" - "@opentelemetry/api" ">=1.0.0 <1.9.0" - "@opentelemetry/core" "^1.14.0" - crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.4" - ignore "^5.2.4" - import-in-the-middle "1.11.2" - int64-buffer "^0.1.9" - istanbul-lib-coverage "3.2.0" - jest-docblock "^29.7.0" - koalas "^1.0.2" - limiter "1.1.5" - lodash.sortby "^4.7.0" - lru-cache "^7.14.0" - module-details-from-path "^1.0.3" - msgpack-lite "^0.1.26" - opentracing ">=0.12.1" - path-to-regexp "^0.1.10" - pprof-format "^2.1.0" - protobufjs "^7.2.5" - retry "^0.13.1" - rfdc "^1.3.1" - semver "^7.5.4" - shell-quote "^1.8.1" - tlhunter-sorted-set "^0.1.0" - -debug@2.6.9, debug@^2.2.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.3.7: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - -debug@4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -decode-uri-component@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== - -deep-eql@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" - integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== - dependencies: - type-detect "^4.0.0" - -deep-eql@^5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" - integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== - -deep-is@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -defu@^6.1.4: - version "6.1.4" - resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" - integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== - -delay@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" - integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -denque@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" - integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -des.js@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" - integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destr@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.3.tgz#7f9e97cb3d16dbdca7be52aca1644ce402cfe449" - integrity sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-browser@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" - integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== - -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== - -detect-libc@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" - integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -detect-node-es@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" - integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== - -diffie-hellman@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dijkstrajs@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" - integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -dotenv@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - -dotenv@^16.0.3: - version "16.4.7" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" - integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== - -dunder-proto@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.0.tgz#c2fce098b3c8f8899554905f4377b6d85dabaa80" - integrity sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A== - dependencies: - call-bind-apply-helpers "^1.0.0" - es-errors "^1.3.0" - gopd "^1.2.0" - -duplexify@^4.0.0, duplexify@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" - integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== - dependencies: - end-of-stream "^1.4.1" - inherits "^2.0.3" - readable-stream "^3.1.1" - stream-shift "^1.0.2" - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -eip1193-provider@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/eip1193-provider/-/eip1193-provider-1.0.1.tgz#420d29cf4f6c443e3f32e718fb16fafb250637c3" - integrity sha512-kSuqwQ26d7CzuS/t3yRXo2Su2cVH0QfvyKbr2H7Be7O5YDyIq4hQGCNTo5wRdP07bt+E2R/8nPCzey4ojBHf7g== - dependencies: - "@json-rpc-tools/provider" "^1.5.5" - -ejs@^3.1.10: - version "3.1.10" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" - integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== - dependencies: - jake "^10.8.5" - -elliptic@6.5.4, elliptic@6.5.7, elliptic@6.6.0, elliptic@6.6.1, elliptic@>=6.6.0, elliptic@^6.4.1, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.5, elliptic@^6.5.7: - version "6.6.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" - integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -enabled@2.0.x: - version "2.0.0" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" - integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== - -encode-utf8@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - -end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -entities@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - -erc721a-upgradeable@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/erc721a-upgradeable/-/erc721a-upgradeable-3.3.0.tgz#c7b481668694756120868261fe98ab3a245a06b4" - integrity sha512-ILE0SjKuvhx+PABG0A/41QUp0MFiYmzrgo71htQ0Ov6JfDOmgUzGxDW8gZuYfKrdlYjNwSAqMpUFWBbyW3sWBA== - dependencies: - "@openzeppelin/contracts-upgradeable" "^4.4.2" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-define-property@^1.0.0, es-define-property@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" - integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-module-lexer@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" - integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== - -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es5-ext@^0.10.35, es5-ext@^0.10.62, es5-ext@^0.10.63, es5-ext@^0.10.64, es5-ext@~0.10.14: - version "0.10.64" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" - integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== - dependencies: - es6-iterator "^2.0.3" - es6-symbol "^3.1.3" - esniff "^2.0.1" - next-tick "^1.1.0" - -es6-iterator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-promise@^4.2.8: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-symbol@^3.1.1, es6-symbol@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" - integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== - dependencies: - d "^1.0.2" - ext "^1.7.0" - -esbuild@^0.21.3: - version "0.21.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== - optionalDependencies: - "@esbuild/aix-ppc64" "0.21.5" - "@esbuild/android-arm" "0.21.5" - "@esbuild/android-arm64" "0.21.5" - "@esbuild/android-x64" "0.21.5" - "@esbuild/darwin-arm64" "0.21.5" - "@esbuild/darwin-x64" "0.21.5" - "@esbuild/freebsd-arm64" "0.21.5" - "@esbuild/freebsd-x64" "0.21.5" - "@esbuild/linux-arm" "0.21.5" - "@esbuild/linux-arm64" "0.21.5" - "@esbuild/linux-ia32" "0.21.5" - "@esbuild/linux-loong64" "0.21.5" - "@esbuild/linux-mips64el" "0.21.5" - "@esbuild/linux-ppc64" "0.21.5" - "@esbuild/linux-riscv64" "0.21.5" - "@esbuild/linux-s390x" "0.21.5" - "@esbuild/linux-x64" "0.21.5" - "@esbuild/netbsd-x64" "0.21.5" - "@esbuild/openbsd-x64" "0.21.5" - "@esbuild/sunos-x64" "0.21.5" - "@esbuild/win32-arm64" "0.21.5" - "@esbuild/win32-ia32" "0.21.5" - "@esbuild/win32-x64" "0.21.5" - -escalade@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -escodegen@^1.13.0: - version "1.14.3" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" - integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== - dependencies: - esprima "^4.0.1" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-visitor-keys@^3.4.1: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -esm@^3.2.25: - version "3.2.25" - resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" - integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== - -esniff@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" - integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== - dependencies: - d "^1.0.1" - es5-ext "^0.10.62" - event-emitter "^0.3.5" - type "^2.7.2" - -espree@^9.0.0: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -estree-walker@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" - integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== - dependencies: - "@types/estree" "^1.0.0" - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -eth-block-tracker@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-7.1.0.tgz#dfc16085c6817cc30caabba381deb8d204c1c766" - integrity sha512-8YdplnuE1IK4xfqpf4iU7oBxnOYAc35934o083G8ao+8WM8QQtt/mVlAY6yIAdY1eMeLqg4Z//PZjJGmWGPMRg== - dependencies: - "@metamask/eth-json-rpc-provider" "^1.0.0" - "@metamask/safe-event-emitter" "^3.0.0" - "@metamask/utils" "^5.0.1" - json-rpc-random-id "^1.0.1" - pify "^3.0.0" - -eth-json-rpc-filters@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-6.0.1.tgz#0b3e370f017f5c6f58d3e7bd0756d8099ed85c56" - integrity sha512-ITJTvqoCw6OVMLs7pI8f4gG92n/St6x80ACtHodeS+IXmO0w+t1T5OOzfSt7KLSMLRkVUoexV7tztLgDxg+iig== - dependencies: - "@metamask/safe-event-emitter" "^3.0.0" - async-mutex "^0.2.6" - eth-query "^2.1.2" - json-rpc-engine "^6.1.0" - pify "^5.0.0" - -eth-provider@^0.13.6: - version "0.13.7" - resolved "https://registry.yarnpkg.com/eth-provider/-/eth-provider-0.13.7.tgz#f7bec9c255724f54792a6c9a6e3a30e70c4fefe6" - integrity sha512-D07HcKBQ0+liERDbkwpex03Y5D7agOMBv8NMkGu0obmD+vHzP9q8jI/tkZMfYAhbfXwpudEgXKiJODXH5UQu7g== - dependencies: - ethereum-provider "0.7.7" - events "3.3.0" - oboe "2.1.5" - uuid "9.0.0" - ws "8.9.0" - xhr2-cookies "1.1.0" - -eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-rpc-errors@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz#6ddb6190a4bf360afda82790bb7d9d5e724f423a" - integrity sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg== - dependencies: - fast-safe-stringify "^2.0.6" - -ethereum-cryptography@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" - integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== - dependencies: - "@types/pbkdf2" "^3.0.0" - "@types/secp256k1" "^4.0.1" - blakejs "^1.1.0" - browserify-aes "^1.2.0" - bs58check "^2.1.2" - create-hash "^1.2.0" - create-hmac "^1.1.7" - hash.js "^1.1.7" - keccak "^3.0.0" - pbkdf2 "^3.0.17" - randombytes "^2.1.0" - safe-buffer "^5.1.2" - scrypt-js "^3.0.0" - secp256k1 "^4.0.1" - setimmediate "^1.0.5" - -ethereum-cryptography@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" - integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== - dependencies: - "@noble/curves" "1.4.2" - "@noble/hashes" "1.4.0" - "@scure/bip32" "1.4.0" - "@scure/bip39" "1.3.0" - -ethereum-provider@0.7.7: - version "0.7.7" - resolved "https://registry.yarnpkg.com/ethereum-provider/-/ethereum-provider-0.7.7.tgz#c67c69aa9ced8f728dacc2b4c00ad4a8bf329319" - integrity sha512-ulbjKgu1p2IqtZqNTNfzXysvFJrMR3oTmWEEX3DnoEae7WLd4MkY4u82kvXhxA2C171rK8IVlcodENX7TXvHTA== - dependencies: - events "3.3.0" - -ethereumjs-abi@^0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" - integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-util@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" - integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" - -ethereumjs-util@^7.1.5: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - -ethers-aws-kms-signer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/ethers-aws-kms-signer/-/ethers-aws-kms-signer-1.3.2.tgz#af4e3686f79feff82cca94cf39279fd4c45f7fbc" - integrity sha512-A/xsjCtUGXybpo7imThn4wWcOazHKQi9wnfs9ArPrgp4TmD7dH0bw0FsX71rr9QWsP6RCj0FAGsAxCKNWgEP/g== - dependencies: - asn1.js "^5.4.1" - aws-sdk "^2.922.0" - bn.js "^5.2.0" - debug "^4.3.1" - ethers "^5.4.1" - -ethers-gcp-kms-signer@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/ethers-gcp-kms-signer/-/ethers-gcp-kms-signer-1.1.6.tgz#7510f390d491dc5507b42a54a6d7362b3074f30b" - integrity sha512-mxnDcNM2lgd1IhcbVAQsATYDhJkyK5XbB0Pba3E+9ODNApzwmMzRf8fV58nl95IeRteDY3NTms/6QOapPp4hoQ== - dependencies: - "@google-cloud/kms" "3.0.1" - "@metamask/eth-sig-util" "4.0.0" - asn1.js "5.4.1" - bn.js "5.2.0" - crypto "1.0.1" - dotenv "^10.0.0" - ethereumjs-util "7.1.3" - ethers "5.5.1" - key-encoder "2.0.3" - -ethers@5, ethers@5.7.2, ethers@^5.4.1, ethers@^5.7.2: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -ethers@5.5.1: - version "5.5.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.1.tgz#d3259a95a42557844aa543906c537106c0406fbf" - integrity sha512-RodEvUFZI+EmFcE6bwkuJqpCYHazdzeR1nMzg+YWQSmQEsNtfl1KHGfp/FWZYl48bI/g7cgBeP2IlPthjiVngw== - dependencies: - "@ethersproject/abi" "5.5.0" - "@ethersproject/abstract-provider" "5.5.1" - "@ethersproject/abstract-signer" "5.5.0" - "@ethersproject/address" "5.5.0" - "@ethersproject/base64" "5.5.0" - "@ethersproject/basex" "5.5.0" - "@ethersproject/bignumber" "5.5.0" - "@ethersproject/bytes" "5.5.0" - "@ethersproject/constants" "5.5.0" - "@ethersproject/contracts" "5.5.0" - "@ethersproject/hash" "5.5.0" - "@ethersproject/hdnode" "5.5.0" - "@ethersproject/json-wallets" "5.5.0" - "@ethersproject/keccak256" "5.5.0" - "@ethersproject/logger" "5.5.0" - "@ethersproject/networks" "5.5.0" - "@ethersproject/pbkdf2" "5.5.0" - "@ethersproject/properties" "5.5.0" - "@ethersproject/providers" "5.5.0" - "@ethersproject/random" "5.5.0" - "@ethersproject/rlp" "5.5.0" - "@ethersproject/sha2" "5.5.0" - "@ethersproject/signing-key" "5.5.0" - "@ethersproject/solidity" "5.5.0" - "@ethersproject/strings" "5.5.0" - "@ethersproject/transactions" "5.5.0" - "@ethersproject/units" "5.5.0" - "@ethersproject/wallet" "5.5.0" - "@ethersproject/web" "5.5.0" - "@ethersproject/wordlists" "5.5.0" - -ethjs-util@0.1.6, ethjs-util@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -event-emitter@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== - dependencies: - d "1" - es5-ext "~0.10.14" - -event-lite@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/event-lite/-/event-lite-0.1.3.tgz#3dfe01144e808ac46448f0c19b4ab68e403a901d" - integrity sha512-8qz9nOz5VeD2z96elrEKD2U433+L3DWdUdDkOINLGOJvx1GsMBbMn0aCeu28y8/e85A6mCigBiFlYMnTBEGlSw== - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -eventemitter3@5.0.1, eventemitter3@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" - integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== - -eventemitter3@^4.0.0, eventemitter3@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== - -events@3.3.0, events@^3.0.0, events@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -execa@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" - integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^8.0.1" - human-signals "^5.0.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^4.1.0" - strip-final-newline "^3.0.0" - -execa@^9.1.0: - version "9.5.2" - resolved "https://registry.yarnpkg.com/execa/-/execa-9.5.2.tgz#a4551034ee0795e241025d2f987dab3f4242dff2" - integrity sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q== - dependencies: - "@sindresorhus/merge-streams" "^4.0.0" - cross-spawn "^7.0.3" - figures "^6.1.0" - get-stream "^9.0.0" - human-signals "^8.0.0" - is-plain-obj "^4.1.0" - is-stream "^4.0.1" - npm-run-path "^6.0.0" - pretty-ms "^9.0.0" - signal-exit "^4.1.0" - strip-final-newline "^4.0.0" - yoctocolors "^2.0.0" - -expect-type@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" - integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA== - -explain-error@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/explain-error/-/explain-error-1.0.4.tgz#a793d3ac0cad4c6ab571e9968fbbab6cb2532929" - integrity sha512-/wSgNMxFusiYRy1rd19LT2SQlIXDppHpumpWo06wxjflD1OYxDLbl6rMVw+U3bxD5Nuhex4TKqv9Aem4D0lVzQ== - -ext@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" - integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== - dependencies: - type "^2.7.2" - -extend@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -fast-content-type-parse@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz#4087162bf5af3294d4726ff29b334f72e3a1092c" - integrity sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ== - -fast-decode-uri-component@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" - integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== - -fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stringify@^5.7.0, fast-json-stringify@^5.8.0: - version "5.16.1" - resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz#a6d0c575231a3a08c376a00171d757372f2ca46e" - integrity sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g== - dependencies: - "@fastify/merge-json-schemas" "^0.1.0" - ajv "^8.10.0" - ajv-formats "^3.0.1" - fast-deep-equal "^3.1.3" - fast-uri "^2.1.0" - json-schema-ref-resolver "^1.0.1" - rfdc "^1.2.0" - -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fast-querystring@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53" - integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg== - dependencies: - fast-decode-uri-component "^1.0.1" - -fast-redact@^3.0.0, fast-redact@^3.1.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" - integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== - -fast-safe-stringify@^2.0.6: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - -fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3, fast-text-encoding@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" - integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== - -fast-uri@^2.0.0, fast-uri@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.4.0.tgz#67eae6fbbe9f25339d5d3f4c4234787b65d7d55e" - integrity sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA== - -fast-uri@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" - integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== - -fast-xml-parser@4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" - integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== - dependencies: - strnum "^1.0.5" - -fastify-plugin@^4.0.0, fastify-plugin@^4.5.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-4.5.1.tgz#44dc6a3cc2cce0988bc09e13f160120bbd91dbee" - integrity sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ== - -fastify-type-provider-zod@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fastify-type-provider-zod/-/fastify-type-provider-zod-1.2.0.tgz#a1843938ea6e739b86aaeee762728c9891a3c68a" - integrity sha512-2zkPEWFIBYzkGQ0kmn8gOW5tlQOmdDWn5edF5LQ2r0RiydFGhD86FVZX6wLraXAmdFm8P1CMmo19lwlGb0mZrA== - dependencies: - zod-to-json-schema "^3.23.0" - -fastify@^4.28.1: - version "4.29.0" - resolved "https://registry.yarnpkg.com/fastify/-/fastify-4.29.0.tgz#ea3fcd92f4d9deaa841a6722dc6e3e7ff9392850" - integrity sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ== - dependencies: - "@fastify/ajv-compiler" "^3.5.0" - "@fastify/error" "^3.4.0" - "@fastify/fast-json-stringify-compiler" "^4.3.0" - abstract-logging "^2.0.1" - avvio "^8.3.0" - fast-content-type-parse "^1.1.0" - fast-json-stringify "^5.8.0" - find-my-way "^8.0.0" - light-my-request "^5.11.0" - pino "^9.0.0" - process-warning "^3.0.0" - proxy-addr "^2.0.7" - rfdc "^1.3.0" - secure-json-parse "^2.7.0" - semver "^7.5.4" - toad-cache "^3.3.0" - -fastq@^1.17.1: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -fecha@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" - integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== - -figures@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-6.1.0.tgz#935479f51865fa7479f6fa94fc6fc7ac14e62c4a" - integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== - dependencies: - is-unicode-supported "^2.0.0" - -filelist@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" - integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== - dependencies: - minimatch "^5.0.1" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -filter-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== - -find-my-way@^8.0.0: - version "8.2.2" - resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-8.2.2.tgz#f3e78bc6ead2da4fdaa201335da3228600ed0285" - integrity sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA== - dependencies: - fast-deep-equal "^3.1.3" - fast-querystring "^1.0.0" - safe-regex2 "^3.1.0" - -find-root@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -fn.name@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" - integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== - -follow-redirects@^1.0.0, follow-redirects@^1.15.6: - version "1.15.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" - integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" - integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -form-data@^2.5.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.2.tgz#dc653743d1de2fcc340ceea38079daf6e9069fd2" - integrity sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - safe-buffer "^5.2.1" - -form-data@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" - integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fs-extra@^11.1.1: - version "11.2.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@2.3.3, fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -fuse.js@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-7.0.0.tgz#6573c9fcd4c8268e403b4fc7d7131ffcf99a9eb2" - integrity sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q== - -gaxios@^5.0.0, gaxios@^5.0.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-5.1.3.tgz#f7fa92da0fe197c846441e5ead2573d4979e9013" - integrity sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA== - dependencies: - extend "^3.0.2" - https-proxy-agent "^5.0.0" - is-stream "^2.0.0" - node-fetch "^2.6.9" - -gaxios@^6.0.0, gaxios@^6.1.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.7.1.tgz#ebd9f7093ede3ba502685e73390248bb5b7f71fb" - integrity sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ== - dependencies: - extend "^3.0.2" - https-proxy-agent "^7.0.1" - is-stream "^2.0.0" - node-fetch "^2.6.9" - uuid "^9.0.1" - -gcp-metadata@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-5.3.0.tgz#6f45eb473d0cb47d15001476b48b663744d25408" - integrity sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w== - dependencies: - gaxios "^5.0.0" - json-bigint "^1.0.0" - -gcp-metadata@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.0.tgz#9b0dd2b2445258e7597f2024332d20611cbd6b8c" - integrity sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg== - dependencies: - gaxios "^6.0.0" - json-bigint "^1.0.0" - -get-caller-file@^2.0.1, get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.1, get-func-name@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" - integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== - -get-intrinsic@^1.2.4, get-intrinsic@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz#43dd3dd0e7b49b82b2dfcad10dc824bf7fc265d5" - integrity sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA== - dependencies: - call-bind-apply-helpers "^1.0.1" - dunder-proto "^1.0.0" - es-define-property "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - function-bind "^1.1.2" - gopd "^1.2.0" - has-symbols "^1.1.0" - hasown "^2.0.2" - math-intrinsics "^1.0.0" - -get-nonce@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" - integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-port-please@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.2.tgz#502795e56217128e4183025c89a48c71652f4e49" - integrity sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ== - -get-port@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-7.1.0.tgz#d5a500ebfc7aa705294ec2b83cc38c5d0e364fec" - integrity sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw== - -get-stream@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" - integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== - -get-stream@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-9.0.1.tgz#95157d21df8eb90d1647102b63039b1df60ebd27" - integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== - dependencies: - "@sec-ant/readable-stream" "^0.4.1" - is-stream "^4.0.1" - -getopts@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4" - integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA== - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^10.3.7, glob@^10.4.1: - version "10.4.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - -glob@^8.0.0, glob@^8.0.1: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -google-auth-library@^8.0.2: - version "8.9.0" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-8.9.0.tgz#15a271eb2ec35d43b81deb72211bd61b1ef14dd0" - integrity sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg== - dependencies: - arrify "^2.0.0" - base64-js "^1.3.0" - ecdsa-sig-formatter "^1.0.11" - fast-text-encoding "^1.0.0" - gaxios "^5.0.0" - gcp-metadata "^5.3.0" - gtoken "^6.1.0" - jws "^4.0.0" - lru-cache "^6.0.0" - -google-auth-library@^9.3.0: - version "9.15.0" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.15.0.tgz#1b009c08557929c881d72f953f17e839e91b009b" - integrity sha512-7ccSEJFDFO7exFbO6NRyC+xH8/mZ1GZGG2xxx9iHxZWcjUjJpjWxIMw3cofAKcueZ6DATiukmmprD7yavQHOyQ== - dependencies: - base64-js "^1.3.0" - ecdsa-sig-formatter "^1.0.11" - gaxios "^6.1.1" - gcp-metadata "^6.1.0" - gtoken "^7.0.0" - jws "^4.0.0" - -google-gax@^3.0.1, google-gax@^3.5.8: - version "3.6.1" - resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-3.6.1.tgz#02c78fc496f5adf86f2ca9145545f4b6575f6118" - integrity sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w== - dependencies: - "@grpc/grpc-js" "~1.8.0" - "@grpc/proto-loader" "^0.7.0" - "@types/long" "^4.0.0" - "@types/rimraf" "^3.0.2" - abort-controller "^3.0.0" - duplexify "^4.0.0" - fast-text-encoding "^1.0.3" - google-auth-library "^8.0.2" - is-stream-ended "^0.1.4" - node-fetch "^2.6.1" - object-hash "^3.0.0" - proto3-json-serializer "^1.0.0" - protobufjs "7.2.4" - protobufjs-cli "1.1.1" - retry-request "^5.0.0" - -google-gax@^4.0.3: - version "4.4.1" - resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-4.4.1.tgz#95a9cf7ee7777ac22d1926a45b5f886dd8beecae" - integrity sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg== - dependencies: - "@grpc/grpc-js" "^1.10.9" - "@grpc/proto-loader" "^0.7.13" - "@types/long" "^4.0.0" - abort-controller "^3.0.0" - duplexify "^4.0.0" - google-auth-library "^9.3.0" - node-fetch "^2.7.0" - object-hash "^3.0.0" - proto3-json-serializer "^2.0.2" - protobufjs "^7.3.2" - retry-request "^7.0.0" - uuid "^9.0.1" - -google-p12-pem@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a" - integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ== - dependencies: - node-forge "^1.3.1" - -gopd@^1.0.1, gopd@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" - integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== - -graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -gtoken@^6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" - integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ== - dependencies: - gaxios "^5.0.1" - google-p12-pem "^4.0.0" - jws "^4.0.0" - -gtoken@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.1.0.tgz#d61b4ebd10132222817f7222b1e6064bd463fc26" - integrity sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw== - dependencies: - gaxios "^6.0.0" - jws "^4.0.0" - -h3@^1.12.0, h3@^1.13.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/h3/-/h3-1.13.0.tgz#b5347a8936529794b6754b440e26c0ab8a60dceb" - integrity sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg== - dependencies: - cookie-es "^1.2.2" - crossws ">=0.2.0 <0.4.0" - defu "^6.1.4" - destr "^2.0.3" - iron-webcrypto "^1.2.1" - ohash "^1.1.4" - radix3 "^1.1.2" - ufo "^1.5.4" - uncrypto "^0.1.3" - unenv "^1.10.0" - -handlebars@^4.7.7: - version "4.7.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" - integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.2" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-symbols@^1.0.3, has-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" - integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash-base@~3.0, hash-base@~3.0.4: - version "3.0.5" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" - integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== - dependencies: - inherits "^2.0.4" - safe-buffer "^5.2.1" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hashlru@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/hashlru/-/hashlru-2.3.0.tgz#5dc15928b3f6961a2056416bb3a4910216fdfb51" - integrity sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A== - -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -hey-listen@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" - integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hoist-non-react-statics@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg== - -http-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" - integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== - dependencies: - "@tootallnate/once" "2" - agent-base "6" - debug "4" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http-shutdown@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" - integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== - -http-status-codes@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.3.0.tgz#987fefb28c69f92a43aecc77feec2866349a8bfc" - integrity sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA== - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== - -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - -https-proxy-agent@^7.0.1: - version "7.0.6" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" - integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== - dependencies: - agent-base "^7.1.2" - debug "4" - -human-signals@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" - integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== - -human-signals@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-8.0.0.tgz#2d3d63481c7c2319f0373428b01ffe30da6df852" - integrity sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -idb-keyval@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" - integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== - -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ieee754@^1.1.4, ieee754@^1.1.8, ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.4: - version "5.3.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" - integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== - -immediate@~3.0.5: - version "3.0.6" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" - integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-in-the-middle@1.11.2: - version "1.11.2" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" - integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== - dependencies: - acorn "^8.8.2" - acorn-import-attributes "^1.9.5" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -input-otp@^1.2.4, input-otp@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/input-otp/-/input-otp-1.4.1.tgz#bc22e68b14b1667219d54adf74243e37ea79cf84" - integrity sha512-+yvpmKYKHi9jIGngxagY9oWiiblPB7+nEO75F2l2o4vs+6vpPZZmUl4tBNYuTCvQjhvEIbdNeJu70bhfYP2nbw== - -int64-buffer@^0.1.9: - version "0.1.10" - resolved "https://registry.yarnpkg.com/int64-buffer/-/int64-buffer-0.1.10.tgz#277b228a87d95ad777d07c13832022406a473423" - integrity sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA== - -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -ioredis@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.4.1.tgz#1c56b70b759f01465913887375ed809134296f40" - integrity sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA== - dependencies: - "@ioredis/commands" "^1.1.1" - cluster-key-slot "^1.1.0" - debug "^4.3.4" - denque "^2.1.0" - lodash.defaults "^4.2.0" - lodash.isarguments "^3.1.0" - redis-errors "^1.2.0" - redis-parser "^3.0.0" - standard-as-callback "^2.1.0" - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -iron-webcrypto@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz#aa60ff2aa10550630f4c0b11fd2442becdb35a6f" - integrity sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-callable@^1.1.3: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.13.0: - version "2.15.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" - integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== - dependencies: - hasown "^2.0.2" - -is-docker@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" - integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== - -is-inside-container@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" - integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== - dependencies: - is-docker "^3.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-stream-ended@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" - integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - -is-stream@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-4.0.1.tgz#375cf891e16d2e4baec250b85926cffc14720d9b" - integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== - -is-typed-array@^1.1.3: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - -is-unicode-supported@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz#09f0ab0de6d3744d48d265ebb98f65d11f2a9b3a" - integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== - -is-what@^4.1.8: - version "4.1.16" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f" - integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== - -is-wsl@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" - integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== - dependencies: - is-inside-container "^1.0.0" - -is64bit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is64bit/-/is64bit-2.0.0.tgz#198c627cbcb198bbec402251f88e5e1a51236c07" - integrity sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw== - dependencies: - system-architecture "^0.1.0" - -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isomorphic-unfetch@3.1.0, isomorphic-unfetch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" - integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== - dependencies: - node-fetch "^2.6.1" - unfetch "^4.2.0" - -isows@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" - integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== - -isows@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" - integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== - -istanbul-lib-coverage@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" - integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== - dependencies: - "@jridgewell/trace-mapping" "^0.3.23" - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - -istanbul-reports@^3.1.7: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jackspeak@^3.1.2: - version "3.4.3" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" - integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jake@^10.8.5: - version "10.9.2" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" - integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== - dependencies: - async "^3.2.3" - chalk "^4.0.2" - filelist "^1.0.4" - minimatch "^3.1.2" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jiti@^2.1.2: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.1.tgz#4de9766ccbfa941d9b6390d2b159a4b295a52e6b" - integrity sha512-yPBThwecp1wS9DmoA4x4KR2h3QoslacnDR8ypuFM962kI4/456Iy1oHx2RAgh4jfZNdn0bctsdadceiBUgpU1g== - -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - -js-sha3@0.8.0, js-sha3@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-sha3@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.9.3.tgz#f0209432b23a66a0f6c7af592c26802291a75c2a" - integrity sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -js2xmlparser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" - integrity sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA== - dependencies: - xmlcreate "^2.0.4" - -jsdoc@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-4.0.4.tgz#86565a9e39cc723a3640465b3fb189a22d1206ca" - integrity sha512-zeFezwyXeG4syyYHbvh1A967IAqq/67yXtXvuL5wnqCkFZe8I0vKfm+EO+YEvLguo6w9CDUbrAXVtJSHh2E8rw== - dependencies: - "@babel/parser" "^7.20.15" - "@jsdoc/salty" "^0.2.1" - "@types/markdown-it" "^14.1.1" - bluebird "^3.7.2" - catharsis "^0.9.0" - escape-string-regexp "^2.0.0" - js2xmlparser "^4.0.2" - klaw "^3.0.0" - markdown-it "^14.1.0" - markdown-it-anchor "^8.6.7" - marked "^4.0.10" - mkdirp "^1.0.4" - requizzle "^0.2.3" - strip-json-comments "^3.1.0" - underscore "~1.13.2" - -jsesc@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - -json-bigint@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" - integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== - dependencies: - bignumber.js "^9.0.0" - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-rpc-engine@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393" - integrity sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ== - dependencies: - "@metamask/safe-event-emitter" "^2.0.0" - eth-rpc-errors "^4.0.2" - -json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== - -json-schema-ref-parser@^9.0.9: - version "9.0.9" - resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#66ea538e7450b12af342fa3d5b8458bc1e1e013f" - integrity sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q== - dependencies: - "@apidevtools/json-schema-ref-parser" "9.0.9" - -json-schema-ref-resolver@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz#6586f483b76254784fc1d2120f717bdc9f0a99bf" - integrity sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw== - dependencies: - fast-deep-equal "^3.1.3" - -json-schema-resolver@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-schema-resolver/-/json-schema-resolver-2.0.0.tgz#d17fdf53560e6bc9af084b930fee27f6ce4a03b6" - integrity sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg== - dependencies: - debug "^4.1.1" - rfdc "^1.1.4" - uri-js "^4.2.2" - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonwebtoken@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" - integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^7.5.4" - -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jwa@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" - integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - -jws@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" - integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== - dependencies: - jwa "^2.0.0" - safe-buffer "^5.0.1" - -keccak@^3.0.0, keccak@^3.0.2, keccak@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" - integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - readable-stream "^3.6.0" - -key-encoder@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/key-encoder/-/key-encoder-2.0.3.tgz#77073bb48ff1fe2173bb2088b83b91152c8fa4ba" - integrity sha512-fgBtpAGIr/Fy5/+ZLQZIPPhsZEcbSlYu/Wu96tNDFNSjSACw5lEIOFeaVdQ/iwrb8oxjlWi6wmWdH76hV6GZjg== - dependencies: - "@types/elliptic" "^6.4.9" - asn1.js "^5.0.1" - bn.js "^4.11.8" - elliptic "^6.4.1" - -keyvaluestorage-interface@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" - integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== - -klaw@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" - integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== - dependencies: - graceful-fs "^4.1.9" - -knex@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/knex/-/knex-3.1.0.tgz#b6ddd5b5ad26a6315234a5b09ec38dc4a370bd8c" - integrity sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw== - dependencies: - colorette "2.0.19" - commander "^10.0.0" - debug "4.3.4" - escalade "^3.1.1" - esm "^3.2.25" - get-package-type "^0.1.0" - getopts "2.3.0" - interpret "^2.2.0" - lodash "^4.17.21" - pg-connection-string "2.6.2" - rechoir "^0.8.0" - resolve-from "^5.0.0" - tarn "^3.0.2" - tildify "2.0.0" - -koalas@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/koalas/-/koalas-1.0.2.tgz#318433f074235db78fae5661a02a8ca53ee295cd" - integrity sha512-RYhBbYaTTTHId3l6fnMZc3eGQNW6FVCqMG6AMwA5I1Mafr6AflaXeoi6x3xQuATRotGYRLk6+1ELZH4dstFNOA== - -kuler@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" - integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -lie@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" - integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw== - dependencies: - immediate "~3.0.5" - -light-my-request@^5.11.0: - version "5.14.0" - resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-5.14.0.tgz#11ddae56de4053fd5c1845cbfbee5c29e8a257e7" - integrity sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA== - dependencies: - cookie "^0.7.0" - process-warning "^3.0.0" - set-cookie-parser "^2.4.1" - -limiter@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" - integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -linkify-it@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" - integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== - dependencies: - uc.micro "^2.0.0" - -listhen@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.9.0.tgz#59355f7e4fc1eefda6bc494ae7e9ed13aa7658ef" - integrity sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg== - dependencies: - "@parcel/watcher" "^2.4.1" - "@parcel/watcher-wasm" "^2.4.1" - citty "^0.1.6" - clipboardy "^4.0.0" - consola "^3.2.3" - crossws ">=0.2.0 <0.4.0" - defu "^6.1.4" - get-port-please "^3.1.2" - h3 "^1.12.0" - http-shutdown "^1.2.2" - jiti "^2.1.2" - mlly "^1.7.1" - node-forge "^1.3.1" - pathe "^1.1.2" - std-env "^3.7.0" - ufo "^1.5.4" - untun "^0.1.3" - uqr "^0.1.2" - -lit-element@^3.3.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.3.3.tgz#10bc19702b96ef5416cf7a70177255bfb17b3209" - integrity sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA== - dependencies: - "@lit-labs/ssr-dom-shim" "^1.1.0" - "@lit/reactive-element" "^1.3.0" - lit-html "^2.8.0" - -lit-html@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.8.0.tgz#96456a4bb4ee717b9a7d2f94562a16509d39bffa" - integrity sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q== - dependencies: - "@types/trusted-types" "^2.0.2" - -lit@2.8.0, lit@^2.2.3: - version "2.8.0" - resolved "https://registry.yarnpkg.com/lit/-/lit-2.8.0.tgz#4d838ae03059bf9cafa06e5c61d8acc0081e974e" - integrity sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA== - dependencies: - "@lit/reactive-element" "^1.6.0" - lit-element "^3.3.0" - lit-html "^2.8.0" - -localforage@^1.7.4: - version "1.10.0" - resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" - integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== - dependencies: - lie "3.1.1" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.defaults@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - -lodash.isarguments@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - -lodash.isequal@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== - -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -logform@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" - integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== - dependencies: - "@colors/colors" "1.6.0" - "@types/triple-beam" "^1.3.2" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - -long@^5.0.0: - version "5.2.3" - resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" - integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -loupe@^2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" - integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== - dependencies: - get-func-name "^2.0.1" - -loupe@^3.1.0, loupe@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240" - integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg== - -lru-cache@^10.2.0, lru-cache@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lru-cache@^7.14.0: - version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" - integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== - -luxon@^3.2.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20" - integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ== - -magic-sdk@^13.6.2: - version "13.6.2" - resolved "https://registry.yarnpkg.com/magic-sdk/-/magic-sdk-13.6.2.tgz#68766fd9d1805332d2a00e5da1bd30fce251a6ac" - integrity sha512-ZjIZM2gqaxxOR+ZAyKVw50akjfdyo0q5hZzrCMiqyCqh4BXulU7yqHgUa/5/nJ+0/4xBgUejoOcDEm+UdmzLjA== - dependencies: - "@magic-sdk/commons" "^9.6.2" - "@magic-sdk/provider" "^13.6.2" - "@magic-sdk/types" "^11.6.2" - localforage "^1.7.4" - -magic-string@^0.30.12: - version "0.30.15" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.15.tgz#d5474a2c4c5f35f041349edaba8a5cb02733ed3c" - integrity sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - -magicast@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.5.tgz#8301c3c7d66704a0771eb1bad74274f0ec036739" - integrity sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ== - dependencies: - "@babel/parser" "^7.25.4" - "@babel/types" "^7.25.4" - source-map-js "^1.2.0" - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -markdown-it-anchor@^8.6.7: - version "8.6.7" - resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634" - integrity sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA== - -markdown-it@^14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" - integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== - dependencies: - argparse "^2.0.1" - entities "^4.4.0" - linkify-it "^5.0.0" - mdurl "^2.0.0" - punycode.js "^2.3.1" - uc.micro "^2.1.0" - -marked@^4.0.10: - version "4.3.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" - integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== - -math-intrinsics@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.0.0.tgz#4e04bf87c85aa51e90d078dac2252b4eb5260817" - integrity sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA== - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -mdurl@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" - integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merkletreejs@^0.3.11: - version "0.3.11" - resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.11.tgz#e0de05c3ca1fd368de05a12cb8efb954ef6fc04f" - integrity sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ== - dependencies: - bignumber.js "^9.0.1" - buffer-reverse "^1.0.1" - crypto-js "^4.2.0" - treeify "^1.1.0" - web3-utils "^1.3.4" - -micro-ftch@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" - integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== - -micromatch@>=4.0.8, micromatch@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@~2.1.24: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" - integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== - -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.0, minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -minizlib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.1.tgz#46d5329d1eb3c83924eff1d3b858ca0a31581012" - integrity sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg== - dependencies: - minipass "^7.0.4" - rimraf "^5.0.5" - -mipd@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mipd/-/mipd-0.0.7.tgz#bb5559e21fa18dc3d9fe1c08902ef14b7ce32fd9" - integrity sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg== - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -mkdirp@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" - integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== - -mlly@^1.7.1, mlly@^1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.3.tgz#d86c0fcd8ad8e16395eb764a5f4b831590cee48c" - integrity sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A== - dependencies: - acorn "^8.14.0" - pathe "^1.1.2" - pkg-types "^1.2.1" - ufo "^1.5.4" - -mnemonist@^0.39.8: - version "0.39.8" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.39.8.tgz#9078cd8386081afd986cca34b52b5d84ea7a4d38" - integrity sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ== - dependencies: - obliterator "^2.0.1" - -module-details-from-path@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" - integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== - -motion@10.16.2: - version "10.16.2" - resolved "https://registry.yarnpkg.com/motion/-/motion-10.16.2.tgz#7dc173c6ad62210a7e9916caeeaf22c51e598d21" - integrity sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ== - dependencies: - "@motionone/animation" "^10.15.1" - "@motionone/dom" "^10.16.2" - "@motionone/svelte" "^10.16.2" - "@motionone/types" "^10.15.1" - "@motionone/utils" "^10.15.1" - "@motionone/vue" "^10.16.2" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1, ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -msgpack-lite@^0.1.26: - version "0.1.26" - resolved "https://registry.yarnpkg.com/msgpack-lite/-/msgpack-lite-0.1.26.tgz#dd3c50b26f059f25e7edee3644418358e2a9ad89" - integrity sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw== - dependencies: - event-lite "^0.1.1" - ieee754 "^1.1.8" - int64-buffer "^0.1.9" - isarray "^1.0.0" - -msgpackr-extract@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz#e9d87023de39ce714872f9e9504e3c1996d61012" - integrity sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA== - dependencies: - node-gyp-build-optional-packages "5.2.2" - optionalDependencies: - "@msgpackr-extract/msgpackr-extract-darwin-arm64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-darwin-x64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-linux-arm" "3.0.3" - "@msgpackr-extract/msgpackr-extract-linux-arm64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.3" - -msgpackr@^1.11.2: - version "1.11.2" - resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.11.2.tgz#4463b7f7d68f2e24865c395664973562ad24473d" - integrity sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g== - optionalDependencies: - msgpackr-extract "^3.0.2" - -multibase@^4.0.1, multibase@^4.0.2: - version "4.0.6" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559" - integrity sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ== - dependencies: - "@multiformats/base-x" "^4.0.1" - -multicodec@^3.0.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-3.2.1.tgz#82de3254a0fb163a107c1aab324f2a91ef51efb2" - integrity sha512-+expTPftro8VAW8kfvcuNNNBgb9gPeNYV9dn+z1kJRWF2vih+/S79f2RVeIwmrJBUJ6NT9IUPWnZDQvegEh5pw== - dependencies: - uint8arrays "^3.0.0" - varint "^6.0.0" - -multiformats@^9.4.2: - version "9.9.0" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" - integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== - -multihashes@^4.0.1, multihashes@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" - integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== - dependencies: - multibase "^4.0.1" - uint8arrays "^3.0.0" - varint "^5.0.2" - -nanoid@^3.3.7: - version "3.3.8" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" - integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== - -napi-wasm@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.3.tgz#7bb95c88e6561f84880bb67195437b1cfbe99224" - integrity sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -next-tick@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" - integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== - -node-abort-controller@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" - integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== - -node-addon-api@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" - integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== - -node-addon-api@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" - integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== - -node-addon-api@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" - integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== - -node-addon-api@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" - integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== - -node-cron@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/node-cron/-/node-cron-3.0.3.tgz#c4bc7173dd96d96c50bdb51122c64415458caff2" - integrity sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A== - dependencies: - uuid "8.3.2" - -node-fetch-native@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e" - integrity sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ== - -node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - -node-gyp-build-optional-packages@5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz#522f50c2d53134d7f3a76cd7255de4ab6c96a3a4" - integrity sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw== - dependencies: - detect-libc "^2.0.1" - -node-gyp-build@<4.0, node-gyp-build@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.9.0.tgz#53a350187dd4d5276750da21605d1cb681d09e25" - integrity sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A== - -node-gyp-build@^4.2.0, node-gyp-build@^4.3.0, node-gyp-build@^4.5.0: - version "4.8.4" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" - integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== - -node-libs-browser@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== - dependencies: - path-key "^4.0.0" - -npm-run-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-6.0.0.tgz#25cfdc4eae04976f3349c0b1afc089052c362537" - integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== - dependencies: - path-key "^4.0.0" - unicorn-magic "^0.3.0" - -object-hash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" - integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== - -object-inspect@^1.13.3: - version "1.13.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" - integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -obliterator@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" - integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== - -oboe@2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" - integrity sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA== - dependencies: - http-https "^1.0.0" - -obuf@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -ofetch@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec" - integrity sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw== - dependencies: - destr "^2.0.3" - node-fetch-native "^1.6.4" - ufo "^1.5.4" - -ohash@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.4.tgz#ae8d83014ab81157d2c285abf7792e2995fadd72" - integrity sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g== - -on-exit-leak-free@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" - integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== - -on-exit-leak-free@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" - integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -one-time@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" - integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== - dependencies: - fn.name "1.x.x" - -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== - dependencies: - mimic-fn "^4.0.0" - -openapi-types@^12.0.0: - version "12.1.3" - resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" - integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== - -openapi-typescript-codegen@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/openapi-typescript-codegen/-/openapi-typescript-codegen-0.25.0.tgz#0cb028f54b33b0a63bd9da3756c1c41b4e1a70e2" - integrity sha512-nN/TnIcGbP58qYgwEEy5FrAAjePcYgfMaCe3tsmYyTgI3v4RR9v8os14L+LEWDvV50+CmqiyTzRkKKtJeb6Ybg== - dependencies: - camelcase "^6.3.0" - commander "^11.0.0" - fs-extra "^11.1.1" - handlebars "^4.7.7" - json-schema-ref-parser "^9.0.9" - -opentracing@>=0.12.1: - version "0.14.7" - resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.7.tgz#25d472bd0296dc0b64d7b94cbc995219031428f5" - integrity sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q== - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== - -ox@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ox/-/ox-0.1.2.tgz#0f791be2ccabeaf4928e6d423498fe1c8094e560" - integrity sha512-ak/8K0Rtphg9vnRJlbOdaX9R7cmxD2MiSthjWGaQdMk3D7hrAlDoM+6Lxn7hN52Za3vrXfZ7enfke/5WjolDww== - dependencies: - "@adraffy/ens-normalize" "^1.10.1" - "@noble/curves" "^1.6.0" - "@noble/hashes" "^1.5.0" - "@scure/bip32" "^1.5.0" - "@scure/bip39" "^1.4.0" - abitype "^1.0.6" - eventemitter3 "5.0.1" - -ox@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/ox/-/ox-0.4.2.tgz#0ef5b322baec0cbd055dfb27f22795f6af522594" - integrity sha512-X3Ho21mTtJiCU2rWmfaheh2b0CG70Adre7Da/XQ0ECy+QppI6pLqdbGAJHiu/cTjumVXfwDGfv48APqePCU+ow== - dependencies: - "@adraffy/ens-normalize" "^1.10.1" - "@noble/curves" "^1.6.0" - "@noble/hashes" "^1.5.0" - "@scure/bip32" "^1.5.0" - "@scure/bip39" "^1.4.0" - abitype "^1.0.6" - eventemitter3 "5.0.1" - -ox@^0.6.9: - version "0.6.9" - resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.9.tgz#da1ee04fa10de30c8d04c15bfb80fe58b1f554bd" - integrity sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug== - dependencies: - "@adraffy/ens-normalize" "^1.10.1" - "@noble/curves" "^1.6.0" - "@noble/hashes" "^1.5.0" - "@scure/bip32" "^1.5.0" - "@scure/bip39" "^1.4.0" - abitype "^1.0.6" - eventemitter3 "5.0.1" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json-from-dist@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" - integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" - integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== - dependencies: - asn1.js "^4.10.1" - browserify-aes "^1.2.0" - evp_bytestokey "^1.0.3" - hash-base "~3.0" - pbkdf2 "^3.1.2" - safe-buffer "^5.2.1" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-ms@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-4.0.0.tgz#c0c058edd47c2a590151a718990533fd62803df4" - integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-to-regexp@^0.1.10: - version "0.1.12" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" - integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pathe@^1.1.1, pathe@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" - integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== - -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== - -pathval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" - integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== - -pbkdf2@^3.0.17, pbkdf2@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -pg-cloudflare@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" - integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== - -pg-connection-string@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.2.tgz#713d82053de4e2bd166fab70cd4f26ad36aab475" - integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA== - -pg-connection-string@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37" - integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA== - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-numeric@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" - integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== - -pg-pool@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.7.0.tgz#d4d3c7ad640f8c6a2245adc369bafde4ebb8cbec" - integrity sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g== - -pg-protocol@*, pg-protocol@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.7.0.tgz#ec037c87c20515372692edac8b63cf4405448a93" - integrity sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ== - -pg-types@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg-types@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d" - integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== - dependencies: - pg-int8 "1.0.1" - pg-numeric "1.0.2" - postgres-array "~3.0.1" - postgres-bytea "~3.0.0" - postgres-date "~2.1.0" - postgres-interval "^3.0.0" - postgres-range "^1.1.1" - -pg@^8.11.3: - version "8.13.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.1.tgz#6498d8b0a87ff76c2df7a32160309d3168c0c080" - integrity sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ== - dependencies: - pg-connection-string "^2.7.0" - pg-pool "^3.7.0" - pg-protocol "^1.7.0" - pg-types "^2.1.0" - pgpass "1.x" - optionalDependencies: - pg-cloudflare "^1.1.1" - -pgpass@1.x: - version "1.0.5" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" - integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== - dependencies: - split2 "^4.1.0" - -picocolors@^1.0.0, picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== - -pify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" - integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== - -pino-abstract-transport@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz#de241578406ac7b8a33ce0d77ae6e8a0b3b68a60" - integrity sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw== - dependencies: - split2 "^4.0.0" - -pino-abstract-transport@v0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" - integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== - dependencies: - duplexify "^4.1.2" - split2 "^4.0.0" - -pino-std-serializers@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" - integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== - -pino-std-serializers@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" - integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== - -pino@7.11.0: - version "7.11.0" - resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6" - integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg== - dependencies: - atomic-sleep "^1.0.0" - fast-redact "^3.0.0" - on-exit-leak-free "^0.2.0" - pino-abstract-transport v0.5.0 - pino-std-serializers "^4.0.0" - process-warning "^1.0.0" - quick-format-unescaped "^4.0.3" - real-require "^0.1.0" - safe-stable-stringify "^2.1.0" - sonic-boom "^2.2.1" - thread-stream "^0.15.1" - -pino@^9.0.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/pino/-/pino-9.5.0.tgz#a7ef0fea868d22d52d8a4ce46e6e03c5dc46fdd6" - integrity sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw== - dependencies: - atomic-sleep "^1.0.0" - fast-redact "^3.1.1" - on-exit-leak-free "^2.1.0" - pino-abstract-transport "^2.0.0" - pino-std-serializers "^7.0.0" - process-warning "^4.0.0" - quick-format-unescaped "^4.0.3" - real-require "^0.2.0" - safe-stable-stringify "^2.3.1" - sonic-boom "^4.0.1" - thread-stream "^3.0.0" - -pkg-types@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.2.1.tgz#6ac4e455a5bb4b9a6185c1c79abd544c901db2e5" - integrity sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw== - dependencies: - confbox "^0.1.8" - mlly "^1.7.2" - pathe "^1.1.2" - -pngjs@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" - integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== - -pony-cause@^2.1.10: - version "2.1.11" - resolved "https://registry.yarnpkg.com/pony-cause/-/pony-cause-2.1.11.tgz#d69a20aaccdb3bdb8f74dd59e5c68d8e6772e4bd" - integrity sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg== - -possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== - -postcss@^8.4.43: - version "8.4.49" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" - integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== - dependencies: - nanoid "^3.3.7" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-array@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98" - integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog== - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== - -postgres-bytea@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089" - integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== - dependencies: - obuf "~1.1.2" - -postgres-date@~1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" - integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== - -postgres-date@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0" - integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== - -postgres-interval@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== - dependencies: - xtend "^4.0.0" - -postgres-interval@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" - integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== - -postgres-range@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" - integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== - -pprof-format@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" - integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== - -preact@^10.16.0, preact@^10.24.2: - version "10.25.1" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.25.1.tgz#1c4b84253c42dee874bfbf6a92bdce45e3662665" - integrity sha512-frxeZV2vhQSohQwJ7FvlqC40ze89+8friponWUFeVEkaCfhC6Eu4V0iND5C9CXz8JLndV07QRDeXzH1+Anz5Og== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - -pretty-ms@^9.0.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-9.2.0.tgz#e14c0aad6493b69ed63114442a84133d7e560ef0" - integrity sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg== - dependencies: - parse-ms "^4.0.0" - -prisma@^5.14.0: - version "5.22.0" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.22.0.tgz#1f6717ff487cdef5f5799cc1010459920e2e6197" - integrity sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A== - dependencies: - "@prisma/engines" "5.22.0" - optionalDependencies: - fsevents "2.3.3" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process-warning@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" - integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== - -process-warning@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-3.0.0.tgz#96e5b88884187a1dce6f5c3166d611132058710b" - integrity sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ== - -process-warning@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.0.tgz#581e3a7a1fb456c5f4fd239f76bce75897682d5a" - integrity sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -prom-client@^15.1.3: - version "15.1.3" - resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.3.tgz#69fa8de93a88bc9783173db5f758dc1c69fa8fc2" - integrity sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g== - dependencies: - "@opentelemetry/api" "^1.4.0" - tdigest "^0.1.1" - -prool@^0.0.16: - version "0.0.16" - resolved "https://registry.yarnpkg.com/prool/-/prool-0.0.16.tgz#b18c76fd102485ce4c706bb6031bd85a49859a45" - integrity sha512-s+i66jsINIJQd8w5iGunT8hCeM6RSXjL8qgXDTvcIuaAOjVRVMh0/PgbJ90KR3JAprXWXpa5XQnDEc4fLnvy1Q== - dependencies: - change-case "5.4.4" - eventemitter3 "^5.0.1" - execa "^9.1.0" - get-port "^7.1.0" - http-proxy "^1.18.1" - tar "7.2.0" - -proto3-json-serializer@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz#1b5703152b6ce811c5cdcc6468032caf53521331" - integrity sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw== - dependencies: - protobufjs "^7.0.0" - -proto3-json-serializer@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz#5b705203b4d58f3880596c95fad64902617529dd" - integrity sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ== - dependencies: - protobufjs "^7.2.5" - -protobufjs-cli@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz#f531201b1c8c7772066aa822bf9a08318b24a704" - integrity sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA== - dependencies: - chalk "^4.0.0" - escodegen "^1.13.0" - espree "^9.0.0" - estraverse "^5.1.0" - glob "^8.0.0" - jsdoc "^4.0.0" - minimist "^1.2.0" - semver "^7.1.2" - tmp "^0.2.1" - uglify-js "^3.7.7" - -protobufjs@7.2.4: - version "7.2.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.4.tgz#3fc1ec0cdc89dd91aef9ba6037ba07408485c3ae" - integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/node" ">=13.7.0" - long "^5.0.0" - -protobufjs@^7.0.0, protobufjs@^7.2.5, protobufjs@^7.3.2: - version "7.4.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" - integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/node" ">=13.7.0" - long "^5.0.0" - -proxy-addr@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -proxy-compare@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.5.1.tgz#17818e33d1653fbac8c2ec31406bce8a2966f600" - integrity sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA== - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -public-encrypt@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -punycode.js@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" - integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -pvtsutils@^1.3.2: - version "1.3.6" - resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" - integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== - dependencies: - tslib "^2.8.1" - -pvutils@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" - integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== - -qrcode@1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" - integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== - dependencies: - dijkstrajs "^1.0.1" - encode-utf8 "^1.0.3" - pngjs "^5.0.0" - yargs "^15.3.1" - -qs@6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" - integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== - dependencies: - side-channel "^1.0.6" - -qs@^6.12.3: - version "6.13.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.1.tgz#3ce5fc72bd3a8171b85c99b93c65dd20b7d1b16e" - integrity sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg== - dependencies: - side-channel "^1.0.6" - -query-string@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" - integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== - dependencies: - decode-uri-component "^0.2.2" - filter-obj "^1.1.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - -quick-format-unescaped@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" - integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== - -radix3@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.2.tgz#fd27d2af3896c6bf4bcdfab6427c69c2afc69ec0" - integrity sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-is@^16.7.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-remove-scroll-bar@^2.3.3: - version "2.3.6" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" - integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== - dependencies: - react-style-singleton "^2.2.1" - tslib "^2.0.0" - -react-remove-scroll-bar@^2.3.7: - version "2.3.8" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" - integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== - dependencies: - react-style-singleton "^2.2.2" - tslib "^2.0.0" - -react-remove-scroll@2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" - integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== - dependencies: - react-remove-scroll-bar "^2.3.3" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - -react-remove-scroll@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz#2518d2c5112e71ea8928f1082a58459b5c7a2a97" - integrity sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw== - dependencies: - react-remove-scroll-bar "^2.3.7" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.3" - use-sidecar "^1.1.2" - -react-style-singleton@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" - integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== - dependencies: - get-nonce "^1.0.0" - invariant "^2.2.4" - tslib "^2.0.0" - -react-style-singleton@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" - integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== - dependencies: - get-nonce "^1.0.0" - tslib "^2.0.0" - -readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -real-require@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" - integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== - -real-require@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" - integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== - -rechoir@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" - integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== - dependencies: - resolve "^1.20.0" - -redis-errors@^1.0.0, redis-errors@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" - integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== - -redis-info@^3.0.8: - version "3.1.0" - resolved "https://registry.yarnpkg.com/redis-info/-/redis-info-3.1.0.tgz#5e349c8720e82d27ac84c73136dce0931e10469a" - integrity sha512-ER4L9Sh/vm63DkIE0bkSjxluQlioBiBgf5w1UuldaW/3vPcecdljVDisZhmnCMvsxHNiARTTDDHGg9cGwTfrKg== - dependencies: - lodash "^4.17.11" - -redis-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" - integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== - dependencies: - redis-errors "^1.0.0" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -requizzle@^0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" - integrity sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw== - dependencies: - lodash "^4.17.21" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.19.0, resolve@^1.20.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -ret@~0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.4.3.tgz#5243fa30e704a2e78a9b9b1e86079e15891aa85c" - integrity sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ== - -retry-request@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" - integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== - dependencies: - debug "^4.1.1" - extend "^3.0.2" - -retry-request@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-7.0.2.tgz#60bf48cfb424ec01b03fca6665dee91d06dd95f3" - integrity sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w== - dependencies: - "@types/request" "^2.48.8" - extend "^3.0.2" - teeny-request "^9.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.0, rfdc@^1.3.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" - integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== - -rimraf@^5.0.5: - version "5.0.10" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" - integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== - dependencies: - glob "^10.3.7" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: - version "2.2.7" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" - integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== - dependencies: - bn.js "^5.2.0" - -rollup@^4.20.0: - version "4.28.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.28.1.tgz#7718ba34d62b449dfc49adbfd2f312b4fe0df4de" - integrity sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg== - dependencies: - "@types/estree" "1.0.6" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.28.1" - "@rollup/rollup-android-arm64" "4.28.1" - "@rollup/rollup-darwin-arm64" "4.28.1" - "@rollup/rollup-darwin-x64" "4.28.1" - "@rollup/rollup-freebsd-arm64" "4.28.1" - "@rollup/rollup-freebsd-x64" "4.28.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.28.1" - "@rollup/rollup-linux-arm-musleabihf" "4.28.1" - "@rollup/rollup-linux-arm64-gnu" "4.28.1" - "@rollup/rollup-linux-arm64-musl" "4.28.1" - "@rollup/rollup-linux-loongarch64-gnu" "4.28.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.28.1" - "@rollup/rollup-linux-riscv64-gnu" "4.28.1" - "@rollup/rollup-linux-s390x-gnu" "4.28.1" - "@rollup/rollup-linux-x64-gnu" "4.28.1" - "@rollup/rollup-linux-x64-musl" "4.28.1" - "@rollup/rollup-win32-arm64-msvc" "4.28.1" - "@rollup/rollup-win32-ia32-msvc" "4.28.1" - "@rollup/rollup-win32-x64-msvc" "4.28.1" - fsevents "~2.3.2" - -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-json-utils@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.1.1.tgz#0e883874467d95ab914c3f511096b89bfb3e63b1" - integrity sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ== - -safe-regex2@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-3.1.0.tgz#fd7ec23908e2c730e1ce7359a5b72883a87d2763" - integrity sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug== - dependencies: - ret "~0.4.0" - -safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" - integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== - -sax@>=0.6.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" - integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== - -scrypt-js@3.0.1, scrypt-js@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -secp256k1@4.0, secp256k1@>=4.0.4, secp256k1@^4.0.1, secp256k1@^4.0.3: - version "5.0.1" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.1.tgz#dc2c86187d48ff2da756f0f7e96417ee03c414b1" - integrity sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA== - dependencies: - elliptic "^6.5.7" - node-addon-api "^5.0.0" - node-gyp-build "^4.2.0" - -secure-json-parse@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" - integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== - -semver@^7.1.2, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-cookie-parser@^2.4.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" - integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== - -set-function-length@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -setimmediate@^1.0.4, setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a" - integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA== - -side-channel-list@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" - integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - -side-channel-map@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" - integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - -side-channel-weakmap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" - integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - get-intrinsic "^1.2.5" - object-inspect "^1.13.3" - side-channel-map "^1.0.1" - -side-channel@^1.0.6: - version "1.1.0" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" - integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== - dependencies: - es-errors "^1.3.0" - object-inspect "^1.13.3" - side-channel-list "^1.0.0" - side-channel-map "^1.0.1" - side-channel-weakmap "^1.0.2" - -siginfo@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" - integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== - -signal-exit@^4.0.1, signal-exit@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== - dependencies: - is-arrayish "^0.3.1" - -solady@0.0.180: - version "0.0.180" - resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.180.tgz#d806c84a0bf8b6e3d85a8fb0978980de086ff59e" - integrity sha512-9QVCyMph+wk78Aq/GxtDAQg7dvNoVWx2dS2Zwf11XlwFKDZ+YJG2lrQsK9NEIth9NOebwjBXAYk4itdwOOE4aw== - -sonic-boom@^2.2.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" - integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== - dependencies: - atomic-sleep "^1.0.0" - -sonic-boom@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" - integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== - dependencies: - atomic-sleep "^1.0.0" - -source-map-js@^1.2.0, source-map-js@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" - integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== - -source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - -source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== - -split2@^3.1.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" - integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== - dependencies: - readable-stream "^3.0.0" - -split2@^4.0.0, split2@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" - integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== - -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - -stackback@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" - integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== - -standard-as-callback@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" - integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -std-env@^3.7.0, std-env@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" - integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-events@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" - integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== - dependencies: - stubs "^3.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" - integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== - -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - -strip-final-newline@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz#35a369ec2ac43df356e3edd5dcebb6429aa1fa5c" - integrity sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw== - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== - dependencies: - is-hex-prefixed "1.0.0" - -strip-json-comments@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== - -stubs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" - integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== - -stylis@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" - integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== - -superjson@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.2.tgz#9d52bf0bf6b5751a3c3472f1292e714782ba3173" - integrity sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q== - dependencies: - copy-anything "^3.0.2" - -superstruct@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" - integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -system-architecture@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/system-architecture/-/system-architecture-0.1.0.tgz#71012b3ac141427d97c67c56bc7921af6bff122d" - integrity sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA== - -tar@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-7.2.0.tgz#f03ae6ecd2e2bab880f2ef33450f502e761d7548" - integrity sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w== - dependencies: - "@isaacs/fs-minipass" "^4.0.0" - chownr "^3.0.0" - minipass "^7.1.0" - minizlib "^3.0.1" - mkdirp "^3.0.1" - yallist "^5.0.0" - -tarn@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" - integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== - -tdigest@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced" - integrity sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA== - dependencies: - bintrees "1.0.2" - -teeny-request@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-9.0.0.tgz#18140de2eb6595771b1b02203312dfad79a4716d" - integrity sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g== - dependencies: - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - node-fetch "^2.6.9" - stream-events "^1.0.5" - uuid "^9.0.0" - -test-exclude@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-7.0.1.tgz#20b3ba4906ac20994e275bbcafd68d510264c2a2" - integrity sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^10.4.1" - minimatch "^9.0.4" - -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - -thirdweb@5.29.6: - version "5.29.6" - resolved "https://registry.yarnpkg.com/thirdweb/-/thirdweb-5.29.6.tgz#3f801de1d8cdf43423f24cf65168bf84a3e0d214" - integrity sha512-OR/YjArZE2gc72kwJENbbWqxT6AY/X7phdyuu9GgG2O56/vbr4rytKdPesGUeYZ3dY5moUgZZgff+FmQhW0OCA== - dependencies: - "@coinbase/wallet-sdk" "4.0.3" - "@emotion/react" "11.11.4" - "@emotion/styled" "11.11.0" - "@google/model-viewer" "2.1.1" - "@noble/curves" "1.4.0" - "@noble/hashes" "1.4.0" - "@passwordless-id/webauthn" "^1.6.1" - "@radix-ui/react-dialog" "1.0.5" - "@radix-ui/react-focus-scope" "1.0.4" - "@radix-ui/react-icons" "1.3.0" - "@radix-ui/react-tooltip" "1.0.7" - "@tanstack/react-query" "5.29.2" - "@walletconnect/ethereum-provider" "2.12.2" - "@walletconnect/sign-client" "^2.13.1" - abitype "1.0.0" - fast-text-encoding "^1.0.6" - fuse.js "7.0.0" - input-otp "^1.2.4" - mipd "0.0.7" - node-libs-browser "2.2.1" - uqr "0.1.2" - viem "2.13.7" - -thirdweb@^5.83.0: - version "5.83.0" - resolved "https://registry.yarnpkg.com/thirdweb/-/thirdweb-5.83.0.tgz#0fb445daa472fcb9bdde61614979a33d0101f163" - integrity sha512-E0wRMEQvbh9EZvrwfHCDHE+RRhDjJAewk/umhwA55axRf4/LENHM0l3KmlQKEaWRXmla8fu+d6q39OlU1QrSTw== - dependencies: - "@coinbase/wallet-sdk" "4.2.4" - "@emotion/react" "11.14.0" - "@emotion/styled" "11.14.0" - "@google/model-viewer" "2.1.1" - "@noble/curves" "1.7.0" - "@noble/hashes" "1.6.1" - "@passwordless-id/webauthn" "^2.1.2" - "@radix-ui/react-dialog" "1.1.4" - "@radix-ui/react-focus-scope" "1.1.1" - "@radix-ui/react-icons" "1.3.2" - "@radix-ui/react-tooltip" "1.1.5" - "@tanstack/react-query" "5.62.16" - "@walletconnect/ethereum-provider" "2.17.3" - "@walletconnect/sign-client" "2.17.3" - abitype "1.0.7" - cross-spawn "7.0.6" - fuse.js "7.0.0" - input-otp "^1.4.1" - mipd "0.0.7" - ox "0.4.2" - uqr "0.1.2" - viem "2.21.55" - -thread-stream@^0.15.1: - version "0.15.2" - resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" - integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA== - dependencies: - real-require "^0.1.0" - -thread-stream@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" - integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== - dependencies: - real-require "^0.2.0" - -three@^0.146.0: - version "0.146.0" - resolved "https://registry.yarnpkg.com/three/-/three-0.146.0.tgz#fd80f0d128ab4bb821a02191ae241e4e6326f17a" - integrity sha512-1lvNfLezN6OJ9NaFAhfX4sm5e9YCzHtaRgZ1+B4C+Hv6TibRMsuBAM5/wVKzxjpYIlMymvgsHEFrrigEfXnb2A== - -tildify@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-2.0.0.tgz#f205f3674d677ce698b7067a99e949ce03b4754a" - integrity sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw== - -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - -tiny-invariant@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" - integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== - -tinybench@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" - integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== - -tinyexec@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98" - integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ== - -tinypool@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2" - integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA== - -tinyrainbow@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" - integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== - -tinyspy@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" - integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== - -tlhunter-sorted-set@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tlhunter-sorted-set/-/tlhunter-sorted-set-0.1.0.tgz#1c3eae28c0fa4dff97e9501d2e3c204b86406f4b" - integrity sha512-eGYW4bjf1DtrHzUYxYfAcSytpOkA44zsr7G2n3PV7yOUR23vmkGe3LL4R+1jL9OsXtbsFOwe8XtbCrabeaEFnw== - -tmp@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" - integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toad-cache@^3.3.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441" - integrity sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw== - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -treeify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" - integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== - -triple-beam@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" - integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== - -tslib@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== - -tweetnacl-util@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" - integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== - -tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - -type-detect@^4.0.0, type-detect@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" - integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -type@^2.7.2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" - integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typescript@^5.1.3: - version "5.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" - integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== - -uc.micro@^2.0.0, uc.micro@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" - integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== - -ufo@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754" - integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== - -uglify-js@^3.1.4, uglify-js@^3.7.7: - version "3.19.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" - integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== - -uint8arrays@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.0.tgz#8186b8eafce68f28bd29bd29d683a311778901e2" - integrity sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog== - dependencies: - multiformats "^9.4.2" - -uint8arrays@^2.1.3: - version "2.1.10" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a" - integrity sha512-Q9/hhJa2836nQfEJSZTmr+pg9+cDJS9XEAp7N2Vg5MzL3bK/mkMVfjscRGYruP9jNda6MAdf4QD/y78gSzkp6A== - dependencies: - multiformats "^9.4.2" - -uint8arrays@^3.0.0, uint8arrays@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" - integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== - dependencies: - multiformats "^9.4.2" - -uncrypto@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" - integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== - -underscore@~1.13.2: - version "1.13.7" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.7.tgz#970e33963af9a7dda228f17ebe8399e5fbe63a10" - integrity sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -undici-types@~6.20.0: - version "6.20.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" - integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== - -undici@^6.20.1: - version "6.20.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.20.1.tgz#fbb87b1e2b69d963ff2d5410a40ffb4c9e81b621" - integrity sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA== - -unenv@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.10.0.tgz#c3394a6c6e4cfe68d699f87af456fe3f0db39571" - integrity sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ== - dependencies: - consola "^3.2.3" - defu "^6.1.4" - mime "^3.0.0" - node-fetch-native "^1.6.4" - pathe "^1.1.2" - -unfetch@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" - integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== - -unicorn-magic@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz#4efd45c85a69e0dd576d25532fbfa22aa5c8a104" - integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== - -universalify@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" - integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -unstorage@^1.9.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.13.1.tgz#090b30de978ee8755b3ad7bbc00acfade124ac13" - integrity sha512-ELexQHUrG05QVIM/iUeQNdl9FXDZhqLJ4yP59fnmn2jGUh0TEulwOgov1ubOb3Gt2ZGK/VMchJwPDNVEGWQpRg== - dependencies: - anymatch "^3.1.3" - chokidar "^3.6.0" - citty "^0.1.6" - destr "^2.0.3" - h3 "^1.13.0" - listhen "^1.9.0" - lru-cache "^10.4.3" - node-fetch-native "^1.6.4" - ofetch "^1.4.1" - ufo "^1.5.4" - -untun@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.3.tgz#5d10dee37a3a5737ff03d158be877dae0a0e58a6" - integrity sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ== - dependencies: - citty "^0.1.5" - consola "^3.2.3" - pathe "^1.1.1" - -uqr@0.1.2, uqr@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d" - integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -url@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" - integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== - dependencies: - punycode "^1.4.1" - qs "^6.12.3" - -use-callback-ref@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" - integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== - dependencies: - tslib "^2.0.0" - -use-callback-ref@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" - integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== - dependencies: - tslib "^2.0.0" - -use-sidecar@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" - integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== - dependencies: - detect-node-es "^1.1.0" - tslib "^2.0.0" - -use-sync-external-store@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== - -utf-8-validate@^5.0.2: - version "5.0.10" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" - integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== - dependencies: - node-gyp-build "^4.3.0" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -util@^0.12.0, util@^0.12.4, util@^0.12.5: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - -uuid@8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -uuid@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== - -uuid@^9.0.0, uuid@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" - integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== - -valtio@1.11.2: - version "1.11.2" - resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.11.2.tgz#b8049c02dfe65620635d23ebae9121a741bb6530" - integrity sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw== - dependencies: - proxy-compare "2.5.1" - use-sync-external-store "1.2.0" - -varint@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" - integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== - -varint@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0" - integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg== - -viem@2.13.7: - version "2.13.7" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.13.7.tgz#c1153c02f7ffaf0263d784fc1d4e4ffa3f66c24a" - integrity sha512-SZWn9LPrz40PHl4PM2iwkPTTtjWPDFsnLr32UwpqC/Z5f0AwxitjLyZdDKcImvbWZ3vLQ0oPggR1aLlqvTcUug== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@scure/bip32" "1.3.2" - "@scure/bip39" "1.2.1" - abitype "1.0.0" - isows "1.0.4" - ws "8.13.0" - -viem@2.21.55: - version "2.21.55" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.55.tgz#a57ad31fcf2a0f6c011b1909f02c94421ec4f781" - integrity sha512-PgXew7C11cAuEtOSgRyQx2kJxEOPUwIwZA9dMglRByqJuFVA7wSGZZOOo/93iylAA8E15bEdqy9xulU3oKZ70Q== - dependencies: - "@noble/curves" "1.7.0" - "@noble/hashes" "1.6.1" - "@scure/bip32" "1.6.0" - "@scure/bip39" "1.5.0" - abitype "1.0.7" - isows "1.0.6" - ox "0.1.2" - webauthn-p256 "0.0.10" - ws "8.18.0" - -viem@^2.21.54: - version "2.21.54" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.21.54.tgz#76d6f86ab8809078f1ac140ac1a2beadbc86b9f6" - integrity sha512-G9mmtbua3UtnVY9BqAtWdNp+3AO+oWhD0B9KaEsZb6gcrOWgmA4rz02yqEMg+qW9m6KgKGie7q3zcHqJIw6AqA== - dependencies: - "@noble/curves" "1.7.0" - "@noble/hashes" "1.6.1" - "@scure/bip32" "1.6.0" - "@scure/bip39" "1.5.0" - abitype "1.0.7" - isows "1.0.6" - ox "0.1.2" - webauthn-p256 "0.0.10" - ws "8.18.0" - -vite-node@2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.8.tgz#9495ca17652f6f7f95ca7c4b568a235e0c8dbac5" - integrity sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg== - dependencies: - cac "^6.7.14" - debug "^4.3.7" - es-module-lexer "^1.5.4" - pathe "^1.1.2" - vite "^5.0.0" - -vite@^5.0.0: - version "5.4.11" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.11.tgz#3b415cd4aed781a356c1de5a9ebafb837715f6e5" - integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q== - dependencies: - esbuild "^0.21.3" - postcss "^8.4.43" - rollup "^4.20.0" - optionalDependencies: - fsevents "~2.3.3" - -vitest@^2.0.3: - version "2.1.8" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.8.tgz#2e6a00bc24833574d535c96d6602fb64163092fa" - integrity sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ== - dependencies: - "@vitest/expect" "2.1.8" - "@vitest/mocker" "2.1.8" - "@vitest/pretty-format" "^2.1.8" - "@vitest/runner" "2.1.8" - "@vitest/snapshot" "2.1.8" - "@vitest/spy" "2.1.8" - "@vitest/utils" "2.1.8" - chai "^5.1.2" - debug "^4.3.7" - expect-type "^1.1.0" - magic-string "^0.30.12" - pathe "^1.1.2" - std-env "^3.8.0" - tinybench "^2.9.0" - tinyexec "^0.3.1" - tinypool "^1.0.1" - tinyrainbow "^1.2.0" - vite "^5.0.0" - vite-node "2.1.8" - why-is-node-running "^2.3.0" - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -web3-core-helpers@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.4.tgz#bd2b4140df2016d5dd3bb2b925fc29ad8678677c" - integrity sha512-r+L5ylA17JlD1vwS8rjhWr0qg7zVoVMDvWhajWA5r5+USdh91jRUYosp19Kd1m2vE034v7Dfqe1xYRoH2zvG0g== - dependencies: - web3-eth-iban "1.10.4" - web3-utils "1.10.4" - -web3-core-helpers@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.5.2.tgz#b6bd5071ca099ba3f92dfafb552eed2b70af2795" - integrity sha512-U7LJoeUdQ3aY9t5gU7t/1XpcApsWm+4AcW5qKl/44ZxD44w0Dmsq1c5zJm3GuLr/a9MwQfXK4lpmvxVQWHHQRg== - dependencies: - web3-eth-iban "1.5.2" - web3-utils "1.5.2" - -web3-core-method@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.4.tgz#566b52f006d3cbb13b21b72b8d2108999bf5d6bf" - integrity sha512-uZTb7flr+Xl6LaDsyTeE2L1TylokCJwTDrIVfIfnrGmnwLc6bmTWCCrm71sSrQ0hqs6vp/MKbQYIYqUN0J8WyA== - dependencies: - "@ethersproject/transactions" "^5.6.2" - web3-core-helpers "1.10.4" - web3-core-promievent "1.10.4" - web3-core-subscriptions "1.10.4" - web3-utils "1.10.4" - -web3-core-method@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.5.2.tgz#d1d602657be1000a29d11e3ca3bf7bc778dea9a5" - integrity sha512-/mC5t9UjjJoQmJJqO5nWK41YHo+tMzFaT7Tp7jDCQsBkinE68KsUJkt0jzygpheW84Zra0DVp6q19gf96+cugg== - dependencies: - "@ethereumjs/common" "^2.4.0" - "@ethersproject/transactions" "^5.0.0-beta.135" - web3-core-helpers "1.5.2" - web3-core-promievent "1.5.2" - web3-core-subscriptions "1.5.2" - web3-utils "1.5.2" - -web3-core-promievent@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.10.4.tgz#629b970b7934430b03c5033c79f3bb3893027e22" - integrity sha512-2de5WnJQ72YcIhYwV/jHLc4/cWJnznuoGTJGD29ncFQHAfwW/MItHFSVKPPA5v8AhJe+r6y4Y12EKvZKjQVBvQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-promievent@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.5.2.tgz#2dc9fe0e5bbeb7c360fc1aac5f12b32d9949a59b" - integrity sha512-5DacbJXe98ozSor7JlkTNCy6G8945VunRRkPxMk98rUrg60ECVEM/vuefk1atACzjQsKx6tmLZuHxbJQ64TQeQ== - dependencies: - eventemitter3 "4.0.4" - -web3-core-requestmanager@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.10.4.tgz#eb1f147e6b9df84e3a37e602162f8925bdb4bb9a" - integrity sha512-vqP6pKH8RrhT/2MoaU+DY/OsYK9h7HmEBNCdoMj+4ZwujQtw/Mq2JifjwsJ7gits7Q+HWJwx8q6WmQoVZAWugg== - dependencies: - util "^0.12.5" - web3-core-helpers "1.10.4" - web3-providers-http "1.10.4" - web3-providers-ipc "1.10.4" - web3-providers-ws "1.10.4" - -web3-core-requestmanager@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.5.2.tgz#43ccc00779394c941b28e6e07e217350fd1ded71" - integrity sha512-oRVW9OrAsXN2JIZt68OEg1Mb1A9a/L3JAGMv15zLEFEnJEGw0KQsGK1ET2kvZBzvpFd5G0EVkYCnx7WDe4HSNw== - dependencies: - util "^0.12.0" - web3-core-helpers "1.5.2" - web3-providers-http "1.5.2" - web3-providers-ipc "1.5.2" - web3-providers-ws "1.5.2" - -web3-core-subscriptions@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.4.tgz#2f4dcb404237e92802a563265d11a33934dc38e6" - integrity sha512-o0lSQo/N/f7/L76C0HV63+S54loXiE9fUPfHFcTtpJRQNDBVsSDdWRdePbWwR206XlsBqD5VHApck1//jEafTw== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.10.4" - -web3-core-subscriptions@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.5.2.tgz#8eaebde44f81fc13c45b555c4422fe79393da9cf" - integrity sha512-hapI4rKFk22yurtIv0BYvkraHsM7epA4iI8Np+HuH6P9DD0zj/llaps6TXLM9HyacLBRwmOLZmr+pHBsPopUnQ== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.5.2" - -web3-core@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.5.2.tgz#ca2b9b1ed3cf84d48b31c9bb91f7628f97cfdcd5" - integrity sha512-sebMpQbg3kbh3vHUbHrlKGKOxDWqjgt8KatmTBsTAWj/HwWYVDzeX+2Q84+swNYsm2DrTBVFlqTErFUwPBvyaA== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.5.2" - web3-core-method "1.5.2" - web3-core-requestmanager "1.5.2" - web3-utils "1.5.2" - -web3-core@^1.8.1: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.4.tgz#639de68b8b9871d2dc8892e0dd4e380cb1361a98" - integrity sha512-B6elffYm81MYZDTrat7aEhnhdtVE3lDBUZft16Z8awYMZYJDbnykEbJVS+l3mnA7AQTnSDr/1MjWofGDLBJPww== - dependencies: - "@types/bn.js" "^5.1.1" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.10.4" - web3-core-method "1.10.4" - web3-core-requestmanager "1.10.4" - web3-utils "1.10.4" - -web3-errors@^1.2.0, web3-errors@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/web3-errors/-/web3-errors-1.3.1.tgz#163bc4d869f98614760b683d733c3ed1fb415d98" - integrity sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ== - dependencies: - web3-types "^1.10.0" - -web3-eth-iban@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.4.tgz#bc61b4a1930d19b1df8762c606d669902558e54d" - integrity sha512-0gE5iNmOkmtBmbKH2aTodeompnNE8jEyvwFJ6s/AF6jkw9ky9Op9cqfzS56AYAbrqEFuClsqB/AoRves7LDELw== - dependencies: - bn.js "^5.2.1" - web3-utils "1.10.4" - -web3-eth-iban@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.5.2.tgz#f390ad244ef8a6c94de7c58736b0b80a484abc8e" - integrity sha512-C04YDXuSG/aDwOHSX+HySBGb0KraiAVt+/l1Mw7y/fCUrKC/K0yYzMYqY/uYOcvLtepBPsC4ZfUYWUBZ2PO8Vg== - dependencies: - bn.js "^4.11.9" - web3-utils "1.5.2" - -web3-providers-http@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.4.tgz#ca7aa58aeaf8123500c24ffe0595896319f830e8" - integrity sha512-m2P5Idc8hdiO0l60O6DSCPw0kw64Zgi0pMjbEFRmxKIck2Py57RQMu4bxvkxJwkF06SlGaEQF8rFZBmuX7aagQ== - dependencies: - abortcontroller-polyfill "^1.7.5" - cross-fetch "^4.0.0" - es6-promise "^4.2.8" - web3-core-helpers "1.10.4" - -web3-providers-http@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.5.2.tgz#94f95fe5572ca54aa2c2ffd42c63956436c9eb0a" - integrity sha512-dUNFJc9IMYDLZnkoQX3H4ZjvHjGO6VRVCqrBrdh84wPX/0da9dOA7DwIWnG0Gv3n9ybWwu5JHQxK4MNQ444lyA== - dependencies: - web3-core-helpers "1.5.2" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.10.4.tgz#2e03437909e4e7771d646ff05518efae44b783c3" - integrity sha512-YRF/bpQk9z3WwjT+A6FI/GmWRCASgd+gC0si7f9zbBWLXjwzYAKG73bQBaFRAHex1hl4CVcM5WUMaQXf3Opeuw== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.10.4" - -web3-providers-ipc@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.5.2.tgz#68a516883c998eeddf60df4cead77baca4fb4aaa" - integrity sha512-SJC4Sivt4g9LHKlRy7cs1jkJgp7bjrQeUndE6BKs0zNALKguxu6QYnzbmuHCTFW85GfMDjhvi24jyyZHMnBNXQ== - dependencies: - oboe "2.1.5" - web3-core-helpers "1.5.2" - -web3-providers-ws@1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.10.4.tgz#55d0c3ba36c6a79d105f02e20a707eb3978e7f82" - integrity sha512-j3FBMifyuFFmUIPVQR4pj+t5ILhAexAui0opgcpu9R5LxQrLRUZxHSnU+YO25UycSOa/NAX8A+qkqZNpcFAlxA== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.10.4" - websocket "^1.0.32" - -web3-providers-ws@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.5.2.tgz#d336a93ed608b40cdcadfadd1f1bc8d32ea046e0" - integrity sha512-xy9RGlyO8MbJDuKv2vAMDkg+en+OvXG0CGTCM2BTl6l1vIdHpCa+6A/9KV2rK8aU9OBZ7/Pf+Y19517kHVl9RA== - dependencies: - eventemitter3 "4.0.4" - web3-core-helpers "1.5.2" - websocket "^1.0.32" - -web3-types@^1.10.0, web3-types@^1.6.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/web3-types/-/web3-types-1.10.0.tgz#41b0b4d2dd75e919d5b6f37bf139e29f445db04e" - integrity sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw== - -web3-utils@1.10.4, web3-utils@1.5.2, web3-utils@>=4.2.1, web3-utils@^1.3.4, web3-utils@^1.8.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-4.3.3.tgz#e380a1c03a050d3704f94bd08c1c9f50a1487205" - integrity sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw== - dependencies: - ethereum-cryptography "^2.0.0" - eventemitter3 "^5.0.1" - web3-errors "^1.3.1" - web3-types "^1.10.0" - web3-validator "^2.0.6" - -web3-validator@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/web3-validator/-/web3-validator-2.0.6.tgz#a0cdaa39e1d1708ece5fae155b034e29d6a19248" - integrity sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg== - dependencies: - ethereum-cryptography "^2.0.0" - util "^0.12.5" - web3-errors "^1.2.0" - web3-types "^1.6.0" - zod "^3.21.4" - -webauthn-p256@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.10.tgz#877e75abe8348d3e14485932968edf3325fd2fdd" - integrity sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA== - dependencies: - "@noble/curves" "^1.4.0" - "@noble/hashes" "^1.4.0" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -websocket@^1.0.32: - version "1.0.35" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.35.tgz#374197207d7d4cc4c36cbf8a1bb886ee52a07885" - integrity sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.63" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which-typed-array@^1.1.14, which-typed-array@^1.1.2: - version "1.1.16" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.16.tgz#db4db429c4706feca2f01677a144278e4a8c216b" - integrity sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.2" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -why-is-node-running@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" - integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== - dependencies: - siginfo "^2.0.0" - stackback "0.0.2" - -winston-transport@^4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" - integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== - dependencies: - logform "^2.7.0" - readable-stream "^3.6.2" - triple-beam "^1.3.0" - -winston@^3.14.1: - version "3.17.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" - integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== - dependencies: - "@colors/colors" "^1.6.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.7.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.9.0" - -word-wrap@~1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@7.4.6, ws@8.13.0, ws@8.18.0, ws@8.9.0, ws@>=8.17.1, ws@^7.4.0, ws@^7.5.1, ws@^8.0.0: - version "8.18.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" - integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha512-hjXUA6q+jl/bd8ADHcVfFsSPIf+tyLIjuO9TwJC9WI6JP2zKcS7C+p56I9kCLLsaCiNT035iYvEUUzdEFj/8+g== - dependencies: - cookiejar "^2.1.1" - -xml2js@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" - integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - -xmlcreate@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" - integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yallist@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" - integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== - -yaml@^1.10.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yaml@^2.2.2, yaml@^2.4.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773" - integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^20.2.2: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^15.3.1: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yoctocolors@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.1.tgz#e0167474e9fbb9e8b3ecca738deaa61dd12e56fc" - integrity sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ== - -zksync-web3@^0.14.3: - version "0.14.4" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.4.tgz#0b70a7e1a9d45cc57c0971736079185746d46b1f" - integrity sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg== - -zod-to-json-schema@^3.23.0: - version "3.24.1" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz#f08c6725091aadabffa820ba8d50c7ab527f227a" - integrity sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w== - -zod@3.23.8: - version "3.23.8" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" - integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== - -zod@^3.21.4, zod@^3.22.4, zod@^3.23.8: - version "3.24.1" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee" - integrity sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==