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,5 +1,5 @@
|
|
|
1
1
|
import { nanoid } from 'nanoid'
|
|
2
|
-
import
|
|
2
|
+
import Stripe from 'stripe'
|
|
3
3
|
|
|
4
4
|
import * as Runtime from '../../../test/runtime.js'
|
|
5
5
|
import * as ApiKeys from '../../ApiKeys.js'
|
|
@@ -33,16 +33,23 @@ const input = {
|
|
|
33
33
|
/** Inserts and finalizes one billable row; `seed` derives a unique sign payload. */
|
|
34
34
|
async function finalized(
|
|
35
35
|
db: Db.Db,
|
|
36
|
-
options: {
|
|
36
|
+
options: {
|
|
37
|
+
chainId?: number
|
|
38
|
+
feeAmount: string
|
|
39
|
+
finalizedAt?: string
|
|
40
|
+
orgId?: string
|
|
41
|
+
seed: string
|
|
42
|
+
},
|
|
37
43
|
): Promise<SponsoredTransactions.Record> {
|
|
38
44
|
const row = await SponsoredTransactions.upsert(db, {
|
|
39
45
|
...input,
|
|
46
|
+
...(options.chainId === undefined ? {} : { chainId: options.chainId }),
|
|
40
47
|
...(options.orgId ? { orgId: options.orgId } : {}),
|
|
41
48
|
signPayload: `0x${options.seed.repeat(32)}`,
|
|
42
49
|
})
|
|
43
50
|
await SponsoredTransactions.finalize(db, row.id, {
|
|
44
51
|
feeAmount: options.feeAmount,
|
|
45
|
-
finalizedAt: new Date().toISOString(),
|
|
52
|
+
finalizedAt: options.finalizedAt ?? new Date().toISOString(),
|
|
46
53
|
})
|
|
47
54
|
return row
|
|
48
55
|
}
|
|
@@ -178,6 +185,7 @@ type StubSubscription = {
|
|
|
178
185
|
* item/subscription creation are captured for assertions.
|
|
179
186
|
*/
|
|
180
187
|
function stubStripe(options: {
|
|
188
|
+
createdAt?: number | undefined
|
|
181
189
|
meterEvent?: ((params: { identifier: string }) => void) | undefined
|
|
182
190
|
subscriptions?: readonly StubSubscription[] | undefined
|
|
183
191
|
subscriptionsList?: (() => Promise<void>) | undefined
|
|
@@ -239,7 +247,7 @@ function stubStripe(options: {
|
|
|
239
247
|
subscriptionItems: {
|
|
240
248
|
create: async (params: { price: string; subscription: string }) => {
|
|
241
249
|
itemsCreated.push(params)
|
|
242
|
-
return { created: Math.floor(Date.now() / 1_000) }
|
|
250
|
+
return { created: options.createdAt ?? Math.floor(Date.now() / 1_000) }
|
|
243
251
|
},
|
|
244
252
|
},
|
|
245
253
|
subscriptions: {
|
|
@@ -248,7 +256,7 @@ function stubStripe(options: {
|
|
|
248
256
|
return {
|
|
249
257
|
items: {
|
|
250
258
|
data: params.items.map(({ price }) => ({
|
|
251
|
-
created: Math.floor(Date.now() / 1_000),
|
|
259
|
+
created: options.createdAt ?? Math.floor(Date.now() / 1_000),
|
|
252
260
|
price: { id: price },
|
|
253
261
|
})),
|
|
254
262
|
},
|
|
@@ -315,6 +323,89 @@ describe('status', () => {
|
|
|
315
323
|
})
|
|
316
324
|
|
|
317
325
|
describe('createReporter', () => {
|
|
326
|
+
test('retries an explicitly rejected Stripe event after its configuration is corrected', async () => {
|
|
327
|
+
const db = create()
|
|
328
|
+
await db.migrate()
|
|
329
|
+
await StripeCustomers.create(db, { orgId: 'org_1', stripeCustomerId: 'cus_1' })
|
|
330
|
+
const row = await finalized(db, { feeAmount: '100000', seed: '42' })
|
|
331
|
+
let reject = true
|
|
332
|
+
const { meterEvents, stripe } = stubStripe({
|
|
333
|
+
meterEvent: () => {
|
|
334
|
+
if (reject)
|
|
335
|
+
throw new Stripe.errors.StripeInvalidRequestError({
|
|
336
|
+
message: 'Meter configuration is invalid.',
|
|
337
|
+
statusCode: 400,
|
|
338
|
+
type: 'invalid_request_error',
|
|
339
|
+
})
|
|
340
|
+
},
|
|
341
|
+
subscriptions: [{ items: ['feePayerSpend', 'apiRequests'], status: 'active' }],
|
|
342
|
+
})
|
|
343
|
+
const reporter = Billing.createReporter({ db, stripe })
|
|
344
|
+
expect(await reporter.tick()).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
345
|
+
expect((await SponsoredTransactions.get(db, row.id))?.meterEventFirstAttemptedAt).toBeNull()
|
|
346
|
+
|
|
347
|
+
reject = false
|
|
348
|
+
expect(await reporter.tick()).toStrictEqual({ failed: 0, reported: 1, skipped: 0 })
|
|
349
|
+
expect(meterEvents.map(({ identifier }) => identifier)).toStrictEqual([row.id])
|
|
350
|
+
await db.close()
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
test('stops an uncertain Stripe resend after its identifier window', async () => {
|
|
354
|
+
const db = create()
|
|
355
|
+
await db.migrate()
|
|
356
|
+
await StripeCustomers.create(db, { orgId: 'org_1', stripeCustomerId: 'cus_1' })
|
|
357
|
+
const row = await finalized(db, { feeAmount: '100000', seed: '41' })
|
|
358
|
+
await SponsoredTransactions.beginMeterEvent(
|
|
359
|
+
db,
|
|
360
|
+
row.id,
|
|
361
|
+
new Date(Date.now() - 24 * 60 * 60 * 1_000).toISOString(),
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
const { meterEvents, stripe } = stubStripe({
|
|
365
|
+
subscriptions: [{ items: ['feePayerSpend', 'apiRequests'], status: 'active' }],
|
|
366
|
+
})
|
|
367
|
+
expect(await Billing.createReporter({ db, stripe }).tick()).toStrictEqual({
|
|
368
|
+
failed: 1,
|
|
369
|
+
reported: 0,
|
|
370
|
+
skipped: 0,
|
|
371
|
+
})
|
|
372
|
+
expect(meterEvents).toHaveLength(0)
|
|
373
|
+
expect((await SponsoredTransactions.get(db, row.id))?.meterReportedAt).toBeNull()
|
|
374
|
+
await db.close()
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
test('rotates unavailable sponsorships behind healthy rows', async () => {
|
|
378
|
+
const db = create()
|
|
379
|
+
await db.migrate()
|
|
380
|
+
await StripeCustomers.create(db, { orgId: 'org_1', stripeCustomerId: 'cus_1' })
|
|
381
|
+
const unavailable = await finalized(db, {
|
|
382
|
+
feeAmount: '100000',
|
|
383
|
+
finalizedAt: '2026-01-01T00:00:00.000Z',
|
|
384
|
+
orgId: 'org_missing',
|
|
385
|
+
seed: '39',
|
|
386
|
+
})
|
|
387
|
+
const healthy = await finalized(db, {
|
|
388
|
+
chainId: 421700099,
|
|
389
|
+
feeAmount: '250000',
|
|
390
|
+
finalizedAt: '2026-01-02T00:00:00.000Z',
|
|
391
|
+
seed: '40',
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
const { meterEvents, stripe } = stubStripe({
|
|
395
|
+
subscriptions: [{ items: ['feePayerSpend', 'apiRequests'], status: 'active' }],
|
|
396
|
+
})
|
|
397
|
+
const reporter = Billing.createReporter({ batchSize: 1, db, stripe })
|
|
398
|
+
expect(await reporter.tick()).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
399
|
+
expect(await reporter.tick()).toStrictEqual({ failed: 0, reported: 1, skipped: 0 })
|
|
400
|
+
expect(await reporter.tick()).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
401
|
+
expect(meterEvents.map(({ identifier }) => identifier)).toStrictEqual([healthy.id])
|
|
402
|
+
expect(
|
|
403
|
+
(await SponsoredTransactions.get(db, unavailable.id))?.meterEventFirstAttemptedAt,
|
|
404
|
+
).toBeNull()
|
|
405
|
+
expect((await SponsoredTransactions.get(db, unavailable.id))?.meterReportedAt).toBeNull()
|
|
406
|
+
await db.close()
|
|
407
|
+
})
|
|
408
|
+
|
|
318
409
|
test('behavior: a poisoned row never stalls the queue', async () => {
|
|
319
410
|
const db = create()
|
|
320
411
|
await db.migrate()
|
|
@@ -387,6 +478,7 @@ describe('createReporter', () => {
|
|
|
387
478
|
skipped: 0,
|
|
388
479
|
})
|
|
389
480
|
expect((await SponsoredTransactions.get(db, row.id))?.meterReportedAt).not.toBeNull()
|
|
481
|
+
expect((await SponsoredTransactions.get(db, row.id))?.meterEventFirstAttemptedAt).not.toBeNull()
|
|
390
482
|
expect(await Billing.createReporter({ db, stripe }).tick()).toStrictEqual({
|
|
391
483
|
failed: 0,
|
|
392
484
|
reported: 0,
|
|
@@ -395,24 +487,35 @@ describe('createReporter', () => {
|
|
|
395
487
|
await db.close()
|
|
396
488
|
})
|
|
397
489
|
|
|
398
|
-
test('
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
490
|
+
test.each(['canceled', 'missing'] as const)(
|
|
491
|
+
'behavior: retains sponsorship liability for %s customers',
|
|
492
|
+
async (status) => {
|
|
493
|
+
const db = create()
|
|
494
|
+
await db.migrate()
|
|
495
|
+
if (status === 'canceled') {
|
|
496
|
+
await StripeCustomers.create(db, { orgId: 'org_1', stripeCustomerId: 'cus_1' })
|
|
497
|
+
await StripeCustomers.setStatus(db, 'org_1', 'canceled')
|
|
498
|
+
}
|
|
499
|
+
const row = await finalized(db, { feeAmount: '100000', seed: '03' })
|
|
500
|
+
|
|
501
|
+
// No provider call is needed until a billing identity is available.
|
|
502
|
+
const stripe = new Stripe('sk_test_unavailable_customer', { maxNetworkRetries: 0 })
|
|
503
|
+
const reporter = Billing.createReporter({ db, stripe })
|
|
504
|
+
expect(await reporter.tick()).toStrictEqual({
|
|
505
|
+
failed: 1,
|
|
506
|
+
reported: 0,
|
|
507
|
+
skipped: 0,
|
|
508
|
+
})
|
|
509
|
+
expect((await SponsoredTransactions.get(db, row.id))?.meterReportedAt).toBeNull()
|
|
510
|
+
expect(await reporter.tick()).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
511
|
+
expect(
|
|
512
|
+
(await SponsoredTransactions.listUnreported(db, { chainIds: [Viem.chainId.mainnet] })).map(
|
|
513
|
+
({ id }) => id,
|
|
514
|
+
),
|
|
515
|
+
).toEqual([row.id])
|
|
516
|
+
await db.close()
|
|
517
|
+
},
|
|
518
|
+
)
|
|
416
519
|
|
|
417
520
|
test('behavior: ensures the metered subscription once and stamps its backlog at now', async () => {
|
|
418
521
|
const db = create()
|
|
@@ -779,7 +882,8 @@ describe('createRequestUsageReporter', () => {
|
|
|
779
882
|
|
|
780
883
|
// Tick 1: fresh customer, initial seal of 5. The just-created item bills at
|
|
781
884
|
// now (no backdate).
|
|
782
|
-
const
|
|
885
|
+
const createdAt = Math.floor(now() / 1_000)
|
|
886
|
+
const first = stubStripe({ createdAt, subscriptions: [] })
|
|
783
887
|
const reporter1 = Billing.createRequestUsageReporter({
|
|
784
888
|
db,
|
|
785
889
|
now,
|
|
@@ -788,9 +892,9 @@ describe('createRequestUsageReporter', () => {
|
|
|
788
892
|
})
|
|
789
893
|
expect(await reporter1.tick()).toStrictEqual({ failed: 0, reported: 1, skipped: 0 })
|
|
790
894
|
expect(first.meterEvents).toEqual([
|
|
791
|
-
{ event_name: 'api_request_count', identifier: expect.any(String), payload: expect.objectContaining({ value: '5' }) }, // prettier-ignore
|
|
895
|
+
{ event_name: 'api_request_count', identifier: expect.any(String), payload: expect.objectContaining({ value: '5' }), timestamp: createdAt }, // prettier-ignore
|
|
792
896
|
])
|
|
793
|
-
expect(first.meterEvents[0]!.timestamp).
|
|
897
|
+
expect(first.meterEvents[0]!.timestamp).toBe(createdAt)
|
|
794
898
|
expect((await RequestUsage.getBucket(db, { bucketStart, environment: 'production', orgId: 'org_1' }))?.reportedCount).toBe(5) // prettier-ignore
|
|
795
899
|
|
|
796
900
|
// Tick 2: count grows to 8; only the delta of 3 bills, backdated (item exists).
|
|
@@ -824,6 +928,30 @@ describe('createRequestUsageReporter', () => {
|
|
|
824
928
|
await db.close()
|
|
825
929
|
})
|
|
826
930
|
|
|
931
|
+
test('behavior: clamps initial backlog to an item provisioned by another reporter', async () => {
|
|
932
|
+
const db = create()
|
|
933
|
+
await db.migrate()
|
|
934
|
+
await StripeCustomers.create(db, { orgId: 'org_1', stripeCustomerId: 'cus_1' })
|
|
935
|
+
await StripeCustomers.setStatus(db, 'org_1', 'active')
|
|
936
|
+
const createdAt = Math.floor(Date.parse('2026-01-01T18:00:00.000Z') / 1_000)
|
|
937
|
+
const { meterEvents, stripe } = stubStripe({
|
|
938
|
+
subscriptions: [
|
|
939
|
+
{ createdAt, items: ['feePayerSpend', 'routeSubsidy', 'apiRequests'], status: 'active' },
|
|
940
|
+
],
|
|
941
|
+
})
|
|
942
|
+
|
|
943
|
+
expect(
|
|
944
|
+
await Billing.createRequestUsageReporter({
|
|
945
|
+
db,
|
|
946
|
+
now,
|
|
947
|
+
readCounts: async () => [{ bucketStart, count: 5, orgId: 'org_1' }],
|
|
948
|
+
stripe,
|
|
949
|
+
}).tick(),
|
|
950
|
+
).toStrictEqual({ failed: 0, reported: 1, skipped: 0 })
|
|
951
|
+
expect(meterEvents[0]?.timestamp).toBe(createdAt)
|
|
952
|
+
await db.close()
|
|
953
|
+
})
|
|
954
|
+
|
|
827
955
|
test('behavior: overlapping ticks cannot claim the same observed watermark twice', async () => {
|
|
828
956
|
const db = create()
|
|
829
957
|
await db.migrate()
|
|
@@ -941,6 +1069,7 @@ describe('createRequestUsageReporter', () => {
|
|
|
941
1069
|
bucketStart,
|
|
942
1070
|
deltaCount: 6,
|
|
943
1071
|
environment: 'production',
|
|
1072
|
+
eventTimestamp: bucketStart,
|
|
944
1073
|
identifier: 'rq_production_deadbeef0001_0_0',
|
|
945
1074
|
orgId: 'org_1',
|
|
946
1075
|
sequence: 0,
|
|
@@ -969,11 +1098,12 @@ describe('createRequestUsageReporter', () => {
|
|
|
969
1098
|
await db.migrate()
|
|
970
1099
|
await StripeCustomers.create(db, { orgId: 'org_1', stripeCustomerId: 'cus_1' })
|
|
971
1100
|
await StripeCustomers.setStatus(db, 'org_1', 'active')
|
|
1101
|
+
const createdAt = Math.floor(Date.parse('2026-01-01T18:00:00.000Z') / 1_000)
|
|
972
1102
|
const { stripe } = stubStripe({
|
|
973
1103
|
meterEvent() {
|
|
974
1104
|
throw new Error('Stripe unavailable')
|
|
975
1105
|
},
|
|
976
|
-
subscriptions: [{ items: ['feePayerSpend', 'apiRequests'], status: 'active' }],
|
|
1106
|
+
subscriptions: [{ createdAt, items: ['feePayerSpend', 'apiRequests'], status: 'active' }],
|
|
977
1107
|
})
|
|
978
1108
|
const reporter = Billing.createRequestUsageReporter({
|
|
979
1109
|
db,
|
|
@@ -990,6 +1120,102 @@ describe('createRequestUsageReporter', () => {
|
|
|
990
1120
|
oldestPendingAgeSeconds: expect.any(Number),
|
|
991
1121
|
},
|
|
992
1122
|
])
|
|
1123
|
+
|
|
1124
|
+
const pending = (await RequestUsage.listPending(db, 'production'))[0]!
|
|
1125
|
+
await db.kysely
|
|
1126
|
+
.updateTable('request_usage_meter_events')
|
|
1127
|
+
.set({ eventTimestamp: pending.firstAttemptedAt })
|
|
1128
|
+
.where('identifier', '=', pending.identifier)
|
|
1129
|
+
.execute()
|
|
1130
|
+
const retryAt = new Date(pending.firstAttemptedAt).getTime() + 23 * 60 * 60 * 1_000
|
|
1131
|
+
const failedRetry = stubStripe({ subscriptions: [] })
|
|
1132
|
+
expect(
|
|
1133
|
+
await Billing.createRequestUsageReporter({
|
|
1134
|
+
db,
|
|
1135
|
+
now: () => retryAt,
|
|
1136
|
+
readCounts: async () => [],
|
|
1137
|
+
stripe: failedRetry.stripe,
|
|
1138
|
+
}).tick(),
|
|
1139
|
+
).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
1140
|
+
expect(failedRetry.meterEvents).toHaveLength(0)
|
|
1141
|
+
expect(await RequestUsage.listPending(db, 'production')).toHaveLength(1)
|
|
1142
|
+
expect(await reporter.pending()).toMatchObject([{ count: 1, environment: 'production' }])
|
|
1143
|
+
|
|
1144
|
+
const retry = stubStripe({ subscriptions: [] })
|
|
1145
|
+
expect(
|
|
1146
|
+
await Billing.createRequestUsageReporter({
|
|
1147
|
+
db,
|
|
1148
|
+
now: () => retryAt + 24 * 60 * 60 * 1_000,
|
|
1149
|
+
readCounts: async () => [],
|
|
1150
|
+
stripe: retry.stripe,
|
|
1151
|
+
}).tick(),
|
|
1152
|
+
).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
1153
|
+
expect(retry.meterEvents).toHaveLength(0)
|
|
1154
|
+
await db.close()
|
|
1155
|
+
})
|
|
1156
|
+
|
|
1157
|
+
test('behavior: stops retrying a legacy event after identifier uniqueness expires', async () => {
|
|
1158
|
+
const db = create()
|
|
1159
|
+
await db.migrate()
|
|
1160
|
+
await RequestUsage.insertPending(db, {
|
|
1161
|
+
bucketStart,
|
|
1162
|
+
deltaCount: 6,
|
|
1163
|
+
environment: 'production',
|
|
1164
|
+
eventTimestamp: new Date().toISOString(),
|
|
1165
|
+
identifier: 'rq_production_deadbeef0003_0_0',
|
|
1166
|
+
orgId: 'org_1',
|
|
1167
|
+
sequence: 0,
|
|
1168
|
+
stripeCustomerId: 'cus_1',
|
|
1169
|
+
})
|
|
1170
|
+
await db.kysely
|
|
1171
|
+
.updateTable('request_usage_meter_events')
|
|
1172
|
+
.set({ eventTimestamp: null })
|
|
1173
|
+
.where('identifier', '=', 'rq_production_deadbeef0003_0_0')
|
|
1174
|
+
.execute()
|
|
1175
|
+
const pending = (await RequestUsage.listPending(db, 'production'))[0]!
|
|
1176
|
+
expect(pending).not.toHaveProperty('eventTimestamp')
|
|
1177
|
+
const stripe = stubStripe({ subscriptions: [] })
|
|
1178
|
+
expect(
|
|
1179
|
+
await Billing.createRequestUsageReporter({
|
|
1180
|
+
db,
|
|
1181
|
+
now: () => new Date(pending.firstAttemptedAt).getTime() + 23 * 60 * 60 * 1_000,
|
|
1182
|
+
readCounts: async () => [],
|
|
1183
|
+
stripe: stripe.stripe,
|
|
1184
|
+
}).tick(),
|
|
1185
|
+
).toStrictEqual({ failed: 1, reported: 0, skipped: 0 })
|
|
1186
|
+
expect(stripe.meterEvents).toHaveLength(0)
|
|
1187
|
+
expect(await RequestUsage.listPending(db, 'production')).toHaveLength(1)
|
|
1188
|
+
await db.close()
|
|
1189
|
+
})
|
|
1190
|
+
|
|
1191
|
+
test('behavior: settles a retry when Stripe confirms the identifier already exists', async () => {
|
|
1192
|
+
const db = create()
|
|
1193
|
+
await db.migrate()
|
|
1194
|
+
await RequestUsage.insertPending(db, {
|
|
1195
|
+
bucketStart,
|
|
1196
|
+
deltaCount: 6,
|
|
1197
|
+
environment: 'production',
|
|
1198
|
+
eventTimestamp: bucketStart,
|
|
1199
|
+
identifier: 'rq_production_deadbeef0002_0_0',
|
|
1200
|
+
orgId: 'org_1',
|
|
1201
|
+
sequence: 0,
|
|
1202
|
+
stripeCustomerId: 'cus_1',
|
|
1203
|
+
})
|
|
1204
|
+
const { stripe } = stubStripe({
|
|
1205
|
+
meterEvent({ identifier }) {
|
|
1206
|
+
throw new Error(`An event already exists with identifier ${identifier}.`)
|
|
1207
|
+
},
|
|
1208
|
+
subscriptions: [],
|
|
1209
|
+
})
|
|
1210
|
+
expect(
|
|
1211
|
+
await Billing.createRequestUsageReporter({
|
|
1212
|
+
db,
|
|
1213
|
+
now,
|
|
1214
|
+
readCounts: async () => [],
|
|
1215
|
+
stripe,
|
|
1216
|
+
}).tick(),
|
|
1217
|
+
).toStrictEqual({ failed: 0, reported: 1, skipped: 0 })
|
|
1218
|
+
expect((await RequestUsage.getBucket(db, { bucketStart, environment: 'production', orgId: 'org_1' }))?.reportedCount).toBe(6) // prettier-ignore
|
|
993
1219
|
await db.close()
|
|
994
1220
|
})
|
|
995
1221
|
})
|
|
@@ -13,7 +13,6 @@ import type * as Scope from '../../Scope.js'
|
|
|
13
13
|
import * as SponsoredTransactions from '../../db/tables/sponsoredTransactions.js'
|
|
14
14
|
import type * as Store from '../../internal/Store.js'
|
|
15
15
|
import * as StripeCustomers from '../../db/tables/stripeCustomers.js'
|
|
16
|
-
import * as Viem from '../../internal/Viem.js'
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Whether the organization has any active billing source — the production
|
|
@@ -449,12 +448,18 @@ export class DuplicateSubscriptionError extends Error {
|
|
|
449
448
|
}
|
|
450
449
|
}
|
|
451
450
|
|
|
451
|
+
/** Safe Stripe meter-event ingestion window below its documented 35-day limit. */
|
|
452
|
+
const meterEventIngestionWindowMs = 34 * 24 * 60 * 60 * 1_000
|
|
453
|
+
|
|
454
|
+
/** Safe retry window below Stripe's documented 24-hour identifier uniqueness period. */
|
|
455
|
+
const meterEventRetryWindowMs = 23 * 60 * 60 * 1_000
|
|
456
|
+
|
|
452
457
|
/**
|
|
453
458
|
* Creates the sponsorship and Route Subsidy metering job. Each tick reports
|
|
454
459
|
* finalized usage, then marks each row after Stripe acknowledges it.
|
|
455
460
|
*/
|
|
456
461
|
export function createReporter(options: createReporter.Options): createReporter.Reporter {
|
|
457
|
-
const { batchSize = 100,
|
|
462
|
+
const { batchSize = 100, db, stripe } = options
|
|
458
463
|
return {
|
|
459
464
|
async tick() {
|
|
460
465
|
// Resolve per tick so Workers factories build a fresh Hyperdrive-pooled
|
|
@@ -462,7 +467,10 @@ export function createReporter(options: createReporter.Options): createReporter.
|
|
|
462
467
|
const database = Db.get(db)
|
|
463
468
|
const [depositSubsidies, sponsorships, transferSubsidies] = await Promise.all([
|
|
464
469
|
RoutesDeposits.listUnreportedSubsidies(database, { limit: batchSize }),
|
|
465
|
-
SponsoredTransactions.
|
|
470
|
+
SponsoredTransactions.claimUnreported(database, {
|
|
471
|
+
attemptedAt: new Date().toISOString(),
|
|
472
|
+
limit: batchSize,
|
|
473
|
+
}),
|
|
466
474
|
RoutesTransfers.listUnreportedSubsidies(database, { limit: batchSize }),
|
|
467
475
|
])
|
|
468
476
|
const rows: UsageRow[] = [
|
|
@@ -532,7 +540,7 @@ export function createReporter(options: createReporter.Options): createReporter.
|
|
|
532
540
|
// just-created meter item bills nothing before its start, so
|
|
533
541
|
// its backlog stamps at now too.
|
|
534
542
|
const finalizedAt = new Date(row.finalizedAt!).getTime()
|
|
535
|
-
const recent = Date.now() - finalizedAt <
|
|
543
|
+
const recent = Date.now() - finalizedAt < meterEventIngestionWindowMs
|
|
536
544
|
const item = subscription.items[kind]
|
|
537
545
|
const stamp =
|
|
538
546
|
recent && item !== undefined && !item.created && finalizedAt >= item.createdAt * 1_000
|
|
@@ -540,6 +548,19 @@ export function createReporter(options: createReporter.Options): createReporter.
|
|
|
540
548
|
meteredAt = new Date(
|
|
541
549
|
(timestamp ?? Math.floor(Date.now() / 1_000)) * 1_000,
|
|
542
550
|
).toISOString()
|
|
551
|
+
if (row.source === 'sponsorship') {
|
|
552
|
+
const firstAttemptedAt = await SponsoredTransactions.beginMeterEvent(
|
|
553
|
+
database,
|
|
554
|
+
row.id,
|
|
555
|
+
new Date().toISOString(),
|
|
556
|
+
)
|
|
557
|
+
// Stripe only deduplicates identifiers for 24 hours. An older
|
|
558
|
+
// uncertain acknowledgment requires reconciliation before resend.
|
|
559
|
+
if (Date.now() - new Date(firstAttemptedAt).getTime() >= meterEventRetryWindowMs)
|
|
560
|
+
throw new Error(
|
|
561
|
+
`Stripe acknowledgement is ambiguous after the safe meter-event retry window for ${row.id}`,
|
|
562
|
+
)
|
|
563
|
+
}
|
|
543
564
|
// The row id makes short-window retries idempotent on Stripe's
|
|
544
565
|
// side; `meter_reported_at` is the durable exactly-once guard.
|
|
545
566
|
try {
|
|
@@ -556,7 +577,20 @@ export function createReporter(options: createReporter.Options): createReporter.
|
|
|
556
577
|
} catch (error) {
|
|
557
578
|
// Stripe may persist the event before the Worker records its ack.
|
|
558
579
|
// Its duplicate response proves this exact row was already metered.
|
|
559
|
-
if (!isDuplicateMeterEvent(error, row.id))
|
|
580
|
+
if (!isDuplicateMeterEvent(error, row.id)) {
|
|
581
|
+
// An explicit client error rejects this submission. Only
|
|
582
|
+
// uncertain outcomes retain the first-send retry clock.
|
|
583
|
+
if (
|
|
584
|
+
row.source === 'sponsorship' &&
|
|
585
|
+
error instanceof Stripe.errors.StripeError &&
|
|
586
|
+
error.statusCode !== undefined &&
|
|
587
|
+
error.statusCode >= 400 &&
|
|
588
|
+
error.statusCode < 500 &&
|
|
589
|
+
error.statusCode !== 409
|
|
590
|
+
)
|
|
591
|
+
await SponsoredTransactions.clearRejectedMeterEventAttempt(database, row.id)
|
|
592
|
+
throw error
|
|
593
|
+
}
|
|
560
594
|
}
|
|
561
595
|
reported++
|
|
562
596
|
} else if (row.source === 'routes-deposit' && row.orgId.startsWith('key_')) {
|
|
@@ -564,16 +598,11 @@ export function createReporter(options: createReporter.Options): createReporter.
|
|
|
564
598
|
// Stripe customer. Provider subsidies on those routes are non-billable.
|
|
565
599
|
meteredAt = new Date().toISOString()
|
|
566
600
|
skipped++
|
|
567
|
-
} else if (row.source !== 'sponsorship') {
|
|
568
|
-
// Production Routes subsidies were authorized against active billing.
|
|
569
|
-
// Keep the liability durable if that customer disappears before reporting.
|
|
570
|
-
throw new Error(`Stripe customer unavailable for Routes subsidy ${row.id}`)
|
|
571
601
|
} else {
|
|
572
|
-
//
|
|
573
|
-
|
|
574
|
-
skipped++
|
|
602
|
+
// Missing billing identity cannot discharge a committed liability; preserve it for retry and alert through the scheduled-task failure counter.
|
|
603
|
+
throw new Error(`Stripe customer unavailable for ${row.source} ${row.id}`)
|
|
575
604
|
}
|
|
576
|
-
// Mark only after the Stripe ack
|
|
605
|
+
// Mark only after the Stripe ack or the non-billable one-off-key exemption.
|
|
577
606
|
const reportedAt = new Date().toISOString()
|
|
578
607
|
if (row.source !== 'sponsorship') {
|
|
579
608
|
if (!meteredAt) throw new Error(`Routes subsidy ${row.id} has no meter timestamp`)
|
|
@@ -635,10 +664,8 @@ function isDuplicateMeterEvent(error: unknown, identifier: string): boolean {
|
|
|
635
664
|
export declare namespace createReporter {
|
|
636
665
|
/** Options for {@link createReporter}. */
|
|
637
666
|
type Options = {
|
|
638
|
-
/** Maximum rows
|
|
667
|
+
/** Maximum rows attempted per source per tick. @default 100 */
|
|
639
668
|
batchSize?: number | undefined
|
|
640
|
-
/** Chains whose spend is metered. @default mainnet */
|
|
641
|
-
chainIds?: readonly number[] | undefined
|
|
642
669
|
/** Database holding sponsorship rows, or a factory resolved per tick (Workers/Hyperdrive). */
|
|
643
670
|
db: Db.Source
|
|
644
671
|
/** Stripe client used to send meter events. */
|
|
@@ -647,7 +674,7 @@ export declare namespace createReporter {
|
|
|
647
674
|
|
|
648
675
|
/** A scheduled metering job. */
|
|
649
676
|
type Reporter = {
|
|
650
|
-
/** Runs one reporting pass. Failed rows stay unmarked and retry
|
|
677
|
+
/** Runs one reporting pass. Failed rows stay unmarked and retry on later ticks. */
|
|
651
678
|
tick(): Promise<{ failed: number; reported: number; skipped: number }>
|
|
652
679
|
}
|
|
653
680
|
}
|
|
@@ -729,14 +756,36 @@ export function createRequestUsageReporter(
|
|
|
729
756
|
const blocked = new Set<string>()
|
|
730
757
|
for (const event of await RequestUsage.listPending(database, environment)) {
|
|
731
758
|
try {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
759
|
+
const eventTimestamp = event.eventTimestamp
|
|
760
|
+
if (
|
|
761
|
+
nowMs - new Date(event.firstAttemptedAt).getTime() >= meterEventRetryWindowMs ||
|
|
762
|
+
(eventTimestamp !== undefined &&
|
|
763
|
+
nowMs - new Date(eventTimestamp).getTime() >= meterEventIngestionWindowMs)
|
|
764
|
+
) {
|
|
765
|
+
failed++
|
|
766
|
+
blocked.add(bucketKey(event.orgId, event.bucketStart))
|
|
767
|
+
await RequestUsage.markError(
|
|
768
|
+
database,
|
|
769
|
+
event.identifier,
|
|
770
|
+
'Stripe acknowledgement is ambiguous after the safe meter-event retry window.',
|
|
771
|
+
)
|
|
772
|
+
continue
|
|
773
|
+
}
|
|
774
|
+
try {
|
|
775
|
+
await client.billing.meterEvents.create({
|
|
776
|
+
event_name: meters.apiRequests.eventName,
|
|
777
|
+
identifier: event.identifier,
|
|
778
|
+
payload: {
|
|
779
|
+
stripe_customer_id: event.stripeCustomerId,
|
|
780
|
+
value: String(event.deltaCount),
|
|
781
|
+
},
|
|
782
|
+
...(eventTimestamp === undefined
|
|
783
|
+
? {}
|
|
784
|
+
: { timestamp: Math.floor(new Date(eventTimestamp).getTime() / 1_000) }),
|
|
785
|
+
})
|
|
786
|
+
} catch (error) {
|
|
787
|
+
if (!isDuplicateMeterEvent(error, event.identifier)) throw error
|
|
788
|
+
}
|
|
740
789
|
if (await RequestUsage.settle(database, event.identifier, new Date().toISOString()))
|
|
741
790
|
reported++
|
|
742
791
|
} catch (error) {
|
|
@@ -781,9 +830,17 @@ export function createRequestUsageReporter(
|
|
|
781
830
|
// The observed watermark is stable for every tick claiming this delta.
|
|
782
831
|
const sequence = watermark?.reportedCount ?? 0
|
|
783
832
|
const identifier = usageIdentifier(environment, orgId, bucketStart, sequence)
|
|
833
|
+
const item = subscription.items.apiRequests
|
|
834
|
+
if (!item) throw new Error(`API request meter item unavailable for ${orgId}`)
|
|
835
|
+
// Meter events before the subscription item's creation are accepted
|
|
836
|
+
// but not invoiced, so clamp backlog to its billing eligibility window.
|
|
837
|
+
const eventTimestamp = new Date(
|
|
838
|
+
Math.max(new Date(bucketStart).getTime(), item.createdAt * 1_000),
|
|
839
|
+
).toISOString()
|
|
784
840
|
const inserted = await RequestUsage.insertPending(database, {
|
|
785
841
|
...key,
|
|
786
842
|
deltaCount: delta,
|
|
843
|
+
eventTimestamp,
|
|
787
844
|
identifier,
|
|
788
845
|
sequence,
|
|
789
846
|
stripeCustomerId: customer.stripeCustomerId,
|
|
@@ -791,14 +848,11 @@ export function createRequestUsageReporter(
|
|
|
791
848
|
// A concurrent tick already claimed this delta; leave it to that run.
|
|
792
849
|
if (!inserted) continue
|
|
793
850
|
|
|
794
|
-
// Backdate to the bucket hour unless the item was just created (it
|
|
795
|
-
// bills nothing before its start, so its backlog stamps at now).
|
|
796
|
-
const stamp = !subscription.items.apiRequests?.created
|
|
797
851
|
await client.billing.meterEvents.create({
|
|
798
852
|
event_name: meters.apiRequests.eventName,
|
|
799
853
|
identifier,
|
|
800
854
|
payload: { stripe_customer_id: customer.stripeCustomerId, value: String(delta) },
|
|
801
|
-
|
|
855
|
+
timestamp: Math.floor(new Date(eventTimestamp).getTime() / 1_000),
|
|
802
856
|
})
|
|
803
857
|
if (await RequestUsage.settle(database, identifier, new Date().toISOString()))
|
|
804
858
|
reported++
|
|
@@ -1010,7 +1010,7 @@ describe('keys', () => {
|
|
|
1010
1010
|
{
|
|
1011
1011
|
"error": {
|
|
1012
1012
|
"code": "api_key_forbidden",
|
|
1013
|
-
"message": "API key missing required
|
|
1013
|
+
"message": "API key is missing required permissions: data:read. Use an API key with these scopes.",
|
|
1014
1014
|
},
|
|
1015
1015
|
}
|
|
1016
1016
|
`)
|