tapimo 0.15.1 → 0.18.1
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 +893 -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 +70 -70
- 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 +529 -76
- 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 +157 -157
- 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 +205 -201
- 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 +357 -357
- 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/blocks.d.ts +125 -125
- 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 +109 -127
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +83 -54
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +43 -43
- package/dist/apps/data/routes/receipts.d.ts +235 -235
- package/dist/apps/data/routes/rpc.d.ts +30 -30
- 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 +77 -77
- package/dist/apps/data/routes/valuation.d.ts +32 -32
- package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +1 -1
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +31 -31
- package/dist/apps/management/App.d.ts +2909 -2064
- 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 +257 -245
- 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 +138 -138
- package/dist/apps/management/routes/invite-links.d.ts +172 -172
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +104 -104
- 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 +125 -125
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +86 -86
- package/dist/apps/management/routes/webhooks.d.ts +485 -485
- package/dist/apps/mpp/App.d.ts +44 -44
- 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/chains.d.ts +25 -25
- 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 +171 -81
- 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 +532 -480
- 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 +413 -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/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 +57 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +182 -78
- 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 +3 -0
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +352 -41
- 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/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/routeTree.gen.ts +21 -0
- 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 +1 -0
- 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 +1 -0
- package/src/admin/ui.generated.ts +258 -202
- 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/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 +134 -2
- package/src/apps/data/routes/fee-amm.ts +122 -60
- package/src/apps/data/routes/receipts.test.ts +21 -18
- package/src/apps/data/routes/rpc.test.ts +2 -2
- 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.test.ts +12 -3
- package/src/apps/data/routes/webhooks.ts +2 -1
- 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/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 +498 -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 +66 -5
- 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/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 +291 -8
- package/src/internal/Auth.ts +227 -96
- 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 +1263 -41
- package/src/internal/routes/providers/relay.ts +423 -38
- 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}'`)
|
|
@@ -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
|
|
@@ -5,7 +5,7 @@ import { Hash, Hex, Secp256k1 } from 'ox'
|
|
|
5
5
|
import { ZoneRpcAuthentication } from 'ox/tempo'
|
|
6
6
|
import { createClient, http } from 'viem'
|
|
7
7
|
import { prepareTransactionRequest, sendRawTransactionSync, signTransaction } from 'viem/actions'
|
|
8
|
-
import { Account as TempoAccount, Actions, Transaction, withRelay } from 'viem/tempo'
|
|
8
|
+
import { Account as TempoAccount, Actions, Addresses, Transaction, withRelay } from 'viem/tempo'
|
|
9
9
|
|
|
10
10
|
import * as TestApp from '../../../test/App.js'
|
|
11
11
|
import * as Containers from '../../../test/containers.js'
|
|
@@ -25,6 +25,7 @@ import * as SponsoredTransactions from '../../db/tables/sponsoredTransactions.js
|
|
|
25
25
|
import * as StripeCustomers from '../../db/tables/stripeCustomers.js'
|
|
26
26
|
import * as core_Billing from '../management/Billing.js'
|
|
27
27
|
import * as RequestListener from '../../handlers/internal/requestListener.js'
|
|
28
|
+
import * as Store from '../../internal/Store.js'
|
|
28
29
|
import * as Tidx from '../../internal/Tidx.js'
|
|
29
30
|
import * as Viem from '../../internal/Viem.js'
|
|
30
31
|
import * as Sponsorships from './Sponsorships.js'
|
|
@@ -125,6 +126,36 @@ const keys = [
|
|
|
125
126
|
},
|
|
126
127
|
] as const satisfies readonly TestApp.kvStore.Key[]
|
|
127
128
|
|
|
129
|
+
describe('behavior: multisig coordination', () => {
|
|
130
|
+
test('uses configured state and reports coordinator failures', async () => {
|
|
131
|
+
const entries: Log.Entry[] = []
|
|
132
|
+
const store = Store.memory()
|
|
133
|
+
const app = TestApp.create({
|
|
134
|
+
auth: { keys },
|
|
135
|
+
logger: (entry) => void entries.push(entry),
|
|
136
|
+
relay: { multisig: { store } },
|
|
137
|
+
})
|
|
138
|
+
const hash = Hex.random(32)
|
|
139
|
+
const request = async () => {
|
|
140
|
+
const response = await app.request('/rpc/relay', {
|
|
141
|
+
body: JSON.stringify({
|
|
142
|
+
id: 1,
|
|
143
|
+
jsonrpc: '2.0',
|
|
144
|
+
method: 'multisig_getOperation',
|
|
145
|
+
params: [hash],
|
|
146
|
+
}),
|
|
147
|
+
headers: { 'content-type': 'application/json', 'tempo-api-key': 'secret_unscoped' },
|
|
148
|
+
method: 'POST',
|
|
149
|
+
})
|
|
150
|
+
return response.json()
|
|
151
|
+
}
|
|
152
|
+
expect(await request()).toMatchObject({ result: null })
|
|
153
|
+
await store.put(`multisig:v2:multisig:operation:${hash}`, 'invalid')
|
|
154
|
+
expect(await request()).toMatchObject({ error: { code: -32603 } })
|
|
155
|
+
expect(entries.at(-1)?.rpc).toMatchObject({ serverErrors: 1 })
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
|
|
128
159
|
describe('behavior: Zone chain routing', () => {
|
|
129
160
|
const zoneSelectors = [
|
|
130
161
|
['relay', 'path'],
|
|
@@ -712,6 +743,8 @@ describe.skipIf(runtime.mode !== 'localnet')('behavior: sponsorship', () => {
|
|
|
712
743
|
"finalizationAttemptedAt": null,
|
|
713
744
|
"finalizedAt": null,
|
|
714
745
|
"id": "<id>",
|
|
746
|
+
"meterEventFirstAttemptedAt": null,
|
|
747
|
+
"meterReportAttemptedAt": null,
|
|
715
748
|
"meterReportedAt": null,
|
|
716
749
|
"orgId": "org_1",
|
|
717
750
|
"projectId": "prj_1",
|
|
@@ -720,6 +753,7 @@ describe.skipIf(runtime.mode !== 'localnet')('behavior: sponsorship', () => {
|
|
|
720
753
|
"status": "pending",
|
|
721
754
|
"transaction": "<hex>",
|
|
722
755
|
"transactionHash": "<hash>",
|
|
756
|
+
"transactionHashReconciled": false,
|
|
723
757
|
}
|
|
724
758
|
`)
|
|
725
759
|
})
|
|
@@ -1239,6 +1273,56 @@ describe('behavior: mainnet billing gate', () => {
|
|
|
1239
1273
|
await TestApp.verifiedSeed(db, Viem.chainId.mainnet)
|
|
1240
1274
|
}
|
|
1241
1275
|
|
|
1276
|
+
test('behavior: uses the same sponsor fee token for each authenticated organization', async () => {
|
|
1277
|
+
const db = TestApp.database()
|
|
1278
|
+
const ousd = '0x20c0000000000000000000006a37DA5C996874BE'
|
|
1279
|
+
await activate(db, 'org_1')
|
|
1280
|
+
await activate(db, 'org_2')
|
|
1281
|
+
await TestApp.verifiedSeed(db, Viem.chainId.mainnet, {
|
|
1282
|
+
tokens: [Addresses.pathUsd, ousd].map((address) => ({
|
|
1283
|
+
address,
|
|
1284
|
+
currency: 'USD',
|
|
1285
|
+
decimals: 6,
|
|
1286
|
+
name: address === ousd ? 'OUSD' : 'pathUSD',
|
|
1287
|
+
symbol: address === ousd ? 'OUSD' : 'pathUSD',
|
|
1288
|
+
})),
|
|
1289
|
+
})
|
|
1290
|
+
const app = TestApp.create({
|
|
1291
|
+
auth: { keys },
|
|
1292
|
+
db,
|
|
1293
|
+
relay: {
|
|
1294
|
+
feePayer: {
|
|
1295
|
+
account: feePayerAccount,
|
|
1296
|
+
resolveFeeToken: ({ chainId }) => {
|
|
1297
|
+
expect(chainId).toBe(Viem.chainId.mainnet)
|
|
1298
|
+
return ousd
|
|
1299
|
+
},
|
|
1300
|
+
},
|
|
1301
|
+
},
|
|
1302
|
+
supportedChainIds: [Viem.chainId.mainnet],
|
|
1303
|
+
})
|
|
1304
|
+
|
|
1305
|
+
for (const [nonce, { orgId, token }] of [
|
|
1306
|
+
{ orgId: 'org_1', token: 'secret_sponsor_prod' },
|
|
1307
|
+
{ orgId: 'org_2', token: 'secret_wildcard_prod' },
|
|
1308
|
+
{ orgId: 'org_1', token: 'secret_sponsor_prod' },
|
|
1309
|
+
].entries()) {
|
|
1310
|
+
const body = await relayRequest(app, {
|
|
1311
|
+
method: 'eth_signRawTransaction',
|
|
1312
|
+
params: [await signSponsorable({ chainId: Viem.chainId.mainnet, nonce })],
|
|
1313
|
+
token,
|
|
1314
|
+
})
|
|
1315
|
+
expect(body.error).toBeUndefined()
|
|
1316
|
+
const signed = Transaction.deserialize(body.result as `0x76${string}`)
|
|
1317
|
+
expect(signed.feeToken?.toString().toLowerCase()).toBe(ousd.toLowerCase())
|
|
1318
|
+
const row = (await SponsoredTransactions.listPending(db)).find(
|
|
1319
|
+
(row) => row.transactionHash === Hash.keccak256(body.result!),
|
|
1320
|
+
)
|
|
1321
|
+
expect(row?.orgId).toBe(orgId)
|
|
1322
|
+
expect(row?.feeToken?.toLowerCase()).toBe(ousd.toLowerCase())
|
|
1323
|
+
}
|
|
1324
|
+
})
|
|
1325
|
+
|
|
1242
1326
|
/** Configures one attributed project for Tempo-funded sponsorship. */
|
|
1243
1327
|
async function configureSubsidy(db: ReturnType<typeof TestApp.database>) {
|
|
1244
1328
|
await Organizations.create(db, { id: 'org_1', name: 'Privy' })
|
package/src/apps/relay/App.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Hono } from 'hono'
|
|
|
2
2
|
import { createMiddleware } from 'hono/factory'
|
|
3
3
|
import { Hash, Hex, RpcResponse } from 'ox'
|
|
4
4
|
import { ZoneRpcAuthentication } from 'ox/tempo'
|
|
5
|
+
import type { Address } from 'viem'
|
|
5
6
|
import { Addresses, TokenId, Transaction } from 'viem/tempo'
|
|
6
7
|
|
|
7
8
|
import type * as App from '../../App.js'
|
|
@@ -75,10 +76,19 @@ export declare namespace relay {
|
|
|
75
76
|
NonNullable<Handler.relay.Options['feePayer']>,
|
|
76
77
|
'account' | 'feeToken' | 'name' | 'url'
|
|
77
78
|
> & {
|
|
79
|
+
/** Resolves the sponsor's fee token using the transaction chain. */
|
|
80
|
+
resolveFeeToken?:
|
|
81
|
+
| ((options: {
|
|
82
|
+
/** Transaction chain id. */
|
|
83
|
+
chainId: number
|
|
84
|
+
}) => Address | undefined)
|
|
85
|
+
| undefined
|
|
78
86
|
/** Per-transaction fee cap (decimal USD string); orgs tighten it, never loosen. @default '1.00' */
|
|
79
87
|
txFeeLimit?: string | undefined
|
|
80
88
|
})
|
|
81
89
|
| undefined
|
|
90
|
+
/** Native multisig coordination backed by authoritative atomic storage. */
|
|
91
|
+
multisig?: Handler.relay.Options['multisig'] | undefined
|
|
82
92
|
}
|
|
83
93
|
}
|
|
84
94
|
|
|
@@ -151,11 +161,18 @@ function middleware(options: middleware.Options) {
|
|
|
151
161
|
principal?.type === 'api_key' &&
|
|
152
162
|
(principal.apiKey.scopes.includes('rpc-relay:sponsor') ||
|
|
153
163
|
principal.apiKey.scopes.includes(Scope.wildcard))
|
|
154
|
-
//
|
|
155
|
-
|
|
164
|
+
// Resolve against the transaction chain because one app serves mainnet,
|
|
165
|
+
// testnet, and hosted Zones concurrently.
|
|
166
|
+
const feeToken_sponsor = (chainId: number) => {
|
|
167
|
+
return (
|
|
168
|
+
options.feePayer?.resolveFeeToken?.({ chainId }) ??
|
|
169
|
+
options.feePayer?.feeToken ??
|
|
170
|
+
Addresses.pathUsd
|
|
171
|
+
)
|
|
172
|
+
}
|
|
156
173
|
return {
|
|
157
174
|
...options.feePayer,
|
|
158
|
-
|
|
175
|
+
resolveFeeToken: feeToken_sponsor,
|
|
159
176
|
validate: async (transaction) => {
|
|
160
177
|
// Allowlist the chains this deployment serves rather than denylisting
|
|
161
178
|
// only mainnet: the relay resolves chainId from the request body, so
|
|
@@ -230,7 +247,7 @@ function middleware(options: middleware.Options) {
|
|
|
230
247
|
}
|
|
231
248
|
const feeToken = (() => {
|
|
232
249
|
try {
|
|
233
|
-
return TokenId.toAddress(transaction.feeToken ?? feeToken_sponsor)
|
|
250
|
+
return TokenId.toAddress(transaction.feeToken ?? feeToken_sponsor(id))
|
|
234
251
|
} catch {
|
|
235
252
|
return undefined
|
|
236
253
|
}
|
|
@@ -388,6 +405,12 @@ function middleware(options: middleware.Options) {
|
|
|
388
405
|
: await SponsoredTransactions.reserve(db, input, billingLimit)
|
|
389
406
|
return { subsidized: !record.billable }
|
|
390
407
|
} catch (error) {
|
|
408
|
+
if (error instanceof SponsoredTransactions.OrganizationDeletedError)
|
|
409
|
+
rejectSponsorship({
|
|
410
|
+
chainId: event.chainId,
|
|
411
|
+
message: 'Organization no longer exists.',
|
|
412
|
+
reason: 'billing_required',
|
|
413
|
+
})
|
|
391
414
|
if (error instanceof SponsoredTransactions.AttributionConflictError)
|
|
392
415
|
rejectSponsorship({
|
|
393
416
|
chainId: event.chainId,
|
|
@@ -466,6 +489,7 @@ function middleware(options: middleware.Options) {
|
|
|
466
489
|
cache: c.get('store'),
|
|
467
490
|
...(options.features ? { features: options.features } : {}),
|
|
468
491
|
getClient,
|
|
492
|
+
...(options.multisig ? { multisig: options.multisig } : {}),
|
|
469
493
|
onRequest: async (request) => {
|
|
470
494
|
const method = sponsorshipMethod(request.method)
|
|
471
495
|
const params = 'params' in request && Array.isArray(request.params) ? request.params : []
|
|
@@ -339,6 +339,29 @@ describe('reconcile', () => {
|
|
|
339
339
|
await db.close()
|
|
340
340
|
})
|
|
341
341
|
|
|
342
|
+
test('behavior: replaces an unresolved recorded hash by sign payload', async () => {
|
|
343
|
+
const db = create()
|
|
344
|
+
await db.migrate()
|
|
345
|
+
const sponsorship = await SponsoredTransactions.upsert(db, {
|
|
346
|
+
...input,
|
|
347
|
+
signPayload,
|
|
348
|
+
transactionHash: `0x${'cc'.repeat(32)}`,
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
const result = await Sponsorships.reconcile(db, {
|
|
352
|
+
feePayer: '0xFee0000000000000000000000000000000000000',
|
|
353
|
+
getClient: () => rpc,
|
|
354
|
+
getTidx: () => tidx([{ from: sender, hash: minedHash }]),
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
expect(result).toMatchObject({ matched: 1 })
|
|
358
|
+
expect(await SponsoredTransactions.get(db, sponsorship.id)).toMatchObject({
|
|
359
|
+
status: 'pending',
|
|
360
|
+
transactionHash: minedHash,
|
|
361
|
+
})
|
|
362
|
+
await db.close()
|
|
363
|
+
})
|
|
364
|
+
|
|
342
365
|
test('behavior: recovers recently failed intents by sign payload', async () => {
|
|
343
366
|
const db = create()
|
|
344
367
|
await db.migrate()
|
|
@@ -373,6 +396,44 @@ describe('reconcile', () => {
|
|
|
373
396
|
await db.close()
|
|
374
397
|
})
|
|
375
398
|
|
|
399
|
+
test('behavior: recovers a failed recorded hash by sign payload without duplicating spend', async () => {
|
|
400
|
+
const db = create()
|
|
401
|
+
await db.migrate()
|
|
402
|
+
await Organizations.create(db, { id: 'org_1', name: 'One' })
|
|
403
|
+
const recordedHash = `0x${'cc'.repeat(32)}`
|
|
404
|
+
const sponsorship = await SponsoredTransactions.upsert(db, {
|
|
405
|
+
...input,
|
|
406
|
+
signPayload,
|
|
407
|
+
transactionHash: recordedHash,
|
|
408
|
+
})
|
|
409
|
+
await SponsoredTransactions.fail(db, sponsorship.id, '2026-01-01T00:00:00.000Z')
|
|
410
|
+
|
|
411
|
+
vi.useFakeTimers({ now: new Date('2026-01-01T00:01:00.000Z') })
|
|
412
|
+
try {
|
|
413
|
+
const options = {
|
|
414
|
+
feePayer: '0xFee0000000000000000000000000000000000000' as const,
|
|
415
|
+
getClient: () => rpc,
|
|
416
|
+
getTidx: () => tidx([{ block_num: 1, from: sender, hash: minedHash, idx: 0 }]),
|
|
417
|
+
}
|
|
418
|
+
expect(await Sponsorships.reconcile(db, options)).toMatchObject({ matched: 1 })
|
|
419
|
+
expect(
|
|
420
|
+
await Sponsorships.finalize(db, {
|
|
421
|
+
getClient: () => client({ [minedHash]: { effectiveGasPrice: '0x3', gasUsed: '0x5208' } }),
|
|
422
|
+
}),
|
|
423
|
+
).toMatchObject({ finalized: 1 })
|
|
424
|
+
expect(await Sponsorships.reconcile(db, options)).toMatchObject({ matched: 0 })
|
|
425
|
+
} finally {
|
|
426
|
+
vi.useRealTimers()
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
expect(await SponsoredTransactions.get(db, sponsorship.id)).toMatchObject({
|
|
430
|
+
status: 'finalized',
|
|
431
|
+
transactionHash: minedHash,
|
|
432
|
+
})
|
|
433
|
+
expect(await SponsoredTransactions.list(db, { limit: 10 })).toHaveLength(1)
|
|
434
|
+
await db.close()
|
|
435
|
+
})
|
|
436
|
+
|
|
376
437
|
test('behavior: spend-limit refusals are not operational errors', async () => {
|
|
377
438
|
const db = create()
|
|
378
439
|
await db.migrate()
|
|
@@ -460,6 +521,41 @@ describe('reconcile', () => {
|
|
|
460
521
|
await db.close()
|
|
461
522
|
})
|
|
462
523
|
|
|
524
|
+
test('behavior: scans fill intents and submitted hashes from independent windows', async () => {
|
|
525
|
+
const db = create()
|
|
526
|
+
await db.migrate()
|
|
527
|
+
vi.useFakeTimers({ now: new Date('2026-01-01T00:00:00.000Z') })
|
|
528
|
+
try {
|
|
529
|
+
await SponsoredTransactions.upsert(db, {
|
|
530
|
+
...input,
|
|
531
|
+
signPayload: `0x${'ee'.repeat(32)}`,
|
|
532
|
+
})
|
|
533
|
+
vi.setSystemTime(new Date('2026-01-01T01:00:00.000Z'))
|
|
534
|
+
const { transactionHash: _, ...intent } = input
|
|
535
|
+
await SponsoredTransactions.upsert(db, { ...intent, signPayload })
|
|
536
|
+
const queries: string[] = []
|
|
537
|
+
|
|
538
|
+
await Sponsorships.reconcile(db, {
|
|
539
|
+
feePayer: '0xFee0000000000000000000000000000000000000',
|
|
540
|
+
getClient: () => rpc,
|
|
541
|
+
getTidx: () =>
|
|
542
|
+
({
|
|
543
|
+
fetch: async (options: { query: string }) => {
|
|
544
|
+
queries.push(options.query)
|
|
545
|
+
return { rows: [] }
|
|
546
|
+
},
|
|
547
|
+
}) as never,
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
expect(queries).toHaveLength(2)
|
|
551
|
+
expect(queries[0]).toContain("block_timestamp >= '2026-01-01 00:58:00'")
|
|
552
|
+
expect(queries[1]).toContain("block_timestamp >= '2025-12-31 23:58:00'")
|
|
553
|
+
} finally {
|
|
554
|
+
vi.useRealTimers()
|
|
555
|
+
await db.close()
|
|
556
|
+
}
|
|
557
|
+
})
|
|
558
|
+
|
|
463
559
|
test('behavior: an indexer error leaves intents for the next pass', async () => {
|
|
464
560
|
const db = create()
|
|
465
561
|
await db.migrate()
|
|
@@ -483,7 +579,7 @@ describe('reconcile', () => {
|
|
|
483
579
|
"scanned": 0,
|
|
484
580
|
}
|
|
485
581
|
`)
|
|
486
|
-
expect(await SponsoredTransactions.
|
|
582
|
+
expect(await SponsoredTransactions.listReconciliationCandidates(db)).toHaveLength(1)
|
|
487
583
|
await db.close()
|
|
488
584
|
})
|
|
489
585
|
})
|