tapimo 0.15.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -0
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +4 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +37 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +163 -10
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +13085 -11974
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +46 -15
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +1 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +1 -1
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +896 -191
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +5 -1
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +33 -33
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +66 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +36 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +25 -25
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +5 -4
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/route-policies.d.ts +632 -0
- package/dist/admin/apps/route-policies.d.ts.map +1 -0
- package/dist/admin/apps/route-policies.js +257 -0
- package/dist/admin/apps/route-policies.js.map +1 -0
- package/dist/admin/apps/routes-support.js +39 -3
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +454 -1
- package/dist/admin/apps/routes.d.ts.map +1 -1
- package/dist/admin/apps/routes.js +82 -1
- package/dist/admin/apps/routes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +10 -4
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +24 -4
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/index.d.ts +0 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +99 -103
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +65 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +58 -59
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +2709 -2670
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +5 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +50 -0
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +248 -248
- package/dist/apps/data/routes/balances.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +5 -7
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/earn.d.ts +103 -12
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +456 -220
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +267 -97
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +1 -19
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +93 -56
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +10 -10
- package/dist/apps/data/routes/rpc.d.ts +30 -30
- package/dist/apps/data/routes/rpc.js +45 -11
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +11 -6
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +2 -0
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +30 -22
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +12 -12
- package/dist/apps/data/routes/valuation.d.ts +30 -30
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1 -1
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +18 -11
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +3 -3
- package/dist/apps/management/App.d.ts +3043 -2198
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -0
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +2 -4
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +65 -26
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +16 -4
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +70 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +84 -84
- package/dist/apps/management/routes/cli.d.ts +912 -0
- package/dist/apps/management/routes/cli.d.ts.map +1 -0
- package/dist/apps/management/routes/cli.js +416 -0
- package/dist/apps/management/routes/cli.js.map +1 -0
- package/dist/apps/management/routes/faucet.d.ts +8 -8
- package/dist/apps/management/routes/invitations.d.ts +24 -24
- package/dist/apps/management/routes/invite-links.d.ts +66 -66
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +20 -20
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +8 -2
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +76 -76
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +42 -42
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +7 -9
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +119 -119
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +16 -3
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +4 -2
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -4
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +8 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +16 -4
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -6
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +71 -60
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/routes/Access.d.ts +53 -0
- package/dist/apps/routes/Access.d.ts.map +1 -1
- package/dist/apps/routes/Access.js +121 -0
- package/dist/apps/routes/Access.js.map +1 -1
- package/dist/apps/routes/App.d.ts +397 -158
- package/dist/apps/routes/App.d.ts.map +1 -1
- package/dist/apps/routes/App.js.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.js +217 -32
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/routes/routes/quotes.d.ts +90 -0
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
- package/dist/apps/routes/routes/quotes.js +101 -27
- package/dist/apps/routes/routes/quotes.js.map +1 -1
- package/dist/apps/routes/routes/transfers.d.ts +187 -135
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
- package/dist/apps/routes/routes/transfers.js +182 -37
- package/dist/apps/routes/routes/transfers.js.map +1 -1
- package/dist/cli/ApiKeys.d.ts +120 -0
- package/dist/cli/ApiKeys.d.ts.map +1 -0
- package/dist/cli/ApiKeys.js +138 -0
- package/dist/cli/ApiKeys.js.map +1 -0
- package/dist/cli/Cli.d.ts +92 -34
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +188 -11
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/Credentials.d.ts +95 -0
- package/dist/cli/Credentials.d.ts.map +1 -0
- package/dist/cli/Credentials.js +110 -0
- package/dist/cli/Credentials.js.map +1 -0
- package/dist/cli/Spec.d.ts +59 -0
- package/dist/cli/Spec.d.ts.map +1 -0
- package/dist/cli/Spec.js +77 -0
- package/dist/cli/Spec.js.map +1 -0
- package/dist/cli/bin.js +5 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -5
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/auth.d.ts +73 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +204 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/keys.d.ts +17 -0
- package/dist/cli/commands/keys.d.ts.map +1 -0
- package/dist/cli/commands/keys.js +109 -0
- package/dist/cli/commands/keys.js.map +1 -0
- package/dist/cloudflare.d.ts +27 -2
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +144 -17
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +23 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +418 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +44 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.js +65 -9
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
- package/dist/db/tables/authAccounts.d.ts.map +1 -1
- package/dist/db/tables/authAccounts.js +1 -0
- package/dist/db/tables/authAccounts.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +12 -1
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +4 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +8 -34
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +5 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +10 -2
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +4 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.js +2 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
- package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
- package/dist/db/tables/routesDepositAddresses.js +84 -31
- package/dist/db/tables/routesDepositAddresses.js.map +1 -1
- package/dist/db/tables/routesDeposits.d.ts.map +1 -1
- package/dist/db/tables/routesDeposits.js +31 -21
- package/dist/db/tables/routesDeposits.js.map +1 -1
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
- package/dist/db/tables/routesIdempotency.js +2 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -1
- package/dist/db/tables/routesPolicies.d.ts +58 -0
- package/dist/db/tables/routesPolicies.d.ts.map +1 -0
- package/dist/db/tables/routesPolicies.js +198 -0
- package/dist/db/tables/routesPolicies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidies.js +41 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
- package/dist/db/tables/routesTransfers.d.ts +26 -1
- package/dist/db/tables/routesTransfers.d.ts.map +1 -1
- package/dist/db/tables/routesTransfers.js +36 -6
- package/dist/db/tables/routesTransfers.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +144 -33
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +2 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +11 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +21 -4
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.js +65 -44
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +1 -1
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +3 -2
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/relay.d.ts +2 -0
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +34 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +73 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +212 -85
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +22 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -1
- package/dist/internal/BetterAuth.js +17 -14
- package/dist/internal/BetterAuth.js.map +1 -1
- package/dist/internal/Cache.d.ts +5 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +3 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/CliAuth.d.ts +243 -0
- package/dist/internal/CliAuth.d.ts.map +1 -0
- package/dist/internal/CliAuth.js +249 -0
- package/dist/internal/CliAuth.js.map +1 -0
- package/dist/internal/EarnSharePrices.d.ts +1 -1
- package/dist/internal/EarnSharePrices.d.ts.map +1 -1
- package/dist/internal/EarnSharePrices.js +7 -3
- package/dist/internal/EarnSharePrices.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +47 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +188 -4
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/EarnWithdrawals.d.ts +73 -0
- package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
- package/dist/internal/EarnWithdrawals.js +189 -0
- package/dist/internal/EarnWithdrawals.js.map +1 -0
- package/dist/internal/ExecutionContext.d.ts +21 -0
- package/dist/internal/ExecutionContext.d.ts.map +1 -0
- package/dist/internal/ExecutionContext.js +16 -0
- package/dist/internal/ExecutionContext.js.map +1 -0
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +163 -130
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +26 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +67 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +174 -27
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +4 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Timing.d.ts +6 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +21 -1
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/Tron.d.ts +124 -0
- package/dist/internal/Tron.d.ts.map +1 -0
- package/dist/internal/Tron.js +202 -0
- package/dist/internal/Tron.js.map +1 -0
- package/dist/internal/Viem.d.ts +4 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +25 -6
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/rewards/Read.d.ts +2 -2
- package/dist/internal/rewards/Read.d.ts.map +1 -1
- package/dist/internal/rewards/Read.js +11 -2
- package/dist/internal/rewards/Read.js.map +1 -1
- package/dist/internal/routes/Action.d.ts +27 -0
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +49 -1
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Chain.d.ts +2 -0
- package/dist/internal/routes/Chain.d.ts.map +1 -1
- package/dist/internal/routes/Chain.js +4 -0
- package/dist/internal/routes/Chain.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +5 -0
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Evidence.d.ts.map +1 -1
- package/dist/internal/routes/Evidence.js +6 -2
- package/dist/internal/routes/Evidence.js.map +1 -1
- package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
- package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/EvmTransferSettlement.js +196 -0
- package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
- package/dist/internal/routes/Policy.d.ts +161 -0
- package/dist/internal/routes/Policy.d.ts.map +1 -0
- package/dist/internal/routes/Policy.js +249 -0
- package/dist/internal/routes/Policy.js.map +1 -0
- package/dist/internal/routes/Provider.d.ts +66 -3
- package/dist/internal/routes/Provider.d.ts.map +1 -1
- package/dist/internal/routes/Provider.js +106 -27
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Quota.d.ts +57 -0
- package/dist/internal/routes/Quota.d.ts.map +1 -0
- package/dist/internal/routes/Quota.js +144 -0
- package/dist/internal/routes/Quota.js.map +1 -0
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +163 -47
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
- package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/Subsidy.d.ts +2 -2
- package/dist/internal/routes/Subsidy.d.ts.map +1 -1
- package/dist/internal/routes/Subsidy.js +2 -2
- package/dist/internal/routes/Subsidy.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts +229 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +644 -7
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
- package/dist/internal/routes/TransferReconciliation.js +83 -159
- package/dist/internal/routes/TransferReconciliation.js.map +1 -1
- package/dist/internal/routes/TransferSettlement.d.ts +45 -0
- package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TransferSettlement.js +2 -0
- package/dist/internal/routes/TransferSettlement.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
- package/dist/internal/routes/TransferSubsidy.js +64 -5
- package/dist/internal/routes/TransferSubsidy.js.map +1 -1
- package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSettlement.js +201 -0
- package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.js +439 -0
- package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/index.d.ts +3 -0
- package/dist/internal/routes/index.d.ts.map +1 -1
- package/dist/internal/routes/index.js +3 -0
- package/dist/internal/routes/index.js.map +1 -1
- package/dist/internal/routes/providers/across.d.ts +3 -0
- package/dist/internal/routes/providers/across.d.ts.map +1 -1
- package/dist/internal/routes/providers/across.js +11 -0
- package/dist/internal/routes/providers/across.js.map +1 -1
- package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
- package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMesh.js +474 -0
- package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
- package/dist/internal/routes/providers/propAmm.d.ts +70 -0
- package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
- package/dist/internal/routes/providers/propAmm.js +524 -0
- package/dist/internal/routes/providers/propAmm.js.map +1 -0
- package/dist/internal/routes/providers/relay.d.ts +4 -1
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +353 -42
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/dist/internal/routes/providers/rhino.d.ts +3 -0
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
- package/dist/internal/routes/providers/rhino.js +11 -0
- package/dist/internal/routes/providers/rhino.js.map +1 -1
- package/dist/internal/routes/providers/squid.d.ts +3 -0
- package/dist/internal/routes/providers/squid.d.ts.map +1 -1
- package/dist/internal/routes/providers/squid.js +19 -0
- package/dist/internal/routes/providers/squid.js.map +1 -1
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
- package/dist/internal/routes/providers/stargate.js +22 -9
- package/dist/internal/routes/providers/stargate.js.map +1 -1
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
- package/dist/internal/routes/providers/symbiosis.js +13 -17
- package/dist/internal/routes/providers/symbiosis.js.map +1 -1
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +16 -6
- package/src/ApiKey.ts +7 -3
- package/src/ApiKeys.test.ts +652 -8
- package/src/ApiKeys.ts +191 -11
- package/src/App.test.ts +405 -18
- package/src/App.ts +51 -15
- package/src/Client.test-d.ts +157 -10
- package/src/Client.test.ts +4 -4
- package/src/Scope.ts +1 -2
- package/src/admin/App.ts +11 -5
- package/src/admin/apps/api-keys.test.ts +98 -2
- package/src/admin/apps/api-keys.ts +21 -12
- package/src/admin/apps/earn-vaults.test.ts +76 -7
- package/src/admin/apps/earn-vaults.ts +47 -8
- package/src/admin/apps/organizations.test.ts +147 -31
- package/src/admin/apps/organizations.ts +5 -4
- package/src/admin/apps/route-policies.test.ts +220 -0
- package/src/admin/apps/route-policies.ts +322 -0
- package/src/admin/apps/routes-support.test.ts +107 -2
- package/src/admin/apps/routes-support.ts +43 -3
- package/src/admin/apps/routes.test.ts +150 -0
- package/src/admin/apps/routes.ts +97 -1
- package/src/admin/apps/scopes.test.ts +1 -1
- package/src/admin/apps/verified-tokens.test.ts +32 -0
- package/src/admin/apps/verified-tokens.ts +30 -4
- package/src/admin/index.ts +0 -1
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/components/Dialog.tsx +1 -1
- package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
- package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
- package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
- package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
- package/src/admin/ui/src/lib/route-policies.ts +232 -0
- package/src/admin/ui/src/lib/routes.ts +34 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +24 -9
- package/src/admin/ui/src/routeTree.gen.ts +21 -0
- package/src/admin/ui/src/routes/__root.tsx +1 -1
- package/src/admin/ui/src/routes/api-keys.tsx +21 -2
- package/src/admin/ui/src/routes/early-access.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
- package/src/admin/ui/src/routes/organizations.tsx +35 -4
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
- package/src/admin/ui/src/routes/route-policies.tsx +678 -0
- package/src/admin/ui/src/routes/routes.tsx +85 -2
- package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
- package/src/admin/ui/src/routes/subsidies.tsx +1 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +65 -20
- package/src/admin/ui.generated.ts +99 -104
- package/src/analytics/Analytics.test.ts +4 -50
- package/src/analytics/Analytics.ts +65 -1
- package/src/analytics/tables/requestEvents.test.ts +402 -1
- package/src/analytics/tables/requestEvents.ts +62 -93
- package/src/apps/data/App.test.ts +26 -0
- package/src/apps/data/routes/activities.test.ts +315 -14
- package/src/apps/data/routes/activities.ts +60 -0
- package/src/apps/data/routes/balances.ts +5 -7
- package/src/apps/data/routes/earn.bench.ts +18 -0
- package/src/apps/data/routes/earn.local.test.ts +507 -0
- package/src/apps/data/routes/earn.test.ts +405 -127
- package/src/apps/data/routes/earn.ts +660 -270
- package/src/apps/data/routes/exchanges.bench.ts +3 -1
- package/src/apps/data/routes/exchanges.test.ts +166 -2
- package/src/apps/data/routes/exchanges.ts +308 -101
- package/src/apps/data/routes/fee-amm.test.ts +153 -2
- package/src/apps/data/routes/fee-amm.ts +132 -62
- package/src/apps/data/routes/receipts.test.ts +21 -18
- package/src/apps/data/routes/rpc.test.ts +34 -2
- package/src/apps/data/routes/rpc.ts +47 -10
- package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
- package/src/apps/data/routes/tokens.test.ts +4 -4
- package/src/apps/data/routes/tokens.ts +11 -6
- package/src/apps/data/routes/transactions.test.ts +29 -0
- package/src/apps/data/routes/transactions.ts +33 -22
- package/src/apps/data/routes/webhooks.scan.test.ts +29 -0
- package/src/apps/data/routes/webhooks.test.ts +18 -3
- package/src/apps/data/routes/webhooks.ts +27 -13
- package/src/apps/management/App.ts +4 -0
- package/src/apps/management/Billing.test.ts +253 -27
- package/src/apps/management/Billing.ts +83 -29
- package/src/apps/management/routes/api-keys.test.ts +1 -1
- package/src/apps/management/routes/api-keys.ts +85 -11
- package/src/apps/management/routes/billing.test.ts +68 -4
- package/src/apps/management/routes/cli.test.ts +370 -0
- package/src/apps/management/routes/cli.ts +533 -0
- package/src/apps/management/routes/me.test.ts +14 -4
- package/src/apps/management/routes/orgs.test.ts +108 -4
- package/src/apps/management/routes/orgs.ts +7 -2
- package/src/apps/management/routes/usage.test.ts +2 -2
- package/src/apps/management/routes/verified-token-requests.test.ts +16 -2
- package/src/apps/management/routes/verified-token-requests.ts +7 -10
- package/src/apps/mcp.test.ts +108 -25
- package/src/apps/mcp.ts +15 -3
- package/src/apps/mpp/internal/Policy.test.ts +51 -4
- package/src/apps/mpp/internal/Policy.ts +6 -2
- package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
- package/src/apps/mpp/internal/Sponsorship.ts +6 -4
- package/src/apps/relay/App.test.ts +85 -1
- package/src/apps/relay/App.ts +28 -4
- package/src/apps/relay/Sponsorships.test.ts +97 -1
- package/src/apps/relay/Sponsorships.ts +77 -66
- package/src/apps/routes/Access.test.ts +319 -0
- package/src/apps/routes/Access.ts +147 -0
- package/src/apps/routes/App.ts +10 -0
- package/src/apps/routes/routes/chains.test.ts +3 -2
- package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
- package/src/apps/routes/routes/deposit-addresses.ts +243 -32
- package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
- package/src/apps/routes/routes/quotes.test.ts +81 -8
- package/src/apps/routes/routes/quotes.ts +109 -27
- package/src/apps/routes/routes/transfers.test.ts +252 -15
- package/src/apps/routes/routes/transfers.ts +212 -33
- package/src/cli/ApiKeys.test.ts +265 -0
- package/src/cli/ApiKeys.ts +189 -0
- package/src/cli/Cli.test.ts +188 -0
- package/src/cli/Cli.ts +280 -12
- package/src/cli/Credentials.test.ts +122 -0
- package/src/cli/Credentials.ts +144 -0
- package/src/cli/Spec.test.ts +133 -0
- package/src/cli/Spec.ts +132 -0
- package/src/cli/bin.test.ts +49 -0
- package/src/cli/bin.ts +5 -1
- package/src/cli/commands/auth.test.ts +138 -0
- package/src/cli/commands/auth.ts +254 -0
- package/src/cli/commands/keys.test.ts +68 -0
- package/src/cli/commands/keys.ts +125 -0
- package/src/cloudflare.ts +184 -36
- package/src/db/Db.test.ts +877 -0
- package/src/db/Db.ts +507 -1
- package/src/db/Schema.ts +75 -4
- package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
- package/src/db/tables/apiKeyAdmissions.ts +101 -11
- package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
- package/src/db/tables/authAccounts.test.ts +30 -0
- package/src/db/tables/authAccounts.ts +1 -0
- package/src/db/tables/earnVaults.test.ts +34 -0
- package/src/db/tables/earnVaults.ts +17 -2
- package/src/db/tables/organizations.test.ts +148 -84
- package/src/db/tables/organizations.ts +11 -43
- package/src/db/tables/requestUsage.ts +13 -2
- package/src/db/tables/rewardCampaigns.test.ts +163 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
- package/src/db/tables/rewardRuns.ts +4 -0
- package/src/db/tables/rewardTransactionAttempts.ts +2 -0
- package/src/db/tables/routesDepositAddresses.test.ts +263 -0
- package/src/db/tables/routesDepositAddresses.ts +118 -34
- package/src/db/tables/routesDeposits.test.ts +133 -0
- package/src/db/tables/routesDeposits.ts +47 -26
- package/src/db/tables/routesIdempotency.test.ts +80 -0
- package/src/db/tables/routesIdempotency.ts +2 -0
- package/src/db/tables/routesPolicies.test.ts +143 -0
- package/src/db/tables/routesPolicies.ts +251 -0
- package/src/db/tables/routesTransferSubsidies.ts +64 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
- package/src/db/tables/routesTransfers.test.ts +183 -2
- package/src/db/tables/routesTransfers.ts +65 -6
- package/src/db/tables/sponsoredTransactions.test.ts +351 -76
- package/src/db/tables/sponsoredTransactions.ts +182 -38
- package/src/db/tables/users.test.ts +51 -0
- package/src/db/tables/users.ts +12 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +39 -20
- package/src/db/tables/verifiedTokenRequests.ts +80 -44
- package/src/handlers/internal/multisig.store.test.ts +120 -0
- package/src/handlers/internal/multisig.test.ts +389 -0
- package/src/handlers/internal/multisig.ts +13 -10
- package/src/handlers/relay.test.ts +259 -83
- package/src/handlers/relay.ts +36 -17
- package/src/internal/Auth.test.ts +383 -8
- package/src/internal/Auth.ts +272 -99
- package/src/internal/BetterAuth.test.ts +58 -22
- package/src/internal/BetterAuth.ts +23 -17
- package/src/internal/Cache.ts +3 -1
- package/src/internal/CliAuth.test.ts +279 -0
- package/src/internal/CliAuth.ts +319 -0
- package/src/internal/EarnSharePrices.test.ts +25 -0
- package/src/internal/EarnSharePrices.ts +9 -2
- package/src/internal/EarnVaults.test.ts +67 -0
- package/src/internal/EarnVaults.ts +299 -4
- package/src/internal/EarnWithdrawals.test.ts +315 -0
- package/src/internal/EarnWithdrawals.ts +266 -0
- package/src/internal/ExecutionContext.ts +31 -0
- package/src/internal/Log.test.ts +210 -0
- package/src/internal/Log.ts +180 -142
- package/src/internal/MetricSink.test.ts +190 -15
- package/src/internal/MetricSink.ts +27 -1
- package/src/internal/RateLimit.test.ts +144 -8
- package/src/internal/RateLimit.ts +254 -26
- package/src/internal/Store.ts +4 -5
- package/src/internal/Timing.test.ts +32 -0
- package/src/internal/Timing.ts +20 -1
- package/src/internal/Tron.test-d.ts +22 -0
- package/src/internal/Tron.test.ts +94 -0
- package/src/internal/Tron.ts +289 -0
- package/src/internal/Viem.rpc.test.ts +76 -0
- package/src/internal/Viem.ts +29 -6
- package/src/internal/rewards/Read.test.ts +109 -0
- package/src/internal/rewards/Read.ts +13 -4
- package/src/internal/routes/Action.test.ts +70 -0
- package/src/internal/routes/Action.ts +76 -1
- package/src/internal/routes/Chain.test.ts +18 -0
- package/src/internal/routes/Chain.ts +5 -0
- package/src/internal/routes/DepositAddress.ts +5 -0
- package/src/internal/routes/Evidence.test.ts +64 -0
- package/src/internal/routes/Evidence.ts +11 -3
- package/src/internal/routes/EvmTransferSettlement.ts +213 -0
- package/src/internal/routes/Policy.test.ts +316 -0
- package/src/internal/routes/Policy.ts +399 -0
- package/src/internal/routes/Provider.test.ts +103 -2
- package/src/internal/routes/Provider.ts +149 -27
- package/src/internal/routes/Quota.test.ts +149 -0
- package/src/internal/routes/Quota.ts +226 -0
- package/src/internal/routes/Reconciliation.local.test.ts +285 -0
- package/src/internal/routes/Reconciliation.test.ts +371 -13
- package/src/internal/routes/Reconciliation.ts +193 -42
- package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
- package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
- package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
- package/src/internal/routes/SourceObservation.test.ts +221 -0
- package/src/internal/routes/Subsidy.local.test.ts +46 -0
- package/src/internal/routes/Subsidy.ts +4 -2
- package/src/internal/routes/Transfer.solana.test.ts +389 -0
- package/src/internal/routes/Transfer.test.ts +130 -1
- package/src/internal/routes/Transfer.tron.test.ts +172 -0
- package/src/internal/routes/Transfer.ts +866 -8
- package/src/internal/routes/TransferReconciliation.test.ts +26 -4
- package/src/internal/routes/TransferReconciliation.ts +91 -166
- package/src/internal/routes/TransferSettlement.ts +48 -0
- package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
- package/src/internal/routes/TransferSubsidy.test.ts +34 -4
- package/src/internal/routes/TransferSubsidy.ts +87 -12
- package/src/internal/routes/TronTransferSettlement.ts +212 -0
- package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
- package/src/internal/routes/TronTransferSubsidy.ts +619 -0
- package/src/internal/routes/index.test.ts +3 -0
- package/src/internal/routes/index.ts +3 -0
- package/src/internal/routes/providers/across.ts +13 -0
- package/src/internal/routes/providers/index.test.ts +141 -0
- package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
- package/src/internal/routes/providers/legacyMesh.ts +633 -0
- package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
- package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
- package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
- package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
- package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
- package/src/internal/routes/providers/propAmm.ts +640 -0
- package/src/internal/routes/providers/relay.test.ts +1299 -18
- package/src/internal/routes/providers/relay.ts +424 -39
- package/src/internal/routes/providers/rhino.ts +14 -1
- package/src/internal/routes/providers/squid.ts +21 -0
- package/src/internal/routes/providers/stargate.test.ts +105 -1
- package/src/internal/routes/providers/stargate.ts +22 -9
- package/src/internal/routes/providers/symbiosis.ts +13 -47
- package/src/providers/index.test.ts +2 -0
- package/src/providers/index.ts +18 -0
- package/dist/admin/Access.d.ts +0 -39
- package/dist/admin/Access.d.ts.map +0 -1
- package/dist/admin/Access.js +0 -73
- package/dist/admin/Access.js.map +0 -1
- package/src/admin/Access.test.ts +0 -130
- package/src/admin/Access.ts +0 -85
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono'
|
|
2
|
+
import { sql } from 'kysely'
|
|
2
3
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
3
4
|
|
|
4
5
|
import * as TestApp from '../../../../test/App.js'
|
|
@@ -11,6 +12,8 @@ import * as EarlyAccess from '../../../db/tables/earlyAccess.js'
|
|
|
11
12
|
import * as EnabledBillingSources from '../../../db/tables/enabledBillingSources.js'
|
|
12
13
|
import * as Organizations from '../../../db/tables/organizations.js'
|
|
13
14
|
import * as Projects from '../../../db/tables/projects.js'
|
|
15
|
+
import * as SponsoredTransactions from '../../../db/tables/sponsoredTransactions.js'
|
|
16
|
+
import * as StripeCustomers from '../../../db/tables/stripeCustomers.js'
|
|
14
17
|
import * as Users from '../../../db/tables/users.js'
|
|
15
18
|
import type * as Log from '../../../internal/Log.js'
|
|
16
19
|
import * as RoutesDepositAddress from '../../../internal/routes/DepositAddress.js'
|
|
@@ -568,7 +571,39 @@ describe('PATCH /orgs/:orgId', () => {
|
|
|
568
571
|
})
|
|
569
572
|
|
|
570
573
|
describe('DELETE /orgs/:orgId', () => {
|
|
571
|
-
test('
|
|
574
|
+
test('keeps a timed-out Zone sponsorship billable when its owner requests deletion', async () => {
|
|
575
|
+
const db = TestApp.database()
|
|
576
|
+
const app = createApp(db)
|
|
577
|
+
const cookie = await session(app)
|
|
578
|
+
const created = await app.request('/v1/orgs', json('POST', cookie, { name: 'Acme' }))
|
|
579
|
+
const org = await TestApp.json(created, Orgs.schema.Organization)
|
|
580
|
+
await StripeCustomers.create(db, { orgId: org.id, stripeCustomerId: 'cus_zone' })
|
|
581
|
+
const row = await SponsoredTransactions.upsert(db, {
|
|
582
|
+
apiKeyId: 'key_zone',
|
|
583
|
+
billable: true,
|
|
584
|
+
chainId: 421700001,
|
|
585
|
+
environment: 'production',
|
|
586
|
+
orgId: org.id,
|
|
587
|
+
signPayload: `0x${'bb'.repeat(32)}`,
|
|
588
|
+
transaction: `0x76${'cc'.repeat(16)}`,
|
|
589
|
+
transactionHash: `0x${'aa'.repeat(32)}`,
|
|
590
|
+
})
|
|
591
|
+
await SponsoredTransactions.fail(db, row.id, '2026-01-01T00:00:00.000Z')
|
|
592
|
+
|
|
593
|
+
const response = await app.request(`/v1/orgs/${org.id}`, {
|
|
594
|
+
headers: { cookie },
|
|
595
|
+
method: 'DELETE',
|
|
596
|
+
})
|
|
597
|
+
|
|
598
|
+
expect(response.status).toMatchInlineSnapshot(`409`)
|
|
599
|
+
expect((await response.json()).error.code).toMatchInlineSnapshot(`"sponsorships_unreported"`)
|
|
600
|
+
expect((await StripeCustomers.get(db, org.id))?.stripeCustomerId).toMatchInlineSnapshot(
|
|
601
|
+
`"cus_zone"`,
|
|
602
|
+
)
|
|
603
|
+
expect(await Organizations.get(db, org.id)).toBeDefined()
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
test('rolls back organization deletion when its KV fence cannot be written', async () => {
|
|
572
607
|
const db = TestApp.database()
|
|
573
608
|
const org = await Organizations.create(db, { name: 'Legacy owner' })
|
|
574
609
|
const legacy = {
|
|
@@ -597,11 +632,80 @@ describe('DELETE /orgs/:orgId', () => {
|
|
|
597
632
|
...as(secret),
|
|
598
633
|
method: 'DELETE',
|
|
599
634
|
})
|
|
600
|
-
expect(deleted.status).toBe(
|
|
635
|
+
expect(deleted.status).toBe(502)
|
|
636
|
+
expect(await Organizations.get(db, legacy.id)).toBeDefined()
|
|
637
|
+
|
|
638
|
+
const retained = await app.request(`/v1/orgs/${legacy.id}`, as(legacy.token))
|
|
639
|
+
expect(retained.status).toBe(200)
|
|
640
|
+
|
|
641
|
+
failWrites = false
|
|
642
|
+
const retried = await app.request(`/v1/orgs/${legacy.id}`, {
|
|
643
|
+
...as(secret),
|
|
644
|
+
method: 'DELETE',
|
|
645
|
+
})
|
|
646
|
+
expect(retried.status).toBe(200)
|
|
601
647
|
expect(await Organizations.get(db, legacy.id)).toBeUndefined()
|
|
648
|
+
expect((await app.request(`/v1/orgs/${legacy.id}`, as(legacy.token))).status).toBe(401)
|
|
649
|
+
})
|
|
650
|
+
|
|
651
|
+
test('restores key access when deletion fails after publishing its KV fence', async () => {
|
|
652
|
+
const db = TestApp.database()
|
|
653
|
+
const org = await Organizations.create(db, { name: 'Retained owner' })
|
|
654
|
+
const legacy = {
|
|
655
|
+
id: org.id,
|
|
656
|
+
orgId: org.id,
|
|
657
|
+
scopes: ['management:read'],
|
|
658
|
+
token: 'secret_retained_owner',
|
|
659
|
+
} satisfies TestApp.kvStore.Key
|
|
660
|
+
const store = TestApp.kvStore({ keys: [legacy] })
|
|
661
|
+
const app = createApp(db, { kv: { store } })
|
|
662
|
+
await sql`
|
|
663
|
+
CREATE FUNCTION reject_owner_deletion() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
664
|
+
BEGIN RAISE EXCEPTION 'deletion commit rejected'; END $$;
|
|
665
|
+
CREATE CONSTRAINT TRIGGER reject_owner_deletion AFTER DELETE ON organizations
|
|
666
|
+
DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION reject_owner_deletion();
|
|
667
|
+
`.execute(db.kysely)
|
|
668
|
+
|
|
669
|
+
const deleted = await app.request(`/v1/orgs/${org.id}`, { ...as(secret), method: 'DELETE' })
|
|
602
670
|
|
|
603
|
-
|
|
604
|
-
expect(
|
|
671
|
+
expect(deleted.status).toBe(502)
|
|
672
|
+
expect(await Organizations.get(db, org.id)).toBeDefined()
|
|
673
|
+
expect(await ApiKeys.isOwnerDeleted(store, { orgId: org.id })).toBe(false)
|
|
674
|
+
expect((await app.request(`/v1/orgs/${org.id}`, as(legacy.token))).status).toBe(200)
|
|
675
|
+
await expect(
|
|
676
|
+
ApiKeys.mint(store, { orgId: org.id, scopes: ['data:read'] }),
|
|
677
|
+
).resolves.toBeDefined()
|
|
678
|
+
|
|
679
|
+
await sql`DROP TRIGGER reject_owner_deletion ON organizations`.execute(db.kysely)
|
|
680
|
+
const retried = await app.request(`/v1/orgs/${org.id}`, { ...as(secret), method: 'DELETE' })
|
|
681
|
+
expect(retried.status).toBe(200)
|
|
682
|
+
expect(await ApiKeys.isOwnerDeleted(store, { orgId: org.id })).toBe(true)
|
|
683
|
+
})
|
|
684
|
+
|
|
685
|
+
test('rejects a cached key after deletion even when KV record cleanup fails', async () => {
|
|
686
|
+
const db = TestApp.database()
|
|
687
|
+
const org = await Organizations.create(db, { name: 'Retained KV record' })
|
|
688
|
+
const backing = Store.memory()
|
|
689
|
+
const { token } = await ApiKeys.mint(backing, {
|
|
690
|
+
orgId: org.id,
|
|
691
|
+
scopes: ['data:read'],
|
|
692
|
+
})
|
|
693
|
+
const store = Store.from({
|
|
694
|
+
...backing,
|
|
695
|
+
async delete() {
|
|
696
|
+
throw new Error('KV cleanup unavailable')
|
|
697
|
+
},
|
|
698
|
+
})
|
|
699
|
+
const app = createApp(db, { kv: { store } })
|
|
700
|
+
expect((await app.request('/v1/tokens/not-an-address', as(token))).status).toBe(400)
|
|
701
|
+
|
|
702
|
+
const deleted = await app.request(`/v1/orgs/${org.id}`, {
|
|
703
|
+
...as(secret),
|
|
704
|
+
method: 'DELETE',
|
|
705
|
+
})
|
|
706
|
+
expect(deleted.status).toBe(200)
|
|
707
|
+
expect(await Organizations.get(db, org.id)).toBeUndefined()
|
|
708
|
+
expect((await app.request('/v1/tokens/not-an-address', as(token))).status).toBe(401)
|
|
605
709
|
})
|
|
606
710
|
|
|
607
711
|
test('deletes an owned organization and cascades its projects', async () => {
|
|
@@ -389,17 +389,22 @@ export function orgs() {
|
|
|
389
389
|
return subsidizedDepositAddressesActive(c)
|
|
390
390
|
if (await RoutesDepositAddresses.hasSubsidizedRelayAddress(db, Auth.org(c).id))
|
|
391
391
|
return subsidizedDepositAddressesActive(c)
|
|
392
|
+
const kv = c.get('kv')
|
|
392
393
|
const deleted = await Organizations.deleteOrganization(db, Auth.org(c).id, {
|
|
394
|
+
beforeCommit: kv
|
|
395
|
+
? () => ApiKeys.markOwnerDeleting(kv.store, { orgId: Auth.org(c).id })
|
|
396
|
+
: undefined,
|
|
393
397
|
onDepositAddressesDeactivated(transitions) {
|
|
394
398
|
for (const transition of transitions)
|
|
395
399
|
RoutesObservability.recordDepositAddress(c.get('metrics'), transition)
|
|
396
400
|
},
|
|
401
|
+
}).catch(async (cause) => {
|
|
402
|
+
if (kv) await ApiKeys.reconcileOwnerDeletion(db, kv.store, { orgId: Auth.org(c).id })
|
|
403
|
+
throw cause
|
|
397
404
|
})
|
|
398
405
|
if (!deleted) return organizationNotFound(c)
|
|
399
|
-
const kv = c.get('kv')
|
|
400
406
|
if (kv)
|
|
401
407
|
try {
|
|
402
|
-
await ApiKeys.markOwnerDeleting(kv.store, { orgId: Auth.org(c).id })
|
|
403
408
|
for (const record of await ApiKeys.listByOrg(kv.store, Auth.org(c).id, {
|
|
404
409
|
scopeCatalog: c.get('scopeCatalog'),
|
|
405
410
|
}))
|
|
@@ -273,8 +273,8 @@ describe('GET /orgs/:orgId/usage/requests', () => {
|
|
|
273
273
|
|
|
274
274
|
expect(response.status).toBe(200)
|
|
275
275
|
expect(await TestApp.json(response, Usage.schema.getRequestUsage.Response)).toEqual(emptyUsage)
|
|
276
|
-
//
|
|
277
|
-
expect(query).toHaveBeenCalledTimes(
|
|
276
|
+
// All usage breakdowns share one query.
|
|
277
|
+
expect(query).toHaveBeenCalledTimes(1)
|
|
278
278
|
const sql = query.mock.calls[0]![0]
|
|
279
279
|
expect(sql).toContain(`org_id = '${org.id}'`)
|
|
280
280
|
expect(sql).toContain(`project_id = '${project.id}'`)
|
|
@@ -247,10 +247,18 @@ describe('POST /v1/orgs/:orgId/verified-token-requests', () => {
|
|
|
247
247
|
expect(body.error?.code).toBe('request_pending_exists')
|
|
248
248
|
})
|
|
249
249
|
|
|
250
|
-
test('caps pending requests per organization', async () => {
|
|
250
|
+
test('caps pending requests per requester after an organization is deleted', async () => {
|
|
251
251
|
const context = createApp()
|
|
252
252
|
const requests = context.client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}']['verified-token-requests']
|
|
253
253
|
const { org, owner } = await setup(context)
|
|
254
|
+
const nextResponse = await context.client.v1.orgs.$post(
|
|
255
|
+
{ json: { name: 'Next' } },
|
|
256
|
+
as(owner.cookie),
|
|
257
|
+
)
|
|
258
|
+
expect(nextResponse.status).toBe(200)
|
|
259
|
+
if (nextResponse.status !== 200)
|
|
260
|
+
throw new Error(`Failed to create organization: ${nextResponse.status}`)
|
|
261
|
+
const next = await nextResponse.json()
|
|
254
262
|
|
|
255
263
|
for (let index = 0; index < 10; index++) {
|
|
256
264
|
const created = await requests.$post(
|
|
@@ -267,10 +275,16 @@ describe('POST /v1/orgs/:orgId/verified-token-requests', () => {
|
|
|
267
275
|
expect(created.status).toBe(200)
|
|
268
276
|
}
|
|
269
277
|
|
|
278
|
+
const deleted = await context.client.v1.orgs[':orgId{org_[A-Za-z0-9_-]+}'].$delete(
|
|
279
|
+
{ param: { orgId: org.id } },
|
|
280
|
+
as(owner.cookie),
|
|
281
|
+
)
|
|
282
|
+
expect(deleted.status).toBe(200)
|
|
283
|
+
|
|
270
284
|
const overflow = await requests.$post(
|
|
271
285
|
{
|
|
272
286
|
json: { ...token, address: `0x20c${'f'.padStart(37, '0')}` as `0x${string}`, symbol: 'tOVER' }, // prettier-ignore
|
|
273
|
-
param: { orgId:
|
|
287
|
+
param: { orgId: next.id },
|
|
274
288
|
},
|
|
275
289
|
as(owner.cookie),
|
|
276
290
|
)
|
|
@@ -239,9 +239,6 @@ const paramValidation = {
|
|
|
239
239
|
message: 'Check the path parameters and try again.',
|
|
240
240
|
} as const
|
|
241
241
|
|
|
242
|
-
/** Maximum open (pending) requests per organization. */
|
|
243
|
-
const maxPending = 10
|
|
244
|
-
|
|
245
242
|
/** Mounts organization verified-token request operations. */
|
|
246
243
|
export function verifiedTokenRequests() {
|
|
247
244
|
return new Hono<Environment>()
|
|
@@ -265,7 +262,7 @@ export function verifiedTokenRequests() {
|
|
|
265
262
|
},
|
|
266
263
|
409: {
|
|
267
264
|
codes: ['request_limit_reached', 'request_pending_exists', 'verified_symbol_exists', 'verified_token_exists'], // prettier-ignore
|
|
268
|
-
description: 'The token is already verified or requested, or the
|
|
265
|
+
description: 'The token is already verified or requested, or the requester is at the pending-request limit.', // prettier-ignore
|
|
269
266
|
},
|
|
270
267
|
},
|
|
271
268
|
success: { description: 'Created request.', schema: schema.VerifiedTokenRequest },
|
|
@@ -297,12 +294,6 @@ export function verifiedTokenRequests() {
|
|
|
297
294
|
message: 'A verified token already uses this symbol',
|
|
298
295
|
status: 409,
|
|
299
296
|
})
|
|
300
|
-
if ((await VerifiedTokenRequests.countPending(db, orgId)) >= maxPending)
|
|
301
|
-
return Response.error(c, {
|
|
302
|
-
code: 'request_limit_reached',
|
|
303
|
-
message: `Organizations may have at most ${maxPending} pending requests`,
|
|
304
|
-
status: 409,
|
|
305
|
-
})
|
|
306
297
|
const record = await VerifiedTokenRequests.create(db, {
|
|
307
298
|
address: body.address,
|
|
308
299
|
chainId: body.chainId,
|
|
@@ -330,6 +321,12 @@ export function verifiedTokenRequests() {
|
|
|
330
321
|
200,
|
|
331
322
|
)
|
|
332
323
|
} catch (cause) {
|
|
324
|
+
if (cause instanceof VerifiedTokenRequests.PendingLimitError)
|
|
325
|
+
return Response.error(c, {
|
|
326
|
+
code: 'request_limit_reached',
|
|
327
|
+
message: `Requesters may have at most ${VerifiedTokenRequests.maxPendingPerRequester} pending requests`,
|
|
328
|
+
status: 409,
|
|
329
|
+
})
|
|
333
330
|
return Response.upstream(c, cause)
|
|
334
331
|
}
|
|
335
332
|
},
|
package/src/apps/mcp.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Cli as incur_Cli, z } from 'incur'
|
|
2
2
|
import { data } from 'tapimo/apps'
|
|
3
|
-
import { App } from 'tapimo/server'
|
|
3
|
+
import { App, Store } from 'tapimo/server'
|
|
4
4
|
|
|
5
5
|
import * as TestApp from '../../test/App.js'
|
|
6
6
|
import * as Runtime from '../../test/runtime.js'
|
|
@@ -42,32 +42,36 @@ function docsStub() {
|
|
|
42
42
|
type Host = { fetch: (request: Request) => Response | Promise<Response> }
|
|
43
43
|
|
|
44
44
|
async function request(host: Host, body: unknown, headers: Record<string, string> = {}) {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
)
|
|
45
|
+
const request = new Request(new URL('/mcp', origin), {
|
|
46
|
+
body: JSON.stringify(body),
|
|
47
|
+
headers: {
|
|
48
|
+
accept: 'application/json, text/event-stream',
|
|
49
|
+
'content-type': 'application/json',
|
|
50
|
+
...headers,
|
|
51
|
+
},
|
|
52
|
+
method: 'POST',
|
|
53
|
+
})
|
|
54
|
+
if (request.headers.has('cf-connecting-ip')) Object.assign(request, { cf: {} })
|
|
55
|
+
const response = await host.fetch(request)
|
|
56
56
|
expect(response.status).toBe(200)
|
|
57
57
|
return (await response.json()) as { result: any }
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
function initialize(host: Host) {
|
|
61
|
-
return request(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
function initialize(host: Host, headers: Record<string, string> = {}) {
|
|
61
|
+
return request(
|
|
62
|
+
host,
|
|
63
|
+
{
|
|
64
|
+
id: 1,
|
|
65
|
+
jsonrpc: '2.0',
|
|
66
|
+
method: 'initialize',
|
|
67
|
+
params: {
|
|
68
|
+
capabilities: {},
|
|
69
|
+
clientInfo: { name: 'test-client', version: '1.0.0' },
|
|
70
|
+
protocolVersion: '2025-03-26',
|
|
71
|
+
},
|
|
69
72
|
},
|
|
70
|
-
|
|
73
|
+
headers,
|
|
74
|
+
)
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
async function toolsList(host: Host) {
|
|
@@ -109,8 +113,8 @@ async function toolsSearch(host: Host) {
|
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
/** Loads the complete schema and metadata for one catalog tool. */
|
|
112
|
-
async function toolDetails(host: Host, name: string) {
|
|
113
|
-
return resultJson(await toolsCall(host, 'get_tool_details', { name })) as {
|
|
116
|
+
async function toolDetails(host: Host, name: string, headers: Record<string, string> = {}) {
|
|
117
|
+
return resultJson(await toolsCall(host, 'get_tool_details', { name }, headers)) as {
|
|
114
118
|
annotations?: { readOnlyHint?: boolean }
|
|
115
119
|
inputSchema: { properties?: Record<string, { description?: string }> }
|
|
116
120
|
name: string
|
|
@@ -124,7 +128,7 @@ async function generatedToolCall(
|
|
|
124
128
|
args: Record<string, unknown>,
|
|
125
129
|
headers: Record<string, string> = {},
|
|
126
130
|
) {
|
|
127
|
-
const details = await toolDetails(host, name)
|
|
131
|
+
const details = await toolDetails(host, name, headers)
|
|
128
132
|
return toolsCall(
|
|
129
133
|
host,
|
|
130
134
|
details.annotations?.readOnlyHint === true ? 'call_read_tool' : 'call_write_tool',
|
|
@@ -246,6 +250,85 @@ test('forwards the caller Authorization header to authenticated tools', async ()
|
|
|
246
250
|
expect(resultJson(allowed)).toMatchObject({ data: [] })
|
|
247
251
|
})
|
|
248
252
|
|
|
253
|
+
test('preserves Cloudflare client identity across concurrent generated tools', async () => {
|
|
254
|
+
const store = Store.memory()
|
|
255
|
+
const db = TestApp.database()
|
|
256
|
+
await TestApp.verifiedSeed(db, Runtime.get().chainId)
|
|
257
|
+
const app = App.create({
|
|
258
|
+
auth: { rateLimit: { store } },
|
|
259
|
+
cache: { edge: false },
|
|
260
|
+
db,
|
|
261
|
+
}).route('/', data())
|
|
262
|
+
app.route('/', mcp({ docs: false, fetch: (request) => app.fetch(request) }))
|
|
263
|
+
const headers_a = { 'cf-connecting-ip': '203.0.113.7' }
|
|
264
|
+
const headers_b = { 'cf-connecting-ip': '198.51.100.9' }
|
|
265
|
+
await initialize(app, headers_a)
|
|
266
|
+
|
|
267
|
+
const [result_a, result_b] = await Promise.all([
|
|
268
|
+
generatedToolCall(app, 'v1_tokens_get', { verified: true }, headers_a),
|
|
269
|
+
generatedToolCall(app, 'v1_tokens_get', { verified: true }, headers_b),
|
|
270
|
+
])
|
|
271
|
+
|
|
272
|
+
expect(result_a.isError, JSON.stringify(result_a.content)).toBeFalsy()
|
|
273
|
+
expect(result_b.isError, JSON.stringify(result_b.content)).toBeFalsy()
|
|
274
|
+
const keys = (await store.list({ prefix: 'ratelimit:' })).keys.map((key) => key.name)
|
|
275
|
+
expect(keys.some((key) => key.endsWith('public:203.0.113.7'))).toBe(true)
|
|
276
|
+
expect(keys.some((key) => key.endsWith('public:198.51.100.9'))).toBe(true)
|
|
277
|
+
expect(keys.some((key) => key.endsWith('public:anonymous'))).toBe(false)
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
test('allows an IP-restricted API key through generated tools', async () => {
|
|
281
|
+
const db = TestApp.database()
|
|
282
|
+
await TestApp.verifiedSeed(db, Runtime.get().chainId)
|
|
283
|
+
const key = {
|
|
284
|
+
...TestApp.key,
|
|
285
|
+
allowedIps: ['203.0.113.0/24'],
|
|
286
|
+
}
|
|
287
|
+
const app = App.create({
|
|
288
|
+
auth: {},
|
|
289
|
+
cache: { edge: false },
|
|
290
|
+
db,
|
|
291
|
+
kv: { store: TestApp.kvStore({ keys: [key] }) },
|
|
292
|
+
}).route('/', data())
|
|
293
|
+
app.route('/', mcp({ docs: false, fetch: (request) => app.fetch(request) }))
|
|
294
|
+
const headers = {
|
|
295
|
+
authorization: `Bearer ${key.token}`,
|
|
296
|
+
'cf-connecting-ip': '203.0.113.7',
|
|
297
|
+
}
|
|
298
|
+
await initialize(app, headers)
|
|
299
|
+
|
|
300
|
+
const result = await generatedToolCall(app, 'v1_tokens_get', { verified: true }, headers)
|
|
301
|
+
|
|
302
|
+
expect(result.isError, JSON.stringify(result.content)).toBeFalsy()
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
test('preserves a configured trusted client identity through generated tools', async () => {
|
|
306
|
+
const db = TestApp.database()
|
|
307
|
+
await TestApp.verifiedSeed(db, Runtime.get().chainId)
|
|
308
|
+
const key = {
|
|
309
|
+
...TestApp.key,
|
|
310
|
+
allowedIps: ['198.51.100.0/24'],
|
|
311
|
+
}
|
|
312
|
+
const app = App.create({
|
|
313
|
+
auth: { public: { clientIp: (request) => request.headers.get('x-real-ip') ?? undefined } },
|
|
314
|
+
cache: { edge: false },
|
|
315
|
+
db,
|
|
316
|
+
kv: { store: TestApp.kvStore({ keys: [key] }) },
|
|
317
|
+
}).route('/', data())
|
|
318
|
+
app.route('/', mcp({ docs: false, fetch: (request) => app.fetch(request) }))
|
|
319
|
+
const headers = {
|
|
320
|
+
authorization: `Bearer ${key.token}`,
|
|
321
|
+
'cf-connecting-ip': '203.0.113.7',
|
|
322
|
+
'tempo-mcp-client-ip': '192.0.2.1',
|
|
323
|
+
'x-real-ip': '198.51.100.9',
|
|
324
|
+
}
|
|
325
|
+
await initialize(app, headers)
|
|
326
|
+
|
|
327
|
+
const result = await generatedToolCall(app, 'v1_tokens_get', { verified: true }, headers)
|
|
328
|
+
|
|
329
|
+
expect(result.isError, JSON.stringify(result.content)).toBeFalsy()
|
|
330
|
+
})
|
|
331
|
+
|
|
249
332
|
test('proxies docs tool calls to the remote MCP source', async () => {
|
|
250
333
|
const { host } = createHost({ docs: docsStub() })
|
|
251
334
|
await initialize(host)
|
package/src/apps/mcp.ts
CHANGED
|
@@ -16,6 +16,9 @@ const routesTagGroup = 'Routes API'
|
|
|
16
16
|
/** Tags inside the group hidden from MCP: partner-shaped CoinGecko mirrors and the MCP endpoint itself. */
|
|
17
17
|
const excludedTags = ['CoinGecko', 'MCP']
|
|
18
18
|
|
|
19
|
+
/** Internal header carrying the trusted caller identity through incur's generated request. */
|
|
20
|
+
const clientIpHeader = 'tempo-mcp-client-ip'
|
|
21
|
+
|
|
19
22
|
/** Usage guidance surfaced to MCP clients on initialize. */
|
|
20
23
|
const instructions =
|
|
21
24
|
"Tempo MCP provides access to the Tempo API's data and Routes domains, plus documentation. Authenticated tools accept a Tempo API key sent as an `Authorization: Bearer` header on the HTTP request. List endpoints paginate via `cursor`/`nextCursor`. `docs_*` tools search the Tempo documentation."
|
|
@@ -106,7 +109,11 @@ export function mcp(options: mcp.Options) {
|
|
|
106
109
|
// them onto the caller origin and dispatch in-process.
|
|
107
110
|
fetch: (request) => {
|
|
108
111
|
const url = new URL(request.url)
|
|
109
|
-
|
|
112
|
+
const address = request.headers.get(clientIpHeader)
|
|
113
|
+
const forwarded = new Request(new URL(url.pathname + url.search, origin), request)
|
|
114
|
+
forwarded.headers.delete(clientIpHeader)
|
|
115
|
+
if (address) Auth.trustClientIp(forwarded, address)
|
|
116
|
+
return fetch(forwarded)
|
|
110
117
|
},
|
|
111
118
|
mcp: { instructions, title },
|
|
112
119
|
openapi: scope(document),
|
|
@@ -115,7 +122,7 @@ export function mcp(options: mcp.Options) {
|
|
|
115
122
|
// forwarded `Authorization` header).
|
|
116
123
|
openapiConfig: {
|
|
117
124
|
compact: true,
|
|
118
|
-
forwardHeaders: ['authorization'],
|
|
125
|
+
forwardHeaders: ['authorization', clientIpHeader],
|
|
119
126
|
mode: 'namespace',
|
|
120
127
|
security: false,
|
|
121
128
|
},
|
|
@@ -130,7 +137,12 @@ export function mcp(options: mcp.Options) {
|
|
|
130
137
|
const cli = await resolve(new URL(c.req.url).origin)
|
|
131
138
|
// incur routes on the first path segment; pin the path to `/mcp` so a
|
|
132
139
|
// mount prefix never leaks into its router.
|
|
133
|
-
|
|
140
|
+
const request = new Request(new URL('/mcp', c.req.url), c.req.raw)
|
|
141
|
+
// Replace caller input with the identity resolved by the outer auth boundary.
|
|
142
|
+
request.headers.delete(clientIpHeader)
|
|
143
|
+
const address = Auth.getTrustedClientIp(c)
|
|
144
|
+
if (address) request.headers.set(clientIpHeader, address)
|
|
145
|
+
return cli.fetch(request)
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
// The documented POST carries the auth policy (described routes are
|
|
@@ -43,8 +43,19 @@ describe('chainId', () => {
|
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
describe('requiresFeePayer', () => {
|
|
46
|
-
test(
|
|
47
|
-
|
|
46
|
+
test.each([
|
|
47
|
+
['canonical', { methodDetails: { feePayer: true } }],
|
|
48
|
+
['pre-normalized', { feePayer: true }],
|
|
49
|
+
])('recognizes %s sponsorship', (_, request) => {
|
|
50
|
+
expect(
|
|
51
|
+
Policy.requiresFeePayer({
|
|
52
|
+
...input,
|
|
53
|
+
challenge: { ...input.challenge, request },
|
|
54
|
+
}),
|
|
55
|
+
).toBe(true)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('lets an explicit top-level value disable sponsorship', () => {
|
|
48
59
|
expect(
|
|
49
60
|
Policy.requiresFeePayer({
|
|
50
61
|
...input,
|
|
@@ -84,6 +95,42 @@ describe('assertChainAccess', () => {
|
|
|
84
95
|
})
|
|
85
96
|
|
|
86
97
|
describe('authorizeFeePayer', () => {
|
|
98
|
+
test('rejects pre-normalized sandbox sponsorship on mainnet', async () => {
|
|
99
|
+
await expect(
|
|
100
|
+
Policy.authorizeFeePayer({
|
|
101
|
+
chainId: 4217,
|
|
102
|
+
db: TestApp.database(),
|
|
103
|
+
feePayer,
|
|
104
|
+
input: {
|
|
105
|
+
...input,
|
|
106
|
+
challenge: { ...input.challenge, request: { feePayer: true } },
|
|
107
|
+
},
|
|
108
|
+
principal: { ...principal, environment: 'sandbox' },
|
|
109
|
+
zones,
|
|
110
|
+
}),
|
|
111
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
112
|
+
`[Mpp.Policy.PolicyDeniedError: Mainnet fee sponsorship requires a production API key.]`,
|
|
113
|
+
)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('requires active billing for pre-normalized mainnet sponsorship', async () => {
|
|
117
|
+
await expect(
|
|
118
|
+
Policy.authorizeFeePayer({
|
|
119
|
+
chainId: 4217,
|
|
120
|
+
db: TestApp.database(),
|
|
121
|
+
feePayer,
|
|
122
|
+
input: {
|
|
123
|
+
...input,
|
|
124
|
+
challenge: { ...input.challenge, request: { feePayer: true } },
|
|
125
|
+
},
|
|
126
|
+
principal: principal_projectless,
|
|
127
|
+
zones,
|
|
128
|
+
}),
|
|
129
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
130
|
+
`[Mpp.Policy.PolicyDeniedError: Active billing is required for mainnet fee sponsorship.]`,
|
|
131
|
+
)
|
|
132
|
+
})
|
|
133
|
+
|
|
87
134
|
test.each([4217, Zones.zoneMainnetInternal.id, Zones.zoneDeel.id])(
|
|
88
135
|
'rejects sandbox sponsorship on chain %s',
|
|
89
136
|
async (chainId) => {
|
|
@@ -165,7 +212,7 @@ describe('authorizeFeePayer', () => {
|
|
|
165
212
|
},
|
|
166
213
|
)
|
|
167
214
|
|
|
168
|
-
test('
|
|
215
|
+
test('withholds the managed fee payer from self-funded credentials', async () => {
|
|
169
216
|
await expect(
|
|
170
217
|
Policy.authorizeFeePayer({
|
|
171
218
|
chainId: 4217,
|
|
@@ -178,6 +225,6 @@ describe('authorizeFeePayer', () => {
|
|
|
178
225
|
principal,
|
|
179
226
|
zones,
|
|
180
227
|
}),
|
|
181
|
-
).resolves.
|
|
228
|
+
).resolves.toBeUndefined()
|
|
182
229
|
})
|
|
183
230
|
})
|
|
@@ -18,7 +18,11 @@ export function chainId(input: Mpp.RelayInput): number | undefined {
|
|
|
18
18
|
/** Whether a Tempo charge credential requests platform fee sponsorship. */
|
|
19
19
|
export function requiresFeePayer(input: Mpp.RelayInput) {
|
|
20
20
|
const request = input.challenge.request
|
|
21
|
-
|
|
21
|
+
const details = record(request['methodDetails'])
|
|
22
|
+
return (
|
|
23
|
+
(details?.['feePayer'] === true || request['feePayer'] === true) &&
|
|
24
|
+
request['feePayer'] !== false
|
|
25
|
+
)
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
/** Refuses a sponsored transaction that the current fee market cannot admit. */
|
|
@@ -80,7 +84,7 @@ export async function authorizeFeePayer(
|
|
|
80
84
|
options: authorizeFeePayer.Options,
|
|
81
85
|
): Promise<LocalAccount | undefined> {
|
|
82
86
|
const { chainId, db, feePayer, input, principal, zones } = options
|
|
83
|
-
if (!feePayer || !requiresFeePayer(input)) return
|
|
87
|
+
if (!feePayer || !requiresFeePayer(input)) return undefined
|
|
84
88
|
if (principal?.type !== 'api_key')
|
|
85
89
|
throw new PolicyDeniedError('Fee sponsorship requires an API key.')
|
|
86
90
|
if (!Viem.isMainnet(zones.get(chainId)?.sourceId ?? chainId)) return feePayer
|
|
@@ -3,6 +3,7 @@ import { SignatureEnvelope, TxEnvelopeTempo } from 'ox/tempo'
|
|
|
3
3
|
|
|
4
4
|
import * as TestApp from '../../../../test/App.js'
|
|
5
5
|
import * as Tempo from '../../../../test/Tempo.js'
|
|
6
|
+
import * as ApiKeyOwnerTombstones from '../../../db/tables/apiKeyOwnerTombstones.js'
|
|
6
7
|
import * as BillingSettings from '../../../db/tables/billingSettings.js'
|
|
7
8
|
import * as SponsoredTransactions from '../../../db/tables/sponsoredTransactions.js'
|
|
8
9
|
import type * as Auth from '../../../internal/Auth.js'
|
|
@@ -35,6 +36,34 @@ const token = {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
describe('record', () => {
|
|
39
|
+
test.each([undefined, '1.00'])(
|
|
40
|
+
'rejects a deleted owner with spend limit %s',
|
|
41
|
+
async (spendLimit) => {
|
|
42
|
+
const db = TestApp.database()
|
|
43
|
+
const chainId = Zones.zoneDeel.id
|
|
44
|
+
await VerifiedTokens.replace(db, chainId, [token])
|
|
45
|
+
if (spendLimit !== undefined)
|
|
46
|
+
await BillingSettings.upsert(db, { orgId: principal.orgId, spendLimit })
|
|
47
|
+
await db.transaction((tx) =>
|
|
48
|
+
ApiKeyOwnerTombstones.markDeleted(tx, { orgId: principal.orgId }),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
await expect(
|
|
52
|
+
Sponsorship.record({
|
|
53
|
+
db,
|
|
54
|
+
dbCached: db,
|
|
55
|
+
principal,
|
|
56
|
+
serializedTransaction: await transaction({ chainId }),
|
|
57
|
+
txFeeLimit: 1_000_000n,
|
|
58
|
+
zones,
|
|
59
|
+
}),
|
|
60
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
61
|
+
`[Mpp.Policy.PolicyDeniedError: Organization no longer exists.]`,
|
|
62
|
+
)
|
|
63
|
+
expect(await SponsoredTransactions.listPending(db)).toMatchInlineSnapshot(`[]`)
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
|
|
38
67
|
test.each(mainnetChainIds)(
|
|
39
68
|
'records chain %s as billable and eligible for metering',
|
|
40
69
|
async (chainId) => {
|
|
@@ -114,17 +114,19 @@ export async function record(options: record.Options): Promise<void> {
|
|
|
114
114
|
transaction: serializedTransaction,
|
|
115
115
|
transactionHash: Hash.keccak256(serializedTransaction),
|
|
116
116
|
}
|
|
117
|
-
if (settings?.spendLimit == null) {
|
|
118
|
-
await SponsoredTransactions.upsert(db, input)
|
|
119
|
-
return
|
|
120
|
-
}
|
|
121
117
|
try {
|
|
118
|
+
if (settings?.spendLimit == null) {
|
|
119
|
+
await SponsoredTransactions.upsert(db, input)
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
122
|
await SponsoredTransactions.reserve(db, input, {
|
|
123
123
|
chainIds: Zones.chainIds({ sourceId: Viem.chainId.mainnet, zones: zones.values() }),
|
|
124
124
|
max: Billing.toBaseUnits(settings.spendLimit),
|
|
125
125
|
since: Billing.periodStart(settings.period),
|
|
126
126
|
})
|
|
127
127
|
} catch (cause) {
|
|
128
|
+
if (cause instanceof SponsoredTransactions.OrganizationDeletedError)
|
|
129
|
+
throw new Policy.PolicyDeniedError('Organization no longer exists.')
|
|
128
130
|
if (cause instanceof SponsoredTransactions.PeriodSpendLimitError)
|
|
129
131
|
throw new Policy.PolicyDeniedError('Spend limit exceeded.')
|
|
130
132
|
throw cause
|