tapimo 0.14.0 → 0.15.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 +7 -4
- package/dist/ApiKey.js +1 -1
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +95 -14
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +360 -49
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +12466 -10374
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +300 -22
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +2 -1
- package/dist/Assets.js.map +1 -1
- package/dist/Handler.d.ts +0 -1
- package/dist/Handler.d.ts.map +1 -1
- package/dist/Handler.js +0 -1
- package/dist/Handler.js.map +1 -1
- package/dist/Scope.d.ts +13 -5
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +16 -5
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.js +1 -1
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +3057 -546
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +26 -5
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +179 -27
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +95 -43
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +1398 -0
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +463 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +267 -15
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +241 -25
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/routes-support.d.ts +95 -0
- package/dist/admin/apps/routes-support.d.ts.map +1 -0
- package/dist/admin/apps/routes-support.js +151 -0
- package/dist/admin/apps/routes-support.js.map +1 -0
- package/dist/admin/apps/routes.d.ts +2764 -0
- package/dist/admin/apps/routes.d.ts.map +1 -0
- package/dist/admin/apps/routes.js +728 -0
- package/dist/admin/apps/routes.js.map +1 -0
- package/dist/admin/apps/subsidies.d.ts +501 -0
- package/dist/admin/apps/subsidies.d.ts.map +1 -0
- package/dist/admin/apps/subsidies.js +384 -0
- package/dist/admin/apps/subsidies.js.map +1 -0
- package/dist/admin/apps/verified-tokens.d.ts +166 -160
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +27 -7
- package/dist/admin/apps/verified-tokens.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 +201 -149
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +5 -2
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +31 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +2 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +10 -1
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/analytics/tables/routesLifecycleIntervals.d.ts +72 -0
- package/dist/analytics/tables/routesLifecycleIntervals.d.ts.map +1 -0
- package/dist/analytics/tables/routesLifecycleIntervals.js +56 -0
- package/dist/analytics/tables/routesLifecycleIntervals.js.map +1 -0
- package/dist/apps/Zones.d.ts +21 -12526
- package/dist/apps/Zones.d.ts.map +1 -1
- package/dist/apps/Zones.js +37 -5
- package/dist/apps/Zones.js.map +1 -1
- package/dist/apps/data/App.d.ts +3971 -2595
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +76 -21
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +629 -299
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +495 -190
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +72 -0
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +116 -116
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
- package/dist/apps/data/routes/coingecko.js +47 -21
- package/dist/apps/data/routes/coingecko.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +1450 -337
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +1226 -144
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +113 -108
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +41 -21
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +142 -17
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +83 -27
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +235 -235
- package/dist/apps/data/routes/rpc.d.ts +507 -33
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +309 -165
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +47 -15
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +68 -11
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +2 -0
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +26 -14
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +93 -77
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +9 -7
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +32 -32
- package/dist/apps/data/routes/verified-tokens.d.ts +88 -88
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/verified-tokens.js +64 -20
- package/dist/apps/data/routes/verified-tokens.js.map +1 -1
- package/dist/apps/data/routes/webhooks.d.ts +614 -177
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +308 -205
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +31 -31
- package/dist/apps/data/routes/zones.d.ts.map +1 -1
- package/dist/apps/data/routes/zones.js +20 -12
- package/dist/apps/data/routes/zones.js.map +1 -1
- package/dist/apps/docs/reference.js +2 -2
- package/dist/apps/docs/reference.js.map +1 -1
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +1 -1
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/management/App.d.ts +3780 -3402
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +5 -14
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +48 -7
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +204 -25
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +317 -215
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +43 -15
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +290 -4
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +274 -49
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +6 -6
- package/dist/apps/management/routes/faucet.js +1 -1
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +213 -138
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +117 -13
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +166 -166
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +6 -2
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +30 -30
- package/dist/apps/management/routes/orgs.d.ts +103 -87
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +52 -12
- 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/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +6 -1
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +4 -1
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +24 -24
- package/dist/apps/management/routes/usage.js +21 -4
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +95 -95
- 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 +682 -616
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +58 -12
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mcp.d.ts +1 -1
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +23 -10
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/mpp/App.d.ts +44 -44
- package/dist/apps/mpp/App.d.ts.map +1 -1
- package/dist/apps/mpp/App.js +35 -7
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +2 -0
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +30 -1
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts +22 -4
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +24 -6
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts +3 -0
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -3
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +2 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +134 -75
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +5 -3
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +209 -28
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/{funding → routes}/Access.d.ts +4 -4
- package/dist/apps/routes/Access.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/Access.js +4 -4
- package/dist/apps/routes/Access.js.map +1 -0
- package/dist/apps/{funding → routes}/App.d.ts +418 -124
- package/dist/apps/{funding → routes}/App.d.ts.map +1 -1
- package/dist/apps/{funding → routes}/App.js +16 -16
- package/dist/apps/routes/App.js.map +1 -0
- package/dist/apps/routes/Inventory.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/Inventory.js +2 -2
- package/dist/apps/routes/Inventory.js.map +1 -0
- package/dist/apps/routes/index.d.ts +2 -0
- package/dist/apps/routes/index.d.ts.map +1 -0
- package/dist/apps/routes/index.js +2 -0
- package/dist/apps/routes/index.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/chains.d.ts +32 -32
- package/dist/apps/routes/routes/chains.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/routes/chains.js +25 -25
- package/dist/apps/routes/routes/chains.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/deposit-addresses.d.ts +107 -43
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/routes/deposit-addresses.js +497 -222
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/providers.d.ts +8 -8
- package/dist/apps/routes/routes/providers.d.ts.map +1 -0
- package/dist/apps/routes/routes/providers.js +57 -0
- package/dist/apps/routes/routes/providers.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/quotes.d.ts +106 -103
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -0
- package/dist/apps/{funding → routes}/routes/quotes.js +55 -38
- package/dist/apps/routes/routes/quotes.js.map +1 -0
- package/dist/apps/{funding → routes}/routes/transfers.d.ts +733 -428
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -0
- package/dist/apps/routes/routes/transfers.js +1140 -0
- package/dist/apps/routes/routes/transfers.js.map +1 -0
- package/dist/cli/Cli.d.ts +30 -0
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/commands/admin.d.ts +36 -0
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +273 -0
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/cloudflare.d.ts +16 -14
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +26 -21
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +63 -21
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +1035 -15
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +780 -133
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +575 -162
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts +4 -0
- package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts.map +1 -0
- package/dist/db/tables/apiKeyAdmissionBootstraps.js +2 -0
- package/dist/db/tables/apiKeyAdmissionBootstraps.js.map +1 -0
- package/dist/db/tables/apiKeyAdmissions.d.ts +73 -0
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -0
- package/dist/db/tables/apiKeyAdmissions.js +142 -0
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.d.ts +4 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.d.ts.map +1 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.js +2 -0
- package/dist/db/tables/apiKeyOwnerAdmissions.js.map +1 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +20 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -0
- package/dist/db/tables/apiKeyOwnerTombstones.js +57 -0
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -0
- package/dist/db/tables/apiKeyRevocations.d.ts +21 -0
- package/dist/db/tables/apiKeyRevocations.d.ts.map +1 -0
- package/dist/db/tables/apiKeyRevocations.js +98 -0
- package/dist/db/tables/apiKeyRevocations.js.map +1 -0
- package/dist/db/tables/authAccounts.d.ts +47 -0
- package/dist/db/tables/authAccounts.d.ts.map +1 -0
- package/dist/db/tables/authAccounts.js +72 -0
- package/dist/db/tables/authAccounts.js.map +1 -0
- package/dist/db/tables/authSessions.d.ts +12 -0
- package/dist/db/tables/authSessions.d.ts.map +1 -0
- package/dist/db/tables/authSessions.js +2 -0
- package/dist/db/tables/authSessions.js.map +1 -0
- package/dist/db/tables/authVerifications.d.ts +12 -0
- package/dist/db/tables/authVerifications.d.ts.map +1 -0
- package/dist/db/tables/authVerifications.js +2 -0
- package/dist/db/tables/authVerifications.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +17 -1
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/invitations.js +123 -43
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/memberships.d.ts +8 -0
- package/dist/db/tables/memberships.d.ts.map +1 -1
- package/dist/db/tables/memberships.js +51 -2
- package/dist/db/tables/memberships.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +32 -10
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +110 -49
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +2 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +12 -3
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardAccounts.d.ts +86 -0
- package/dist/db/tables/rewardAccounts.d.ts.map +1 -0
- package/dist/db/tables/rewardAccounts.js +88 -0
- package/dist/db/tables/rewardAccounts.js.map +1 -0
- package/dist/db/tables/rewardCampaignDistributors.d.ts +36 -0
- package/dist/db/tables/rewardCampaignDistributors.d.ts.map +1 -0
- package/dist/db/tables/rewardCampaignDistributors.js +30 -0
- package/dist/db/tables/rewardCampaignDistributors.js.map +1 -0
- package/dist/db/tables/rewardCampaigns.d.ts +171 -0
- package/dist/db/tables/rewardCampaigns.d.ts.map +1 -0
- package/dist/db/tables/rewardCampaigns.js +392 -0
- package/dist/db/tables/rewardCampaigns.js.map +1 -0
- package/dist/db/tables/rewardCredits.d.ts +53 -0
- package/dist/db/tables/rewardCredits.d.ts.map +1 -0
- package/dist/db/tables/rewardCredits.js +63 -0
- package/dist/db/tables/rewardCredits.js.map +1 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +61 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -0
- package/dist/db/tables/rewardEligibilityAssociations.js +103 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -0
- package/dist/db/tables/rewardRuns.d.ts +188 -0
- package/dist/db/tables/rewardRuns.d.ts.map +1 -0
- package/dist/db/tables/rewardRuns.js +278 -0
- package/dist/db/tables/rewardRuns.js.map +1 -0
- package/dist/db/tables/rewardTransactionAttempts.d.ts +100 -0
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -0
- package/dist/db/tables/rewardTransactionAttempts.js +163 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -0
- package/dist/db/tables/routesCatalog.d.ts +58 -0
- package/dist/db/tables/routesCatalog.d.ts.map +1 -0
- package/dist/db/tables/{fundingCatalog.js → routesCatalog.js} +19 -19
- package/dist/db/tables/routesCatalog.js.map +1 -0
- package/dist/db/tables/routesDepositAddresses.d.ts +476 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -0
- package/dist/db/tables/routesDepositAddresses.js +587 -0
- package/dist/db/tables/routesDepositAddresses.js.map +1 -0
- package/dist/db/tables/{fundingDepositRequestObservations.d.ts → routesDepositRequestObservations.d.ts} +6 -6
- package/dist/db/tables/routesDepositRequestObservations.d.ts.map +1 -0
- package/dist/db/tables/{fundingDepositRequestObservations.js → routesDepositRequestObservations.js} +6 -6
- package/dist/db/tables/routesDepositRequestObservations.js.map +1 -0
- package/dist/db/tables/{fundingDeposits.d.ts → routesDeposits.d.ts} +210 -22
- package/dist/db/tables/routesDeposits.d.ts.map +1 -0
- package/dist/db/tables/routesDeposits.js +576 -0
- package/dist/db/tables/routesDeposits.js.map +1 -0
- package/dist/db/tables/routesIdempotency.d.ts +166 -0
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -0
- package/dist/db/tables/routesIdempotency.js +330 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -0
- package/dist/db/tables/routesSubsidies.d.ts +27 -0
- package/dist/db/tables/routesSubsidies.d.ts.map +1 -0
- package/dist/db/tables/routesSubsidies.js +45 -0
- package/dist/db/tables/routesSubsidies.js.map +1 -0
- package/dist/db/tables/{fundingTransferEvents.d.ts → routesTransferEvents.d.ts} +3 -3
- package/dist/db/tables/routesTransferEvents.d.ts.map +1 -0
- package/dist/db/tables/{fundingTransferEvents.js → routesTransferEvents.js} +3 -3
- package/dist/db/tables/routesTransferEvents.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +19 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.js +17 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts +51 -0
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -0
- package/dist/db/tables/routesTransferSubsidyNonces.js +82 -0
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -0
- package/dist/db/tables/routesTransferTransactions.d.ts +77 -0
- package/dist/db/tables/routesTransferTransactions.d.ts.map +1 -0
- package/dist/db/tables/{fundingTransferTransactions.js → routesTransferTransactions.js} +31 -13
- package/dist/db/tables/routesTransferTransactions.js.map +1 -0
- package/dist/db/tables/routesTransfers.d.ts +319 -0
- package/dist/db/tables/routesTransfers.d.ts.map +1 -0
- package/dist/db/tables/routesTransfers.js +372 -0
- package/dist/db/tables/routesTransfers.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +75 -20
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +124 -54
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/sponsorshipAttributions.d.ts +69 -0
- package/dist/db/tables/sponsorshipAttributions.d.ts.map +1 -0
- package/dist/db/tables/sponsorshipAttributions.js +77 -0
- package/dist/db/tables/sponsorshipAttributions.js.map +1 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.d.ts +22 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.d.ts.map +1 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.js +45 -0
- package/dist/db/tables/sponsorshipReconciliationCursors.js.map +1 -0
- package/dist/db/tables/stripeCustomers.d.ts +11 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -1
- package/dist/db/tables/stripeCustomers.js +13 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -1
- package/dist/db/tables/users.d.ts +17 -1
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +47 -2
- 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/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +5 -1
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +19 -11
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +45 -13
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/handlers/internal/executionError.d.ts +2 -2
- package/dist/handlers/internal/executionError.d.ts.map +1 -1
- package/dist/handlers/internal/executionError.js +1 -2
- package/dist/handlers/internal/executionError.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +4 -232
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +11 -537
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +19 -8
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +13 -9
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/relay.d.ts +9 -12
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +81 -85
- package/dist/handlers/relay.js.map +1 -1
- package/dist/index.d.ts +0 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -17
- package/dist/index.js.map +1 -1
- package/dist/internal/AssetResponse.d.ts +12 -0
- package/dist/internal/AssetResponse.d.ts.map +1 -0
- package/dist/internal/AssetResponse.js +21 -0
- package/dist/internal/AssetResponse.js.map +1 -0
- package/dist/internal/Auth.d.ts +64 -12
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +631 -180
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +1488 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -0
- package/dist/internal/BetterAuth.js +253 -0
- package/dist/internal/BetterAuth.js.map +1 -0
- package/dist/internal/Cache.d.ts +2 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +2 -0
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnRates.d.ts +26 -3
- package/dist/internal/EarnRates.d.ts.map +1 -1
- package/dist/internal/EarnRates.js +84 -19
- package/dist/internal/EarnRates.js.map +1 -1
- package/dist/internal/EarnSharePrices.d.ts +120 -0
- package/dist/internal/EarnSharePrices.d.ts.map +1 -0
- package/dist/internal/EarnSharePrices.js +179 -0
- package/dist/internal/EarnSharePrices.js.map +1 -0
- package/dist/internal/EarnVaults.d.ts +4 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +27 -10
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/Email.d.ts +37 -0
- package/dist/internal/Email.d.ts.map +1 -0
- package/dist/internal/Email.js +16 -0
- package/dist/internal/Email.js.map +1 -0
- package/dist/internal/Log.d.ts +32 -28
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +18 -11
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts +3 -0
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +67 -8
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/Mpp.d.ts.map +1 -1
- package/dist/internal/Mpp.js +20 -25
- package/dist/internal/Mpp.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +26 -3
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +25 -10
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Provider.d.ts +1 -1
- package/dist/internal/Provider.d.ts.map +1 -1
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +13 -1
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +16 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +59 -8
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +9 -2
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +78 -11
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Timing.d.ts +26 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +63 -5
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/VercelOidc.d.ts +94 -0
- package/dist/internal/VercelOidc.d.ts.map +1 -0
- package/dist/internal/VercelOidc.js +128 -0
- package/dist/internal/VercelOidc.js.map +1 -0
- package/dist/internal/VerifiedTokens.d.ts +2 -8
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +24 -24
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Viem.d.ts +30 -2067
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +167 -17
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +12 -4
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +9 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/ZoneRpc.d.ts +7 -0
- package/dist/internal/ZoneRpc.d.ts.map +1 -0
- package/dist/internal/ZoneRpc.js +49 -0
- package/dist/internal/ZoneRpc.js.map +1 -0
- package/dist/internal/index.d.ts +3 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +3 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/rewards/Audit.d.ts +88 -0
- package/dist/internal/rewards/Audit.d.ts.map +1 -0
- package/dist/internal/rewards/Audit.js +134 -0
- package/dist/internal/rewards/Audit.js.map +1 -0
- package/dist/internal/rewards/Campaigns.d.ts +572 -0
- package/dist/internal/rewards/Campaigns.d.ts.map +1 -0
- package/dist/internal/rewards/Campaigns.js +531 -0
- package/dist/internal/rewards/Campaigns.js.map +1 -0
- package/dist/internal/rewards/Credits.d.ts +76 -0
- package/dist/internal/rewards/Credits.d.ts.map +1 -0
- package/dist/internal/rewards/Credits.js +95 -0
- package/dist/internal/rewards/Credits.js.map +1 -0
- package/dist/internal/rewards/Events.d.ts +100 -0
- package/dist/internal/rewards/Events.d.ts.map +1 -0
- package/dist/internal/rewards/Events.js +340 -0
- package/dist/internal/rewards/Events.js.map +1 -0
- package/dist/internal/rewards/Projection.d.ts +237 -0
- package/dist/internal/rewards/Projection.d.ts.map +1 -0
- package/dist/internal/rewards/Projection.js +616 -0
- package/dist/internal/rewards/Projection.js.map +1 -0
- package/dist/internal/rewards/Rates.d.ts +44 -0
- package/dist/internal/rewards/Rates.d.ts.map +1 -0
- package/dist/internal/rewards/Rates.js +60 -0
- package/dist/internal/rewards/Rates.js.map +1 -0
- package/dist/internal/rewards/Read.d.ts +158 -0
- package/dist/internal/rewards/Read.d.ts.map +1 -0
- package/dist/internal/rewards/Read.js +292 -0
- package/dist/internal/rewards/Read.js.map +1 -0
- package/dist/internal/rewards/Runner.d.ts +164 -0
- package/dist/internal/rewards/Runner.d.ts.map +1 -0
- package/dist/internal/rewards/Runner.js +1778 -0
- package/dist/internal/rewards/Runner.js.map +1 -0
- package/dist/internal/rewards/Signer.d.ts +224 -0
- package/dist/internal/rewards/Signer.d.ts.map +1 -0
- package/dist/internal/rewards/Signer.js +135 -0
- package/dist/internal/rewards/Signer.js.map +1 -0
- package/dist/internal/rewards/index.d.ts +15 -0
- package/dist/internal/rewards/index.d.ts.map +1 -0
- package/dist/internal/rewards/index.js +15 -0
- package/dist/internal/rewards/index.js.map +1 -0
- package/dist/internal/{funding → routes}/Action.d.ts +12 -1
- package/dist/internal/routes/Action.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Action.js +17 -9
- package/dist/internal/routes/Action.js.map +1 -0
- package/dist/internal/{funding → routes}/Catalog.d.ts +20 -20
- package/dist/internal/routes/Catalog.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Catalog.js +29 -29
- package/dist/internal/routes/Catalog.js.map +1 -0
- package/dist/internal/{funding → routes}/Chain.d.ts +10 -10
- package/dist/internal/routes/Chain.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Chain.js +3 -3
- package/dist/internal/routes/Chain.js.map +1 -0
- package/dist/internal/{funding → routes}/Deposit.d.ts +45 -23
- package/dist/internal/routes/Deposit.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Deposit.js +60 -27
- package/dist/internal/routes/Deposit.js.map +1 -0
- package/dist/internal/{funding → routes}/DepositAddress.d.ts +56 -27
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/DepositAddress.js +95 -33
- package/dist/internal/routes/DepositAddress.js.map +1 -0
- package/dist/internal/{funding → routes}/DepositWebhook.d.ts +4 -4
- package/dist/internal/routes/DepositWebhook.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/DepositWebhook.js +4 -4
- package/dist/internal/routes/DepositWebhook.js.map +1 -0
- package/dist/internal/routes/Economics.d.ts +25 -0
- package/dist/internal/routes/Economics.d.ts.map +1 -0
- package/dist/internal/routes/Economics.js +28 -0
- package/dist/internal/routes/Economics.js.map +1 -0
- package/dist/internal/{funding → routes}/Evidence.d.ts +3 -3
- package/dist/internal/routes/Evidence.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Evidence.js +7 -7
- package/dist/internal/routes/Evidence.js.map +1 -0
- package/dist/internal/routes/Observability.d.ts +154 -0
- package/dist/internal/routes/Observability.d.ts.map +1 -0
- package/dist/internal/routes/Observability.js +389 -0
- package/dist/internal/routes/Observability.js.map +1 -0
- package/dist/internal/{funding → routes}/Provider.d.ts +311 -105
- package/dist/internal/routes/Provider.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Provider.js +229 -98
- package/dist/internal/routes/Provider.js.map +1 -0
- package/dist/internal/{funding → routes}/Reconciliation.d.ts +11 -6
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Reconciliation.js +408 -158
- package/dist/internal/routes/Reconciliation.js.map +1 -0
- package/dist/internal/routes/Route.d.ts +21 -0
- package/dist/internal/routes/Route.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Route.js +1 -1
- package/dist/internal/routes/Route.js.map +1 -0
- package/dist/internal/{funding → routes}/SourceObservation.d.ts +6 -6
- package/dist/internal/routes/SourceObservation.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/SourceObservation.js +8 -8
- package/dist/internal/routes/SourceObservation.js.map +1 -0
- package/dist/internal/{funding → routes}/Subsidy.d.ts +48 -3
- package/dist/internal/routes/Subsidy.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Subsidy.js +43 -3
- package/dist/internal/routes/Subsidy.js.map +1 -0
- package/dist/internal/{funding → routes}/Token.d.ts +4 -4
- package/dist/internal/routes/Token.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/Token.js +3 -3
- package/dist/internal/routes/Token.js.map +1 -0
- package/dist/internal/{funding → routes}/Transfer.d.ts +241 -46
- package/dist/internal/routes/Transfer.d.ts.map +1 -0
- package/dist/internal/routes/Transfer.js +728 -0
- package/dist/internal/routes/Transfer.js.map +1 -0
- package/dist/internal/{funding → routes}/TransferReconciliation.d.ts +13 -10
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -0
- package/dist/internal/routes/TransferReconciliation.js +422 -0
- package/dist/internal/routes/TransferReconciliation.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +201 -0
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TransferSubsidy.js +256 -0
- package/dist/internal/routes/TransferSubsidy.js.map +1 -0
- package/dist/internal/{funding → routes}/TransferWebhook.d.ts +5 -5
- package/dist/internal/routes/TransferWebhook.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/TransferWebhook.js +3 -3
- package/dist/internal/routes/TransferWebhook.js.map +1 -0
- package/dist/internal/{funding → routes}/index.d.ts +2 -0
- package/dist/internal/routes/index.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/index.js +2 -0
- package/dist/internal/routes/index.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/across.d.ts +4 -4
- package/dist/internal/routes/providers/across.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/across.js +13 -13
- package/dist/internal/routes/providers/across.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/relay.d.ts +21 -12
- package/dist/internal/routes/providers/relay.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/relay.js +194 -110
- package/dist/internal/routes/providers/relay.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/rhino.d.ts +4 -4
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/rhino.js +10 -10
- package/dist/internal/routes/providers/rhino.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/squid.d.ts +4 -4
- package/dist/internal/routes/providers/squid.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/squid.js +14 -14
- package/dist/internal/routes/providers/squid.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/stargate.d.ts +46 -18
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -0
- package/dist/internal/routes/providers/stargate.js +898 -0
- package/dist/internal/routes/providers/stargate.js.map +1 -0
- package/dist/internal/{funding → routes}/providers/symbiosis.d.ts +4 -4
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -0
- package/dist/internal/{funding → routes}/providers/symbiosis.js +30 -20
- package/dist/internal/routes/providers/symbiosis.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.js +12 -12
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/dist/providers/index.d.ts +12 -12
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +12 -12
- package/dist/providers/index.js.map +1 -1
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +19 -0
- package/dist/server.js.map +1 -0
- package/package.json +15 -4
- package/src/ApiKey.ts +1 -1
- package/src/ApiKeys.test.ts +1033 -3
- package/src/ApiKeys.ts +489 -48
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +216 -25
- package/src/App.ts +334 -31
- package/src/Assets.test.ts +2 -2
- package/src/Assets.ts +3 -1
- package/src/Auth.test-d.ts +1 -1
- package/src/Client.test-d.ts +539 -110
- package/src/Handler.ts +0 -1
- package/src/OpenApi.contract.test.ts +195 -0
- package/src/Scope.ts +17 -5
- package/src/Webhooks.ts +1 -1
- package/src/admin/App.test.ts +30 -2
- package/src/admin/App.ts +42 -6
- package/src/admin/apps/api-keys.test.ts +267 -5
- package/src/admin/apps/api-keys.ts +100 -50
- package/src/admin/apps/earn-vaults.test.ts +158 -0
- package/src/admin/apps/earn-vaults.ts +679 -6
- package/src/admin/apps/organizations.test.ts +306 -17
- package/src/admin/apps/organizations.ts +299 -24
- package/src/admin/apps/routes-support.test.ts +200 -0
- package/src/admin/apps/routes-support.ts +201 -0
- package/src/admin/apps/routes.test.ts +450 -0
- package/src/admin/apps/routes.ts +896 -0
- package/src/admin/apps/scopes.test.ts +15 -5
- package/src/admin/apps/subsidies.test.ts +306 -0
- package/src/admin/apps/subsidies.ts +457 -0
- package/src/admin/apps/verified-tokens.test.ts +40 -3
- package/src/admin/apps/verified-tokens.ts +33 -7
- package/src/admin/ui/plugin.ts +1 -2
- package/src/admin/ui/src/components/RewardCampaignForm.tsx +1009 -0
- package/src/admin/ui/src/lib/config.ts +11 -2
- package/src/admin/ui/src/lib/earn-vaults.ts +2 -2
- package/src/admin/ui/src/lib/organizations.test.ts +83 -50
- package/src/admin/ui/src/lib/organizations.ts +106 -25
- package/src/admin/ui/src/lib/query-client.ts +1 -1
- package/src/admin/ui/src/lib/reward-campaigns.ts +136 -0
- package/src/admin/ui/src/lib/routes.test.ts +88 -0
- package/src/admin/ui/src/lib/routes.ts +304 -0
- package/src/admin/ui/src/lib/subsidies.ts +75 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +24 -9
- package/src/admin/ui/src/routeTree.gen.ts +63 -0
- package/src/admin/ui/src/routes/__root.tsx +13 -2
- package/src/admin/ui/src/routes/api-keys.tsx +196 -84
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +105 -70
- package/src/admin/ui/src/routes/organizations.tsx +34 -4
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +239 -23
- package/src/admin/ui/src/routes/routes.tsx +1615 -0
- package/src/admin/ui/src/routes/routes_.support.tsx +248 -0
- package/src/admin/ui/src/routes/subsidies.tsx +799 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +64 -20
- package/src/admin/ui.generated.ts +202 -188
- package/src/analytics/Analytics.test.ts +108 -18
- package/src/analytics/Analytics.ts +38 -6
- package/src/analytics/tables/requestEvents.test.ts +100 -0
- package/src/analytics/tables/requestEvents.ts +10 -1
- package/src/analytics/tables/routesLifecycleIntervals.ts +140 -0
- package/src/apps/Zones.test.ts +15 -0
- package/src/apps/Zones.ts +52 -5
- package/src/apps/composition.test.ts +68 -60
- package/src/apps/data/App.test.ts +180 -2
- package/src/apps/data/App.ts +88 -28
- package/src/apps/data/routes/activities.test.ts +419 -7
- package/src/apps/data/routes/activities.ts +683 -216
- package/src/apps/data/routes/balances.test.ts +2 -2
- package/src/apps/data/routes/blocks.test.ts +46 -1
- package/src/apps/data/routes/coingecko.test.ts +419 -1
- package/src/apps/data/routes/coingecko.ts +309 -253
- package/src/apps/data/routes/earn.discovery.test.ts +274 -0
- package/src/apps/data/routes/earn.test.ts +1294 -17
- package/src/apps/data/routes/earn.ts +1838 -321
- package/src/apps/data/routes/exchanges.test.ts +12 -15
- package/src/apps/data/routes/fee-amm.test.ts +243 -0
- package/src/apps/data/routes/fee-amm.ts +201 -162
- package/src/apps/data/routes/indexer.test.ts +389 -0
- package/src/apps/data/routes/indexer.ts +165 -69
- package/src/apps/data/routes/receipts.test.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +384 -8
- package/src/apps/data/routes/rpc.ts +452 -227
- package/src/apps/data/routes/rpc.zone.test.ts +340 -0
- package/src/apps/data/routes/tokenlist.test.ts +285 -0
- package/src/apps/data/routes/tokenlist.ts +173 -88
- package/src/apps/data/routes/tokens.test.ts +93 -3
- package/src/apps/data/routes/tokens.ts +39 -23
- package/src/apps/data/routes/transactions.test.ts +1 -1
- package/src/apps/data/routes/transfers.test.ts +56 -24
- package/src/apps/data/routes/transfers.ts +19 -8
- package/src/apps/data/routes/valuation.test.ts +1 -1
- package/src/apps/data/routes/verified-tokens.test.ts +345 -0
- package/src/apps/data/routes/verified-tokens.ts +99 -29
- package/src/apps/data/routes/webhooks.scan.test.ts +29 -0
- package/src/apps/data/routes/webhooks.test.ts +651 -83
- package/src/apps/data/routes/webhooks.ts +1113 -868
- package/src/apps/data/routes/zones.test.ts +148 -71
- package/src/apps/data/routes/zones.ts +71 -55
- package/src/apps/docs/reference.ts +2 -2
- package/src/apps/index.ts +1 -1
- package/src/apps/management/App.ts +9 -51
- package/src/apps/management/Billing.test.ts +375 -14
- package/src/apps/management/Billing.ts +265 -29
- package/src/apps/management/routes/api-keys.test.ts +269 -7
- package/src/apps/management/routes/api-keys.ts +61 -20
- package/src/apps/management/routes/billing.test.ts +477 -15
- package/src/apps/management/routes/billing.ts +377 -50
- package/src/apps/management/routes/faucet.test.ts +1 -1
- package/src/apps/management/routes/faucet.ts +1 -1
- package/src/apps/management/routes/invitations.test.ts +270 -3
- package/src/apps/management/routes/invitations.ts +185 -15
- package/src/apps/management/routes/invoicePreview.test.ts +549 -0
- package/src/apps/management/routes/me.test.ts +246 -5
- package/src/apps/management/routes/me.ts +7 -2
- package/src/apps/management/routes/members.test.ts +108 -0
- package/src/apps/management/routes/orgs.test.ts +191 -3
- package/src/apps/management/routes/orgs.ts +58 -11
- package/src/apps/management/routes/projects.test.ts +33 -3
- package/src/apps/management/routes/projects.ts +6 -1
- package/src/apps/management/routes/scopes.test.ts +30 -2
- package/src/apps/management/routes/scopes.ts +4 -1
- package/src/apps/management/routes/usage.test.ts +32 -0
- package/src/apps/management/routes/usage.ts +22 -4
- 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/management/routes/webhooks.test.ts +49 -26
- package/src/apps/management/routes/webhooks.ts +78 -22
- package/src/apps/mcp.test.ts +113 -30
- package/src/apps/mcp.ts +22 -10
- package/src/apps/mpp/App.ts +37 -7
- package/src/apps/mpp/Mpp.test.ts +49 -8
- package/src/apps/mpp/Mpp.zone.test.ts +219 -0
- package/src/apps/mpp/internal/Adapter.ts +34 -0
- package/src/apps/mpp/internal/Policy.test.ts +86 -31
- package/src/apps/mpp/internal/Policy.ts +49 -7
- package/src/apps/mpp/internal/Sponsorship.test.ts +207 -0
- package/src/apps/mpp/internal/Sponsorship.ts +9 -3
- package/src/apps/relay/App.test.ts +839 -64
- package/src/apps/relay/App.ts +148 -81
- package/src/apps/relay/App.zone-billing.test.ts +257 -0
- package/src/apps/relay/Sponsorships.test.ts +67 -4
- package/src/apps/relay/Sponsorships.ts +233 -32
- package/src/apps/relay/Sponsorships.zone.test.ts +102 -0
- package/src/apps/{funding → routes}/Access.ts +6 -6
- package/src/apps/routes/App.test.ts +165 -0
- package/src/apps/routes/App.ts +96 -0
- package/src/apps/{funding → routes}/Inventory.ts +2 -2
- package/src/apps/routes/index.ts +1 -0
- package/src/apps/{funding → routes}/routes/chains.test.ts +66 -66
- package/src/apps/{funding → routes}/routes/chains.ts +23 -23
- package/src/apps/{funding → routes}/routes/deposit-addresses.test.ts +1358 -458
- package/src/apps/{funding → routes}/routes/deposit-addresses.ts +566 -246
- package/src/apps/{funding → routes}/routes/providers.test.ts +27 -33
- package/src/apps/{funding → routes}/routes/providers.ts +23 -23
- package/src/apps/{funding → routes}/routes/quotes.test.ts +298 -41
- package/src/apps/{funding → routes}/routes/quotes.ts +57 -40
- package/src/apps/{funding → routes}/routes/transfers.test.ts +1100 -353
- package/src/apps/routes/routes/transfers.ts +1332 -0
- package/src/cli/Cli.test.ts +1 -1
- package/src/cli/commands/admin.test.ts +748 -1
- package/src/cli/commands/admin.ts +278 -0
- package/src/cloudflare.ts +52 -47
- package/src/db/Db.test.ts +245 -2
- package/src/db/Db.ts +1485 -34
- package/src/db/Schema.ts +729 -228
- package/src/db/tables/apiKeyAdmissionBootstraps.ts +4 -0
- package/src/db/tables/apiKeyAdmissions.ts +218 -0
- package/src/db/tables/apiKeyOwnerAdmissions.ts +4 -0
- package/src/db/tables/apiKeyOwnerTombstones.ts +81 -0
- package/src/db/tables/apiKeyRevocations.test.ts +74 -0
- package/src/db/tables/apiKeyRevocations.ts +121 -0
- package/src/db/tables/authAccounts.ts +105 -0
- package/src/db/tables/authSessions.ts +13 -0
- package/src/db/tables/authVerifications.ts +13 -0
- package/src/db/tables/invitations.ts +142 -45
- package/src/db/tables/memberships.ts +79 -3
- package/src/db/tables/organizations.test.ts +690 -13
- package/src/db/tables/organizations.ts +139 -55
- package/src/db/tables/projects.test.ts +16 -0
- package/src/db/tables/projects.ts +13 -3
- package/src/db/tables/requestUsage.ts +4 -1
- package/src/db/tables/rewardAccounts.ts +178 -0
- package/src/db/tables/rewardCampaignDistributors.ts +68 -0
- package/src/db/tables/rewardCampaigns.test.ts +1388 -0
- package/src/db/tables/rewardCampaigns.ts +647 -0
- package/src/db/tables/rewardCredits.ts +110 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +271 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +184 -0
- package/src/db/tables/rewardRuns.ts +514 -0
- package/src/db/tables/rewardTransactionAttempts.ts +272 -0
- package/src/db/tables/routesCatalog.test.ts +185 -0
- package/src/db/tables/routesCatalog.ts +163 -0
- package/src/db/tables/routesDepositAddresses.test.ts +1048 -0
- package/src/db/tables/routesDepositAddresses.ts +1008 -0
- package/src/db/tables/{fundingDepositRequestObservations.test.ts → routesDepositRequestObservations.test.ts} +13 -14
- package/src/db/tables/{fundingDepositRequestObservations.ts → routesDepositRequestObservations.ts} +10 -10
- package/src/db/tables/{fundingDeposits.test.ts → routesDeposits.test.ts} +388 -46
- package/src/db/tables/routesDeposits.ts +1062 -0
- package/src/db/tables/routesIdempotency.test.ts +796 -0
- package/src/db/tables/routesIdempotency.ts +496 -0
- package/src/db/tables/routesSubsidies.test.ts +120 -0
- package/src/db/tables/routesSubsidies.ts +71 -0
- package/src/db/tables/{fundingTransferEvents.ts → routesTransferEvents.ts} +4 -4
- package/src/db/tables/routesTransferSubsidies.ts +38 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +124 -0
- package/src/db/tables/routesTransferTransactions.test.ts +195 -0
- package/src/db/tables/{fundingTransferTransactions.ts → routesTransferTransactions.ts} +63 -18
- package/src/db/tables/routesTransfers.test.ts +338 -0
- package/src/db/tables/routesTransfers.ts +662 -0
- package/src/db/tables/sponsoredTransactions.test.ts +269 -45
- package/src/db/tables/sponsoredTransactions.ts +225 -65
- package/src/db/tables/sponsorshipAttributions.test.ts +160 -0
- package/src/db/tables/sponsorshipAttributions.ts +168 -0
- package/src/db/tables/sponsorshipReconciliationCursors.test.ts +115 -0
- package/src/db/tables/sponsorshipReconciliationCursors.ts +67 -0
- package/src/db/tables/stripeCustomers.test.ts +85 -0
- package/src/db/tables/stripeCustomers.ts +24 -0
- package/src/db/tables/users.test.ts +129 -0
- package/src/db/tables/users.ts +49 -3
- package/src/db/tables/verifiedTokenRequests.test.ts +39 -20
- package/src/db/tables/verifiedTokenRequests.ts +80 -44
- package/src/db/tables/webhookQueueEvents.ts +8 -1
- package/src/db/tables/webhookSubscriptions.ts +95 -20
- package/src/handlers/internal/executionError.ts +3 -4
- package/src/handlers/internal/multisig.ts +13 -816
- package/src/handlers/internal/sponsorship.ts +26 -10
- package/src/handlers/relay.test-d.ts +9 -1
- package/src/handlers/relay.test.ts +823 -3
- package/src/handlers/relay.ts +127 -107
- package/src/index.test-d.ts +7 -0
- package/src/index.ts +0 -17
- package/src/internal/AssetResponse.ts +26 -0
- package/src/internal/Auth.test.ts +1656 -9
- package/src/internal/Auth.ts +880 -244
- package/src/internal/BetterAuth.test.ts +242 -0
- package/src/internal/BetterAuth.ts +349 -0
- package/src/internal/Cache.ts +2 -0
- package/src/internal/EarnRates.test.ts +17 -0
- package/src/internal/EarnRates.ts +124 -31
- package/src/internal/EarnSharePrices.test.ts +182 -0
- package/src/internal/EarnSharePrices.ts +313 -0
- package/src/internal/EarnVaults.test.ts +21 -0
- package/src/internal/EarnVaults.ts +33 -11
- package/src/internal/Email.ts +54 -0
- package/src/internal/Idempotency.test.ts +2 -2
- package/src/internal/Log.test-d.ts +8 -7
- package/src/internal/Log.test.ts +114 -16
- package/src/internal/Log.ts +53 -40
- package/src/internal/MetricSink.test.ts +313 -26
- package/src/internal/MetricSink.ts +73 -8
- package/src/internal/Mpp.test.ts +31 -0
- package/src/internal/Mpp.ts +21 -24
- package/src/internal/OpenApi.ts +45 -12
- package/src/internal/Provider.test.ts +1 -1
- package/src/internal/Provider.ts +1 -1
- package/src/internal/RateLimit.test.ts +21 -3
- package/src/internal/RateLimit.ts +12 -1
- package/src/internal/Store.test-d.ts +1 -1
- package/src/internal/Store.test.ts +151 -8
- package/src/internal/Store.ts +76 -9
- package/src/internal/Tidx.test.ts +59 -8
- package/src/internal/Tidx.ts +86 -14
- package/src/internal/Timing.test.ts +77 -0
- package/src/internal/Timing.ts +83 -6
- package/src/internal/VercelOidc.test.ts +188 -0
- package/src/internal/VercelOidc.ts +193 -0
- package/src/internal/VerifiedTokens.test.ts +60 -6
- package/src/internal/VerifiedTokens.ts +21 -24
- package/src/internal/Viem.batch.test.ts +80 -0
- package/src/internal/Viem.test.ts +201 -2
- package/src/internal/Viem.ts +221 -25
- package/src/internal/Webhooks.test.ts +85 -6
- package/src/internal/Webhooks.ts +22 -4
- package/src/internal/ZoneRpc.ts +50 -0
- package/src/internal/exchange/Provider.test.ts +2 -2
- package/src/internal/index.test.ts +3 -1
- package/src/internal/index.ts +3 -1
- package/src/internal/rewards/Audit.ts +231 -0
- package/src/internal/rewards/Campaigns.test.ts +1234 -0
- package/src/internal/rewards/Campaigns.ts +1205 -0
- package/src/internal/rewards/Credits.ts +165 -0
- package/src/internal/rewards/Events.local.test.ts +113 -0
- package/src/internal/rewards/Events.test.ts +152 -0
- package/src/internal/rewards/Events.ts +468 -0
- package/src/internal/rewards/Projection.test.ts +681 -0
- package/src/internal/rewards/Projection.ts +987 -0
- package/src/internal/rewards/Rates.test.ts +171 -0
- package/src/internal/rewards/Rates.ts +110 -0
- package/src/internal/rewards/Read.test.ts +501 -0
- package/src/internal/rewards/Read.ts +476 -0
- package/src/internal/rewards/Runner.checkpoint.test.ts +80 -0
- package/src/internal/rewards/Runner.states.test.ts +188 -0
- package/src/internal/rewards/Runner.test.ts +90 -0
- package/src/internal/rewards/Runner.ts +2229 -0
- package/src/internal/rewards/Signer.test.ts +79 -0
- package/src/internal/rewards/Signer.ts +180 -0
- package/src/internal/rewards/index.ts +14 -0
- package/src/internal/{funding → routes}/Action.test.ts +63 -14
- package/src/internal/{funding → routes}/Action.ts +35 -8
- package/src/internal/{funding → routes}/Catalog.test.ts +3 -3
- package/src/internal/{funding → routes}/Catalog.ts +39 -39
- package/src/internal/{funding → routes}/Chain.test.ts +1 -1
- package/src/internal/{funding → routes}/Chain.ts +11 -11
- package/src/internal/{funding → routes}/Deposit.test.ts +1 -1
- package/src/internal/{funding → routes}/Deposit.ts +93 -45
- package/src/internal/{funding → routes}/DepositAddress.test.ts +11 -3
- package/src/internal/{funding → routes}/DepositAddress.ts +132 -53
- package/src/internal/{funding → routes}/DepositWebhook.test.ts +61 -18
- package/src/internal/{funding → routes}/DepositWebhook.ts +9 -9
- package/src/internal/routes/Economics.test.ts +42 -0
- package/src/internal/routes/Economics.ts +47 -0
- package/src/internal/{funding → routes}/Evidence.test.ts +6 -6
- package/src/internal/{funding → routes}/Evidence.ts +9 -9
- package/src/internal/routes/Observability.test.ts +636 -0
- package/src/internal/routes/Observability.ts +668 -0
- package/src/internal/{funding → routes}/Provider.test.ts +489 -153
- package/src/internal/{funding → routes}/Provider.ts +489 -186
- package/src/internal/{funding → routes}/Reconciliation.local.test.ts +84 -12
- package/src/internal/{funding → routes}/Reconciliation.test.ts +1213 -279
- package/src/internal/{funding → routes}/Reconciliation.ts +501 -203
- package/src/internal/routes/Reconciliation.unattributed.test.ts +250 -0
- package/src/internal/{funding → routes}/Route.ts +7 -7
- package/src/internal/{funding → routes}/SourceObservation.test.ts +13 -14
- package/src/internal/{funding → routes}/SourceObservation.ts +13 -13
- package/src/internal/{funding → routes}/Subsidy.local.test.ts +7 -7
- package/src/internal/routes/Subsidy.test.ts +169 -0
- package/src/internal/{funding → routes}/Subsidy.ts +86 -6
- package/src/internal/{funding → routes}/Token.test.ts +1 -1
- package/src/internal/{funding → routes}/Token.ts +5 -5
- package/src/internal/routes/Transfer.test.ts +1199 -0
- package/src/internal/routes/Transfer.ts +1206 -0
- package/src/internal/routes/TransferReconciliation.test.ts +731 -0
- package/src/internal/routes/TransferReconciliation.ts +527 -0
- package/src/internal/routes/TransferSubsidy.test.ts +172 -0
- package/src/internal/routes/TransferSubsidy.ts +447 -0
- package/src/internal/{funding → routes}/TransferWebhook.test.ts +13 -13
- package/src/internal/{funding → routes}/TransferWebhook.ts +7 -7
- package/src/internal/{funding → routes}/index.test.ts +5 -3
- package/src/internal/{funding → routes}/index.ts +2 -0
- package/src/internal/{funding → routes}/providers/across.ts +16 -16
- package/src/internal/{funding → routes}/providers/index.test.ts +157 -44
- package/src/internal/{funding → routes}/providers/relay.test.ts +224 -32
- package/src/internal/{funding → routes}/providers/relay.ts +228 -121
- package/src/internal/{funding → routes}/providers/rhino.ts +16 -16
- package/src/internal/{funding → routes}/providers/squid.ts +17 -17
- package/src/internal/routes/providers/stargate.test.ts +728 -0
- package/src/internal/routes/providers/stargate.ts +1276 -0
- package/src/internal/{funding → routes}/providers/symbiosis.ts +64 -24
- package/src/internal/webhookDestinations/slack.ts +10 -10
- package/src/providers/index.ts +13 -13
- package/src/server.ts +18 -0
- package/dist/apps/funding/Access.d.ts.map +0 -1
- package/dist/apps/funding/Access.js.map +0 -1
- package/dist/apps/funding/App.js.map +0 -1
- package/dist/apps/funding/Inventory.d.ts.map +0 -1
- package/dist/apps/funding/Inventory.js.map +0 -1
- package/dist/apps/funding/ProviderAttempts.d.ts +0 -5
- package/dist/apps/funding/ProviderAttempts.d.ts.map +0 -1
- package/dist/apps/funding/ProviderAttempts.js +0 -24
- package/dist/apps/funding/ProviderAttempts.js.map +0 -1
- package/dist/apps/funding/index.d.ts +0 -2
- package/dist/apps/funding/index.d.ts.map +0 -1
- package/dist/apps/funding/index.js +0 -2
- package/dist/apps/funding/index.js.map +0 -1
- package/dist/apps/funding/routes/chains.d.ts.map +0 -1
- package/dist/apps/funding/routes/chains.js.map +0 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +0 -1
- package/dist/apps/funding/routes/deposit-addresses.js.map +0 -1
- package/dist/apps/funding/routes/providers.d.ts.map +0 -1
- package/dist/apps/funding/routes/providers.js +0 -57
- package/dist/apps/funding/routes/providers.js.map +0 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +0 -1
- package/dist/apps/funding/routes/quotes.js.map +0 -1
- package/dist/apps/funding/routes/transfers.d.ts.map +0 -1
- package/dist/apps/funding/routes/transfers.js +0 -828
- package/dist/apps/funding/routes/transfers.js.map +0 -1
- package/dist/db/tables/fundingCatalog.d.ts +0 -58
- package/dist/db/tables/fundingCatalog.d.ts.map +0 -1
- package/dist/db/tables/fundingCatalog.js.map +0 -1
- package/dist/db/tables/fundingDepositAddresses.d.ts +0 -192
- package/dist/db/tables/fundingDepositAddresses.d.ts.map +0 -1
- package/dist/db/tables/fundingDepositAddresses.js +0 -235
- package/dist/db/tables/fundingDepositAddresses.js.map +0 -1
- package/dist/db/tables/fundingDepositRequestObservations.d.ts.map +0 -1
- package/dist/db/tables/fundingDepositRequestObservations.js.map +0 -1
- package/dist/db/tables/fundingDeposits.d.ts.map +0 -1
- package/dist/db/tables/fundingDeposits.js +0 -295
- package/dist/db/tables/fundingDeposits.js.map +0 -1
- package/dist/db/tables/fundingIdempotency.d.ts +0 -91
- package/dist/db/tables/fundingIdempotency.d.ts.map +0 -1
- package/dist/db/tables/fundingIdempotency.js +0 -103
- package/dist/db/tables/fundingIdempotency.js.map +0 -1
- package/dist/db/tables/fundingTransferEvents.d.ts.map +0 -1
- package/dist/db/tables/fundingTransferEvents.js.map +0 -1
- package/dist/db/tables/fundingTransferTransactions.d.ts +0 -53
- package/dist/db/tables/fundingTransferTransactions.d.ts.map +0 -1
- package/dist/db/tables/fundingTransferTransactions.js.map +0 -1
- package/dist/db/tables/fundingTransfers.d.ts +0 -99
- package/dist/db/tables/fundingTransfers.d.ts.map +0 -1
- package/dist/db/tables/fundingTransfers.js +0 -110
- package/dist/db/tables/fundingTransfers.js.map +0 -1
- package/dist/internal/funding/Action.d.ts.map +0 -1
- package/dist/internal/funding/Action.js.map +0 -1
- package/dist/internal/funding/Catalog.d.ts.map +0 -1
- package/dist/internal/funding/Catalog.js.map +0 -1
- package/dist/internal/funding/Chain.d.ts.map +0 -1
- package/dist/internal/funding/Chain.js.map +0 -1
- package/dist/internal/funding/Deposit.d.ts.map +0 -1
- package/dist/internal/funding/Deposit.js.map +0 -1
- package/dist/internal/funding/DepositAddress.d.ts.map +0 -1
- package/dist/internal/funding/DepositAddress.js.map +0 -1
- package/dist/internal/funding/DepositWebhook.d.ts.map +0 -1
- package/dist/internal/funding/DepositWebhook.js.map +0 -1
- package/dist/internal/funding/Evidence.d.ts.map +0 -1
- package/dist/internal/funding/Evidence.js.map +0 -1
- package/dist/internal/funding/Provider.d.ts.map +0 -1
- package/dist/internal/funding/Provider.js.map +0 -1
- package/dist/internal/funding/Reconciliation.d.ts.map +0 -1
- package/dist/internal/funding/Reconciliation.js.map +0 -1
- package/dist/internal/funding/Route.d.ts +0 -21
- package/dist/internal/funding/Route.d.ts.map +0 -1
- package/dist/internal/funding/Route.js.map +0 -1
- package/dist/internal/funding/SourceObservation.d.ts.map +0 -1
- package/dist/internal/funding/SourceObservation.js.map +0 -1
- package/dist/internal/funding/Subsidy.d.ts.map +0 -1
- package/dist/internal/funding/Subsidy.js.map +0 -1
- package/dist/internal/funding/Token.d.ts.map +0 -1
- package/dist/internal/funding/Token.js.map +0 -1
- package/dist/internal/funding/Transfer.d.ts.map +0 -1
- package/dist/internal/funding/Transfer.js +0 -462
- package/dist/internal/funding/Transfer.js.map +0 -1
- package/dist/internal/funding/TransferReconciliation.d.ts.map +0 -1
- package/dist/internal/funding/TransferReconciliation.js +0 -192
- package/dist/internal/funding/TransferReconciliation.js.map +0 -1
- package/dist/internal/funding/TransferWebhook.d.ts.map +0 -1
- package/dist/internal/funding/TransferWebhook.js.map +0 -1
- package/dist/internal/funding/index.d.ts.map +0 -1
- package/dist/internal/funding/index.js.map +0 -1
- package/dist/internal/funding/providers/across.d.ts.map +0 -1
- package/dist/internal/funding/providers/across.js.map +0 -1
- package/dist/internal/funding/providers/relay.d.ts.map +0 -1
- package/dist/internal/funding/providers/relay.js.map +0 -1
- package/dist/internal/funding/providers/rhino.d.ts.map +0 -1
- package/dist/internal/funding/providers/rhino.js.map +0 -1
- package/dist/internal/funding/providers/squid.d.ts.map +0 -1
- package/dist/internal/funding/providers/squid.js.map +0 -1
- package/dist/internal/funding/providers/stargate.d.ts.map +0 -1
- package/dist/internal/funding/providers/stargate.js +0 -579
- package/dist/internal/funding/providers/stargate.js.map +0 -1
- package/dist/internal/funding/providers/symbiosis.d.ts.map +0 -1
- package/dist/internal/funding/providers/symbiosis.js.map +0 -1
- package/src/apps/funding/App.test.ts +0 -78
- package/src/apps/funding/App.ts +0 -88
- package/src/apps/funding/ProviderAttempts.ts +0 -26
- package/src/apps/funding/index.ts +0 -1
- package/src/apps/funding/routes/transfers.ts +0 -987
- package/src/db/tables/fundingCatalog.test.ts +0 -122
- package/src/db/tables/fundingCatalog.ts +0 -163
- package/src/db/tables/fundingDepositAddresses.test.ts +0 -608
- package/src/db/tables/fundingDepositAddresses.ts +0 -443
- package/src/db/tables/fundingDeposits.ts +0 -572
- package/src/db/tables/fundingIdempotency.test.ts +0 -182
- package/src/db/tables/fundingIdempotency.ts +0 -180
- package/src/db/tables/fundingTransferTransactions.test.ts +0 -112
- package/src/db/tables/fundingTransfers.test.ts +0 -115
- package/src/db/tables/fundingTransfers.ts +0 -189
- package/src/handlers/internal/multisig.test.ts +0 -818
- package/src/internal/funding/Subsidy.test.ts +0 -75
- package/src/internal/funding/Transfer.test.ts +0 -524
- package/src/internal/funding/Transfer.ts +0 -762
- package/src/internal/funding/TransferReconciliation.test.ts +0 -147
- package/src/internal/funding/TransferReconciliation.ts +0 -264
- package/src/internal/funding/providers/stargate.test.ts +0 -328
- package/src/internal/funding/providers/stargate.ts +0 -856
- /package/dist/apps/{funding → routes}/Inventory.d.ts +0 -0
- /package/src/internal/{funding → routes}/Route.test.ts +0 -0
package/src/internal/Auth.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import * as Accounts from 'accounts/server'
|
|
2
|
+
import { splitSetCookieHeader } from 'better-auth/cookies'
|
|
2
3
|
import { Hono } from 'hono'
|
|
3
4
|
import type { Context as hono_Context, MiddlewareHandler } from 'hono'
|
|
5
|
+
import { deleteCookie, getCookie, setCookie } from 'hono/cookie'
|
|
4
6
|
import type { HonoBase } from 'hono/hono-base'
|
|
5
7
|
import { createMiddleware } from 'hono/factory'
|
|
6
8
|
import { matchedRoutes } from 'hono/route'
|
|
7
9
|
import type { MergePath, RouterRoute, Schema as core_Schema } from 'hono/types'
|
|
8
10
|
import { findTargetHandler } from 'hono/utils/handler'
|
|
11
|
+
import * as jose from 'jose'
|
|
12
|
+
import { sql } from 'kysely'
|
|
9
13
|
import { Challenge, Credential, type Method } from 'mppx'
|
|
10
14
|
import { Mppx, tempo } from 'mppx/hono'
|
|
15
|
+
import { Address, Hex } from 'ox'
|
|
11
16
|
import { Addresses } from 'viem/tempo'
|
|
12
17
|
import { tempoMainnet } from 'viem/tempo/chains'
|
|
13
18
|
import * as z from 'zod/mini'
|
|
@@ -15,25 +20,69 @@ import * as z from 'zod/mini'
|
|
|
15
20
|
import type * as App from '../App.js'
|
|
16
21
|
import * as ApiKey from '../ApiKey.js'
|
|
17
22
|
import * as ApiKeys from '../ApiKeys.js'
|
|
23
|
+
import * as ApiKeyAdmissions from '../db/tables/apiKeyAdmissions.js'
|
|
24
|
+
import * as ApiKeyOwnerTombstones from '../db/tables/apiKeyOwnerTombstones.js'
|
|
25
|
+
import * as AuthAccounts from '../db/tables/authAccounts.js'
|
|
26
|
+
import * as BetterAuth from './BetterAuth.js'
|
|
18
27
|
import * as Db from '../db/Db.js'
|
|
19
|
-
import type * as
|
|
28
|
+
import type * as Email from './Email.js'
|
|
20
29
|
import * as Memberships from '../db/tables/memberships.js'
|
|
21
30
|
import * as IpAllowlist from './IpAllowlist.js'
|
|
22
31
|
import * as Metadata from '../apps/metadata.js'
|
|
23
32
|
import * as OpenApi from './OpenApi.js'
|
|
24
33
|
import * as Organizations from '../db/tables/organizations.js'
|
|
34
|
+
import * as Path from './Path.js'
|
|
25
35
|
import * as Projects from '../db/tables/projects.js'
|
|
26
36
|
import * as RateLimit from './RateLimit.js'
|
|
27
37
|
import * as Response from './Response.js'
|
|
28
38
|
import * as Schema from './Schema.js'
|
|
29
39
|
import * as Scope from '../Scope.js'
|
|
40
|
+
import type * as Store from './Store.js'
|
|
41
|
+
import * as Timing from './Timing.js'
|
|
30
42
|
import * as Users from '../db/tables/users.js'
|
|
31
43
|
import type * as Viem from './Viem.js'
|
|
32
44
|
|
|
33
45
|
const policySymbol = Symbol('tempo-api.auth.policy')
|
|
34
46
|
const mppManagementSymbol = Symbol('tempo-api.auth.mpp-management')
|
|
47
|
+
const trustedClientIps = new WeakMap<Request, string>()
|
|
35
48
|
const defaultApiKeyRateLimit = { limit: 10_000, period: 'minute' } satisfies RateLimit.Limit
|
|
49
|
+
const defaultIdentitySessionTtl = 24 * 60 * 60
|
|
36
50
|
const defaultMppRateLimit = { limit: 100, period: 'minute' } satisfies RateLimit.Limit
|
|
51
|
+
const defaultPublicRateLimit = { limit: 60, period: 'minute' } satisfies RateLimit.Limit
|
|
52
|
+
const identityCookieName = 'tempo_identity'
|
|
53
|
+
const walletIdentityIssuer = 'https://wallet.tempo.xyz/api/oidc'
|
|
54
|
+
|
|
55
|
+
type IdentitySession = {
|
|
56
|
+
/** Wallet address asserted by the identity token. */
|
|
57
|
+
address: string
|
|
58
|
+
/** Verified email asserted by the identity token. */
|
|
59
|
+
email?: string | undefined
|
|
60
|
+
/** Unix timestamp when the session expires. */
|
|
61
|
+
expiresAt: number
|
|
62
|
+
/** Unix timestamp when the session was issued. */
|
|
63
|
+
issuedAt: number
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type WalletSession = {
|
|
67
|
+
/** Wallet address used to resolve the canonical user. */
|
|
68
|
+
address: string
|
|
69
|
+
/** Verified email used to reconcile the canonical user. */
|
|
70
|
+
email?: string | undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function isIdentityTokenError(error: unknown) {
|
|
74
|
+
return (
|
|
75
|
+
error instanceof jose.errors.JOSEAlgNotAllowed ||
|
|
76
|
+
error instanceof jose.errors.JOSENotSupported ||
|
|
77
|
+
error instanceof jose.errors.JWSInvalid ||
|
|
78
|
+
error instanceof jose.errors.JWKSNoMatchingKey ||
|
|
79
|
+
error instanceof jose.errors.JWSSignatureVerificationFailed ||
|
|
80
|
+
error instanceof jose.errors.JWTClaimValidationFailed ||
|
|
81
|
+
error instanceof jose.errors.JWTExpired ||
|
|
82
|
+
error instanceof jose.errors.JWTInvalid ||
|
|
83
|
+
(error instanceof Error && error.message === 'email not verified')
|
|
84
|
+
)
|
|
85
|
+
}
|
|
37
86
|
|
|
38
87
|
/** Auth context consumed by Tempo API handlers. */
|
|
39
88
|
export type Context = {
|
|
@@ -95,7 +144,10 @@ export type Payment = {
|
|
|
95
144
|
type: 'mpp'
|
|
96
145
|
}
|
|
97
146
|
|
|
98
|
-
/**
|
|
147
|
+
/** Host-provided request backstop that returns a rejection response when over quota. */
|
|
148
|
+
export type EdgeRateLimit = (request: Request) => Promise<Response | undefined>
|
|
149
|
+
|
|
150
|
+
/** MPP route-policy types. Distinct from the authentication {@link Session} capability. */
|
|
99
151
|
export declare namespace Mpp {
|
|
100
152
|
/** MPP Session request options used by route access policies. */
|
|
101
153
|
type Session = Method.RequestDefaults<ReturnType<typeof tempo.session>> & {
|
|
@@ -135,6 +187,8 @@ export type PolicyOverride = {
|
|
|
135
187
|
/** API-key lane: pass quota/scopes overrides, or a boolean to enable/disable. */
|
|
136
188
|
apiKey?:
|
|
137
189
|
| {
|
|
190
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
191
|
+
bucket?: string | undefined
|
|
138
192
|
/** API-key quota override for this route (a protective per-route cap). */
|
|
139
193
|
rateLimit?: RateLimit.Limit | undefined
|
|
140
194
|
/** Required API-key scopes override for this route. */
|
|
@@ -145,6 +199,8 @@ export type PolicyOverride = {
|
|
|
145
199
|
/** MPP paid lane: object to override the Session request, or boolean to enable/disable. */
|
|
146
200
|
mpp?:
|
|
147
201
|
| {
|
|
202
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
203
|
+
bucket?: string | undefined
|
|
148
204
|
/** Paid-request quota override for this route (a protective per-route cap). */
|
|
149
205
|
rateLimit?: RateLimit.Limit | undefined
|
|
150
206
|
/** Tempo Session request override for this route. */
|
|
@@ -155,12 +211,14 @@ export type PolicyOverride = {
|
|
|
155
211
|
/** Public lane: object to override the quota, or boolean to enable/disable. */
|
|
156
212
|
public?:
|
|
157
213
|
| {
|
|
214
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
215
|
+
bucket?: string | undefined
|
|
158
216
|
/** Anonymous public quota override for this route. */
|
|
159
217
|
rateLimit?: RateLimit.Limit | undefined
|
|
160
218
|
}
|
|
161
219
|
| boolean
|
|
162
220
|
| undefined
|
|
163
|
-
/** Session lane: `true` allows signed-in
|
|
221
|
+
/** Session lane: `true` allows signed-in sessions, `false` disables. */
|
|
164
222
|
session?: boolean | undefined
|
|
165
223
|
}
|
|
166
224
|
|
|
@@ -197,7 +255,7 @@ export type Principal =
|
|
|
197
255
|
id: string
|
|
198
256
|
/** Identity that established the session, as a provider/subject pair (OIDC `iss`/`sub` semantics). */
|
|
199
257
|
identity: {
|
|
200
|
-
/** Identity provider: `wallet
|
|
258
|
+
/** Identity provider: `email`, `wallet`, or an OIDC issuer. */
|
|
201
259
|
provider: string
|
|
202
260
|
/** Provider-scoped subject — the wallet address for `wallet`. */
|
|
203
261
|
subject: string
|
|
@@ -237,6 +295,17 @@ export function getPrincipal<environment extends Environment>(c: hono_Context<en
|
|
|
237
295
|
return c.get('principal') ?? null
|
|
238
296
|
}
|
|
239
297
|
|
|
298
|
+
/** Resolves the caller IP from configured trusted metadata. */
|
|
299
|
+
export function getTrustedClientIp<environment extends Environment>(c: hono_Context<environment>) {
|
|
300
|
+
const auth = c.get('auth')
|
|
301
|
+
return auth ? trustedClientIp(c, auth) : resolveTrustedClientIp(c.req.raw, undefined)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Marks a synthesized in-process request with its trusted caller IP address. */
|
|
305
|
+
export function trustClientIp(request: Request, address: string) {
|
|
306
|
+
trustedClientIps.set(request, address)
|
|
307
|
+
}
|
|
308
|
+
|
|
240
309
|
/**
|
|
241
310
|
* Guards `:orgId` routes and resolves the organization. Sessions require membership, API keys require ownership, and the super admin bypasses ownership.
|
|
242
311
|
*/
|
|
@@ -504,6 +573,20 @@ export function middleware<
|
|
|
504
573
|
endpoint extends string = string,
|
|
505
574
|
environment extends Environment = Environment,
|
|
506
575
|
>(options: middleware.Options<endpoint>): MiddlewareHandler<environment> {
|
|
576
|
+
const resolve = createApiKeyResolver({
|
|
577
|
+
apiKey: options.apiKey,
|
|
578
|
+
scopeCatalog: options.scopeCatalog,
|
|
579
|
+
})
|
|
580
|
+
return createAuthMiddleware(options, resolve)
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function createAuthMiddleware<
|
|
584
|
+
endpoint extends string = string,
|
|
585
|
+
environment extends Environment = Environment,
|
|
586
|
+
>(
|
|
587
|
+
options: middleware.Options<endpoint>,
|
|
588
|
+
resolve: ReturnType<typeof createApiKeyResolver>,
|
|
589
|
+
): MiddlewareHandler<environment> {
|
|
507
590
|
const {
|
|
508
591
|
rateLimit: mppRateLimit = defaultMppRateLimit,
|
|
509
592
|
session: session_ = {},
|
|
@@ -522,23 +605,13 @@ export function middleware<
|
|
|
522
605
|
// keyed by token sha256) so hot keys skip the backend read on the auth path
|
|
523
606
|
// of every request. Pass `apiKey.cache: false` when immediate key updates
|
|
524
607
|
// matter more than the per-request read.
|
|
525
|
-
const resolve = (() => {
|
|
526
|
-
const uncached = (c: hono_Context, token: string) => {
|
|
527
|
-
const kv = contextKv(c)
|
|
528
|
-
return kv
|
|
529
|
-
? ApiKeys.resolve(kv.store, token, { scopeCatalog: options.scopeCatalog })
|
|
530
|
-
: Promise.resolve(null)
|
|
531
|
-
}
|
|
532
|
-
if (options.apiKey === false || options.apiKey?.cache === false) return uncached
|
|
533
|
-
return cachedResolve(uncached, options.apiKey?.cache ?? {})
|
|
534
|
-
})()
|
|
535
608
|
const auth: Context = {
|
|
536
609
|
...(options.apiKey === false
|
|
537
610
|
? {}
|
|
538
611
|
: {
|
|
539
612
|
apiKey: {
|
|
540
613
|
...(options.apiKey?.rateLimits ? { rateLimits: options.apiKey.rateLimits } : {}),
|
|
541
|
-
resolve,
|
|
614
|
+
resolve: resolve.resolve,
|
|
542
615
|
},
|
|
543
616
|
}),
|
|
544
617
|
// The throttle ceiling for sandbox keys without active billing, so
|
|
@@ -580,38 +653,125 @@ export function middleware<
|
|
|
580
653
|
}
|
|
581
654
|
|
|
582
655
|
return createMiddleware<environment>((c, next) => {
|
|
583
|
-
const
|
|
584
|
-
if (!
|
|
585
|
-
|
|
586
|
-
const { key, description, management, scope } = route
|
|
587
|
-
const overrides = options.overrides as
|
|
588
|
-
| Record<string, PolicyOverride | false | undefined>
|
|
589
|
-
| undefined
|
|
590
|
-
const routePolicies = policies(c)
|
|
591
|
-
const configuredOverride = (() => {
|
|
592
|
-
const configured = overrides?.[key]
|
|
593
|
-
if (configured !== undefined) return configured
|
|
594
|
-
const inheritedMethod = routePolicies.find(
|
|
595
|
-
(policy) => policy.inheritOverridesFrom,
|
|
596
|
-
)?.inheritOverridesFrom
|
|
597
|
-
if (inheritedMethod === undefined) return undefined
|
|
598
|
-
const inheritedKey = `${inheritedMethod.toUpperCase()} ${key.slice(key.indexOf(' ') + 1)}`
|
|
599
|
-
return overrides?.[inheritedKey]
|
|
600
|
-
})()
|
|
601
|
-
const routeOverride =
|
|
602
|
-
management && configuredOverride ? { mpp: configuredOverride.mpp } : configuredOverride
|
|
603
|
-
const endpointPolicy = bindMppScope(
|
|
604
|
-
resolvePolicy(base, defaults, [...routePolicies, routeOverride], description),
|
|
605
|
-
scope,
|
|
606
|
-
)
|
|
607
|
-
if (!endpointPolicy) return next()
|
|
608
|
-
if (management && (!auth.mpp || !endpointPolicy.mpp)) return next()
|
|
656
|
+
const resolved = resolveRequestPolicy(c, { base, defaults, options })
|
|
657
|
+
if (!resolved) return next()
|
|
609
658
|
|
|
610
659
|
c.set('auth', auth)
|
|
611
|
-
|
|
660
|
+
if (!resolved.policy) return next()
|
|
661
|
+
if (resolved.management && (!auth.mpp || !resolved.policy.mpp)) return next()
|
|
662
|
+
|
|
663
|
+
return require<environment>(resolved.policy)(c, next)
|
|
612
664
|
})
|
|
613
665
|
}
|
|
614
666
|
|
|
667
|
+
function resolveRequestPolicy(c: hono_Context, options: resolveRequestPolicy.Options) {
|
|
668
|
+
const route = openApiRoute(c)
|
|
669
|
+
if (!route) return undefined
|
|
670
|
+
|
|
671
|
+
const { key, description, management, scope } = route
|
|
672
|
+
const overrides = options.options.overrides as
|
|
673
|
+
| Record<string, PolicyOverride | false | undefined>
|
|
674
|
+
| undefined
|
|
675
|
+
const routePolicies = policies(c)
|
|
676
|
+
const configuredOverride = (() => {
|
|
677
|
+
const configured = overrides?.[key]
|
|
678
|
+
if (configured !== undefined) return configured
|
|
679
|
+
const inheritedMethod = routePolicies.find(
|
|
680
|
+
(routePolicy): routePolicy is policy.Options =>
|
|
681
|
+
routePolicy !== false && routePolicy.inheritOverridesFrom !== undefined,
|
|
682
|
+
)?.inheritOverridesFrom
|
|
683
|
+
if (inheritedMethod === undefined) return undefined
|
|
684
|
+
const inheritedKey = `${inheritedMethod.toUpperCase()} ${key.slice(key.indexOf(' ') + 1)}`
|
|
685
|
+
return overrides?.[inheritedKey]
|
|
686
|
+
})()
|
|
687
|
+
// Generated management routes already materialize the GET's MPP contract.
|
|
688
|
+
// Reapplying its override would also copy GET-only quota controls.
|
|
689
|
+
const routeOverride = management ? undefined : configuredOverride
|
|
690
|
+
return {
|
|
691
|
+
management,
|
|
692
|
+
policy: bindMppScope(
|
|
693
|
+
resolvePolicy(options.base, options.defaults, [...routePolicies, routeOverride], description),
|
|
694
|
+
scope,
|
|
695
|
+
),
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
declare namespace resolveRequestPolicy {
|
|
700
|
+
/** Inputs used to resolve the current route's authentication policy. */
|
|
701
|
+
type Options = {
|
|
702
|
+
/** Default-closed base policy. */
|
|
703
|
+
base: require.Policy
|
|
704
|
+
/** Configured lane defaults. */
|
|
705
|
+
defaults: LaneDefaults
|
|
706
|
+
/** Authentication middleware options and route overrides. */
|
|
707
|
+
options: middleware.Options
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
type ApiKeyResolverOptions = {
|
|
712
|
+
/** API-key authentication and cache configuration. */
|
|
713
|
+
apiKey: middleware.Options['apiKey']
|
|
714
|
+
/** Authoritative owner store used to reject orphaned API keys. */
|
|
715
|
+
db?: Db.Source | undefined
|
|
716
|
+
/** Scope catalog accepted while resolving records. */
|
|
717
|
+
scopeCatalog: Scope.Catalog | undefined
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
type RequestApiKeyResolution = {
|
|
721
|
+
/** Resolved API key, or null when the token is invalid. */
|
|
722
|
+
apiKey: ApiKey.ApiKey | null
|
|
723
|
+
/** Hash of the presented token associated with the resolution. */
|
|
724
|
+
tokenHash: string
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function createApiKeyResolver(options: ApiKeyResolverOptions) {
|
|
728
|
+
const requests = new WeakMap<hono_Context, RequestApiKeyResolution>()
|
|
729
|
+
const uncached = (c: hono_Context, token: string) => {
|
|
730
|
+
const kv = contextKv(c)
|
|
731
|
+
return kv
|
|
732
|
+
? ApiKeys.resolve(kv.store, token, { scopeCatalog: options.scopeCatalog })
|
|
733
|
+
: Promise.resolve(null)
|
|
734
|
+
}
|
|
735
|
+
const cache =
|
|
736
|
+
options.apiKey === false || options.apiKey?.cache === false
|
|
737
|
+
? { invalidate: () => {}, peek: () => undefined, resolve: uncached }
|
|
738
|
+
: cachedResolve(uncached, options.apiKey?.cache ?? {})
|
|
739
|
+
|
|
740
|
+
return {
|
|
741
|
+
peek: (c: hono_Context, token: string) => {
|
|
742
|
+
const tokenHash = ApiKey.hash(token)
|
|
743
|
+
const existing = requests.get(c)
|
|
744
|
+
if (existing?.tokenHash === tokenHash) return existing.apiKey
|
|
745
|
+
return cache.peek(token)
|
|
746
|
+
},
|
|
747
|
+
resolve: async (c: hono_Context, token: string) => {
|
|
748
|
+
const tokenHash = ApiKey.hash(token)
|
|
749
|
+
const existing = requests.get(c)
|
|
750
|
+
if (existing?.tokenHash === tokenHash) return existing.apiKey
|
|
751
|
+
const cached = await cache.resolve(c, token)
|
|
752
|
+
const kv = contextKv(c)
|
|
753
|
+
const apiKey =
|
|
754
|
+
cached &&
|
|
755
|
+
((kv && (await ApiKeys.isOwnerDeleted(kv.store, cached))) ||
|
|
756
|
+
!(await apiKeyOwnerExists(cached, options.db)))
|
|
757
|
+
? null
|
|
758
|
+
: cached
|
|
759
|
+
if (cached && !apiKey) cache.invalidate(token)
|
|
760
|
+
requests.set(c, { apiKey, tokenHash })
|
|
761
|
+
return apiKey
|
|
762
|
+
},
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/** Rejects attributed keys fenced by a committed owner deletion. */
|
|
767
|
+
async function apiKeyOwnerExists(apiKey: ApiKey.ApiKey, source: Db.Source | undefined) {
|
|
768
|
+
if (!source) return true
|
|
769
|
+
const db = Db.get(source)
|
|
770
|
+
if (!(await ApiKeyAdmissions.matches(db, apiKey))) return false
|
|
771
|
+
if (await ApiKeyOwnerTombstones.isDeleted(db, apiKey)) return false
|
|
772
|
+
return true
|
|
773
|
+
}
|
|
774
|
+
|
|
615
775
|
export declare namespace middleware {
|
|
616
776
|
/** Per-route policy overrides keyed by HTTP endpoint. */
|
|
617
777
|
type Overrides<endpoint extends string = string> = Partial<
|
|
@@ -689,7 +849,7 @@ export declare namespace middleware {
|
|
|
689
849
|
}
|
|
690
850
|
}
|
|
691
851
|
|
|
692
|
-
/** Zod schemas documenting the session sign-in surface
|
|
852
|
+
/** Zod schemas documenting the session sign-in surface. */
|
|
693
853
|
namespace schema {
|
|
694
854
|
const siweMessage =
|
|
695
855
|
'api.tempo.xyz wants you to sign in with your Ethereum account:\n0x0000000000000000000000000000000000000000\n\nURI: https://api.tempo.xyz\nVersion: 1\nChain ID: 0\nNonce: 3D0sZfnHqTBmc9tKR\nIssued At: 2026-01-01T00:00:00.000Z\nExpiration Time: 2026-01-01T00:10:00.000Z'
|
|
@@ -710,64 +870,92 @@ namespace schema {
|
|
|
710
870
|
/** Schemas for `POST /v1/auth/siwe/challenge`. */
|
|
711
871
|
export namespace challenge {
|
|
712
872
|
/** Request body. Accepted fields beyond this document pass through to the SDK handler. */
|
|
713
|
-
export const Body = z.object({})
|
|
873
|
+
export const Body = OpenApi.component(z.object({}), 'SiweChallengeRequest')
|
|
714
874
|
|
|
715
875
|
/** Response body. */
|
|
716
|
-
export const Response =
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
876
|
+
export const Response = OpenApi.component(
|
|
877
|
+
z.object({
|
|
878
|
+
message: z
|
|
879
|
+
.string()
|
|
880
|
+
.check(
|
|
881
|
+
z.describe('Single-use EIP-4361 (SIWE) message to sign and submit for verification.'),
|
|
882
|
+
z.meta({ examples: [siweMessage] }),
|
|
883
|
+
),
|
|
884
|
+
}),
|
|
885
|
+
'SiweChallengeResponse',
|
|
886
|
+
)
|
|
724
887
|
}
|
|
725
888
|
|
|
726
889
|
/** Schemas for `POST /v1/auth/siwe` (verify). */
|
|
727
890
|
export namespace verify {
|
|
728
891
|
/** Request body. */
|
|
729
|
-
export const Body =
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
892
|
+
export const Body = OpenApi.component(
|
|
893
|
+
z.object({
|
|
894
|
+
address: z
|
|
895
|
+
.string()
|
|
896
|
+
.check(
|
|
897
|
+
z.describe('Wallet address that signed the message; becomes the session subject.'),
|
|
898
|
+
z.meta({ examples: ['0x0000000000000000000000000000000000000001'] }),
|
|
899
|
+
),
|
|
900
|
+
idToken: z.optional(z.string()).check(
|
|
901
|
+
z.describe('Wallet-minted OIDC identity token (JWT) asserting a verified email, folded onto the session.'), // prettier-ignore
|
|
902
|
+
z.meta({ examples: ['eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIweDAwMDAifQ.c2lnbmF0dXJl'] }),
|
|
735
903
|
),
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
),
|
|
740
|
-
keyAuthorization: z.optional(z.string()).check(
|
|
741
|
-
z.describe('RLP-serialized signed key authorization (TIP-1053) whose witness binds this message; verification recovers over its digest.'), // prettier-ignore
|
|
742
|
-
z.meta({ examples: [`0x${'aa'.repeat(60)}`] }),
|
|
743
|
-
),
|
|
744
|
-
message: z
|
|
745
|
-
.string()
|
|
746
|
-
.check(
|
|
747
|
-
z.describe('The exact challenge message issued by `POST /v1/auth/siwe/challenge`.'),
|
|
748
|
-
z.meta({ examples: [siweMessage] }),
|
|
904
|
+
keyAuthorization: z.optional(z.string()).check(
|
|
905
|
+
z.describe('RLP-serialized signed key authorization (TIP-1053) whose witness binds this message; verification recovers over its digest.'), // prettier-ignore
|
|
906
|
+
z.meta({ examples: [`0x${'aa'.repeat(60)}`] }),
|
|
749
907
|
),
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
.check(
|
|
757
|
-
z.describe('
|
|
758
|
-
z.meta({ examples: [
|
|
908
|
+
message: z
|
|
909
|
+
.string()
|
|
910
|
+
.check(
|
|
911
|
+
z.describe('The exact challenge message issued by `POST /v1/auth/siwe/challenge`.'),
|
|
912
|
+
z.meta({ examples: [siweMessage] }),
|
|
913
|
+
),
|
|
914
|
+
returnToken: z.optional(z.boolean()).check(
|
|
915
|
+
z.describe('Return the session token in the body instead of setting the session cookie.'), // prettier-ignore
|
|
916
|
+
z.meta({ examples: [true] }),
|
|
759
917
|
),
|
|
760
|
-
|
|
918
|
+
signature: z
|
|
919
|
+
.string()
|
|
920
|
+
.check(
|
|
921
|
+
z.describe('Signature over the challenge message (or the key-authorization digest).'),
|
|
922
|
+
z.meta({ examples: [`0x${'aa'.repeat(65)}`] }),
|
|
923
|
+
),
|
|
924
|
+
}),
|
|
925
|
+
'SiweVerifyRequest',
|
|
926
|
+
)
|
|
761
927
|
|
|
762
928
|
/** Response body. */
|
|
763
|
-
export const Response =
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
929
|
+
export const Response = OpenApi.component(
|
|
930
|
+
z.object({
|
|
931
|
+
token: z
|
|
932
|
+
.optional(z.string())
|
|
933
|
+
.check(
|
|
934
|
+
z.describe('Bearer session token; present only when `returnToken` is true.'),
|
|
935
|
+
z.meta({ examples: ['aa'.repeat(32)] }),
|
|
936
|
+
),
|
|
937
|
+
}),
|
|
938
|
+
'SiweVerifyResponse',
|
|
939
|
+
)
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/** Schemas for `POST /v1/auth/identity`. */
|
|
943
|
+
export namespace identity {
|
|
944
|
+
/** Request body. */
|
|
945
|
+
export const Body = OpenApi.component(
|
|
946
|
+
z.object({
|
|
947
|
+
idToken: z
|
|
948
|
+
.string()
|
|
949
|
+
.check(
|
|
950
|
+
z.describe('Wallet-issued OpenID Connect identity token.'),
|
|
951
|
+
z.meta({ examples: ['eyJhbGciOiJFZERTQSJ9.eyJzdWIiOiIweDAwMDAifQ.c2lnbmF0dXJl'] }),
|
|
952
|
+
),
|
|
953
|
+
}),
|
|
954
|
+
'IdentitySignInRequest',
|
|
955
|
+
)
|
|
956
|
+
|
|
957
|
+
/** Response body. */
|
|
958
|
+
export const Response = OpenApi.component(z.object({}), 'IdentitySignInResponse')
|
|
771
959
|
}
|
|
772
960
|
}
|
|
773
961
|
|
|
@@ -787,19 +975,39 @@ function handlerError(description: string) {
|
|
|
787
975
|
*/
|
|
788
976
|
export function install(options: install.Options) {
|
|
789
977
|
const { db, kv, scopeCatalog } = options
|
|
790
|
-
const {
|
|
791
|
-
|
|
978
|
+
const {
|
|
979
|
+
edgeRateLimit: options_edgeRateLimit,
|
|
980
|
+
session: options_session,
|
|
981
|
+
...options_middleware
|
|
982
|
+
} = options.auth === false ? {} : (options.auth ?? {})
|
|
983
|
+
const publicClientIp =
|
|
984
|
+
typeof options_middleware.public === 'object' ? options_middleware.public.clientIp : undefined
|
|
792
985
|
if (options_session && !kv)
|
|
793
986
|
throw new Error('`auth.session` requires the `kv` state store: sessions and sign-in challenges persist there.') // prettier-ignore
|
|
987
|
+
const options_betterAuth = options_session
|
|
988
|
+
? {
|
|
989
|
+
basePath: Path.join(options.basePath, 'v1/auth'),
|
|
990
|
+
clientIp: (request: Request) => resolveTrustedClientIp(request, publicClientIp),
|
|
991
|
+
db,
|
|
992
|
+
get email() {
|
|
993
|
+
return options.email()
|
|
994
|
+
},
|
|
995
|
+
rateLimit: RateLimit.memory(options_middleware.rateLimit),
|
|
996
|
+
secret: options_session.secret,
|
|
997
|
+
...(options_session.google ? { google: options_session.google } : {}),
|
|
998
|
+
...(options_session.trustedOrigins
|
|
999
|
+
? { trustedOrigins: options_session.trustedOrigins }
|
|
1000
|
+
: {}),
|
|
1001
|
+
}
|
|
1002
|
+
: undefined
|
|
794
1003
|
|
|
795
1004
|
// Session sign-in surface (challenge, verify, logout — SIWE wallet sign-in
|
|
796
1005
|
// today) plus the capability the session lane resolves through. Public but
|
|
797
1006
|
// policy-gated: the hidden describeRoute engages the middleware for the
|
|
798
1007
|
// mounted sub-app, and the public lane rate-limits challenge-store writes.
|
|
799
1008
|
const app = (() => {
|
|
800
|
-
if (!options_session || !kv) return undefined
|
|
801
|
-
const { issuer, origin, requireEmail, ttl } =
|
|
802
|
-
(typeof options_session === 'object' ? options_session.wallet : undefined) ?? {}
|
|
1009
|
+
if (!options_betterAuth || !options_session || !kv) return undefined
|
|
1010
|
+
const { issuer, origin, requireEmail, ttl } = options_session.wallet ?? {}
|
|
803
1011
|
|
|
804
1012
|
const handler = Accounts.Handler.auth({
|
|
805
1013
|
getClient: options.getClient,
|
|
@@ -839,30 +1047,105 @@ export function install(options: install.Options) {
|
|
|
839
1047
|
},
|
|
840
1048
|
...(ttl ? { ttl } : {}),
|
|
841
1049
|
})
|
|
1050
|
+
const identity = options_session.identity
|
|
1051
|
+
const identitySessionTtl = identity?.ttl ?? defaultIdentitySessionTtl
|
|
1052
|
+
const identitySessionKey = (token: string) => `identity:session:${token}`
|
|
1053
|
+
|
|
1054
|
+
async function resolveWallet(payload: WalletSession) {
|
|
1055
|
+
const database = Db.get(db)
|
|
1056
|
+
const verifiedEmail = payload.email?.trim().toLowerCase()
|
|
1057
|
+
return database.kysely.transaction().execute(async (kysely) => {
|
|
1058
|
+
const tx = { ...database, kysely }
|
|
1059
|
+
// Organization creation locks the same address row before resolving
|
|
1060
|
+
// the wallet owner, serializing resource writes with reconciliation.
|
|
1061
|
+
const addressUser = await Users.getByAddressForUpdate(tx, payload.address)
|
|
1062
|
+
if (!addressUser) return null
|
|
1063
|
+
if (verifiedEmail)
|
|
1064
|
+
await sql`SELECT pg_advisory_xact_lock(hashtextextended(${verifiedEmail}, 0))`.execute(
|
|
1065
|
+
kysely,
|
|
1066
|
+
)
|
|
1067
|
+
const linkedUserId = await AuthAccounts.getWalletUserId(tx, payload.address)
|
|
1068
|
+
const linkedUser = linkedUserId ? await Users.get(tx, linkedUserId) : undefined
|
|
1069
|
+
const emailUser = verifiedEmail ? await Users.getByEmail(tx, verifiedEmail) : undefined
|
|
1070
|
+
const walletUser = linkedUser ?? addressUser
|
|
1071
|
+
const walletHasResources =
|
|
1072
|
+
emailUser && walletUser.id !== emailUser.id
|
|
1073
|
+
? await Memberships.existsForUser(tx, walletUser.id)
|
|
1074
|
+
: false
|
|
1075
|
+
// A verified email reconciles a provisional email-less wallet link.
|
|
1076
|
+
// Keep a provisional owner when changing it would orphan its access.
|
|
1077
|
+
const user = walletHasResources ? walletUser : (emailUser ?? walletUser)
|
|
1078
|
+
if (linkedUser?.id !== user.id)
|
|
1079
|
+
await AuthAccounts.setWalletUser(tx, { address: payload.address, userId: user.id })
|
|
1080
|
+
if (verifiedEmail && (user.email !== verifiedEmail || !user.emailVerified))
|
|
1081
|
+
await Users.setEmail(tx, user.id, verifiedEmail)
|
|
1082
|
+
return { email: verifiedEmail ?? user.email ?? undefined, user }
|
|
1083
|
+
})
|
|
1084
|
+
}
|
|
842
1085
|
|
|
843
1086
|
const session: Session = {
|
|
844
1087
|
resolve: async (c) => {
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1088
|
+
const [betterAuth, identitySession, wallet] = await Promise.all([
|
|
1089
|
+
(async () => {
|
|
1090
|
+
const auth = BetterAuth.fromContext(c, options_betterAuth)
|
|
1091
|
+
const request = BetterAuth.request(c, options_betterAuth)
|
|
1092
|
+
const result = await auth.api.getSession({ headers: request.headers })
|
|
1093
|
+
if (!result) return null
|
|
1094
|
+
const provider =
|
|
1095
|
+
'provider' in result.session && typeof result.session.provider === 'string'
|
|
1096
|
+
? result.session.provider
|
|
1097
|
+
: undefined
|
|
1098
|
+
if (
|
|
1099
|
+
!provider ||
|
|
1100
|
+
!result.user.email ||
|
|
1101
|
+
(provider === 'email' && !options_betterAuth.email)
|
|
1102
|
+
)
|
|
1103
|
+
return null
|
|
1104
|
+
return {
|
|
1105
|
+
email: result.user.email,
|
|
1106
|
+
id: result.user.id,
|
|
1107
|
+
identity: { provider, subject: result.user.email },
|
|
1108
|
+
type: 'session',
|
|
1109
|
+
} satisfies SessionPrincipal
|
|
1110
|
+
})(),
|
|
1111
|
+
(async () => {
|
|
1112
|
+
if (!identity) return null
|
|
1113
|
+
const token = getCookie(c, identityCookieName)
|
|
1114
|
+
if (!token) return null
|
|
1115
|
+
const value = await kv.store.get(identitySessionKey(token))
|
|
1116
|
+
if (value === null) return null
|
|
1117
|
+
const payload = JSON.parse(value) as IdentitySession
|
|
1118
|
+
if (payload.expiresAt <= Math.floor(Date.now() / 1_000)) return null
|
|
1119
|
+
const user = await resolveWallet(payload)
|
|
1120
|
+
if (!user) return null
|
|
1121
|
+
return {
|
|
1122
|
+
...(user.email ? { email: user.email } : {}),
|
|
1123
|
+
id: user.user.id,
|
|
1124
|
+
identity: { provider: 'wallet', subject: payload.address },
|
|
1125
|
+
type: 'session',
|
|
1126
|
+
} satisfies SessionPrincipal
|
|
1127
|
+
})(),
|
|
1128
|
+
(async () => {
|
|
1129
|
+
const payload = await handler.getSession(c.req.raw)
|
|
1130
|
+
if (!payload) return null
|
|
1131
|
+
const user = await resolveWallet(payload)
|
|
1132
|
+
if (!user) return null
|
|
1133
|
+
return {
|
|
1134
|
+
...(user.email ? { email: user.email } : {}),
|
|
1135
|
+
id: user.user.id,
|
|
1136
|
+
identity: { provider: 'wallet', subject: payload.address },
|
|
1137
|
+
type: 'session',
|
|
1138
|
+
} satisfies SessionPrincipal
|
|
1139
|
+
})(),
|
|
1140
|
+
])
|
|
1141
|
+
if (betterAuth && identitySession && betterAuth.id !== identitySession.id) return null
|
|
1142
|
+
if (betterAuth && wallet && betterAuth.id !== wallet.id) return null
|
|
1143
|
+
if (identitySession && wallet && identitySession.id !== wallet.id) return null
|
|
1144
|
+
return betterAuth ?? identitySession ?? wallet
|
|
861
1145
|
},
|
|
862
1146
|
}
|
|
863
1147
|
|
|
864
1148
|
const policy_public = policy({ public: true })
|
|
865
|
-
const policy_session = policy({ public: true, session: true })
|
|
866
1149
|
const describe = OpenApi.describeRoute({ hide: true })
|
|
867
1150
|
|
|
868
1151
|
const app = new Hono<App.Environment>()
|
|
@@ -874,10 +1157,8 @@ export function install(options: install.Options) {
|
|
|
874
1157
|
app.post(
|
|
875
1158
|
'/v1/auth/siwe/challenge',
|
|
876
1159
|
policy_public,
|
|
877
|
-
OpenApi.
|
|
878
|
-
|
|
879
|
-
message: 'Invalid request body',
|
|
880
|
-
}),
|
|
1160
|
+
OpenApi.documentJsonRequest(schema.challenge.Body),
|
|
1161
|
+
validateJsonRequest(schema.challenge.Body),
|
|
881
1162
|
OpenApi.describeRoute({
|
|
882
1163
|
description:
|
|
883
1164
|
'Issues a single-use SIWE challenge message to sign. The challenge expires after a short TTL.',
|
|
@@ -901,10 +1182,8 @@ export function install(options: install.Options) {
|
|
|
901
1182
|
app.post(
|
|
902
1183
|
'/v1/auth/siwe',
|
|
903
1184
|
policy_public,
|
|
904
|
-
OpenApi.
|
|
905
|
-
|
|
906
|
-
message: 'Invalid request body',
|
|
907
|
-
}),
|
|
1185
|
+
OpenApi.documentJsonRequest(schema.verify.Body),
|
|
1186
|
+
validateJsonRequest(schema.verify.Body),
|
|
908
1187
|
OpenApi.describeRoute({
|
|
909
1188
|
description:
|
|
910
1189
|
'Verifies the signed challenge and establishes a session. Sets a session cookie by default; pass `returnToken` to receive a bearer token instead.',
|
|
@@ -933,42 +1212,270 @@ export function install(options: install.Options) {
|
|
|
933
1212
|
tags: ['Authentication'],
|
|
934
1213
|
}),
|
|
935
1214
|
)
|
|
1215
|
+
if (identity)
|
|
1216
|
+
app.post(
|
|
1217
|
+
'/v1/auth/identity',
|
|
1218
|
+
policy_public,
|
|
1219
|
+
OpenApi.documentJsonRequest(schema.identity.Body),
|
|
1220
|
+
validateJsonRequest(schema.identity.Body),
|
|
1221
|
+
OpenApi.describeRoute({
|
|
1222
|
+
description:
|
|
1223
|
+
'Verifies a Wallet-issued OpenID Connect identity token and establishes a session.',
|
|
1224
|
+
hide: false,
|
|
1225
|
+
operationId: 'verifyIdentity',
|
|
1226
|
+
responses: {
|
|
1227
|
+
200: {
|
|
1228
|
+
content: {
|
|
1229
|
+
'application/json': { schema: OpenApi.resolver(schema.identity.Response) },
|
|
1230
|
+
},
|
|
1231
|
+
description: 'Session established.',
|
|
1232
|
+
headers: {
|
|
1233
|
+
...OpenApi.successHeaders,
|
|
1234
|
+
'Set-Cookie': {
|
|
1235
|
+
description: `Session cookie (${identityCookieName}).`,
|
|
1236
|
+
schema: { type: 'string' },
|
|
1237
|
+
},
|
|
1238
|
+
},
|
|
1239
|
+
},
|
|
1240
|
+
400: OpenApi.standardError(400, 'Malformed request body.', ['body_invalid']),
|
|
1241
|
+
401: OpenApi.standardError(401, 'Identity verification failed.', ['identity_invalid']),
|
|
1242
|
+
429: OpenApi.standardError(429, 'Rate limited.'),
|
|
1243
|
+
500: OpenApi.standardError(500, 'Internal server error.'),
|
|
1244
|
+
},
|
|
1245
|
+
summary: 'Authenticate identity',
|
|
1246
|
+
tags: ['Authentication'],
|
|
1247
|
+
}),
|
|
1248
|
+
async (c) => {
|
|
1249
|
+
const { idToken } = schema.identity.Body.parse(await c.req.json())
|
|
1250
|
+
const claims = await Accounts.Identity.verify(idToken, {
|
|
1251
|
+
audience: identity.audience,
|
|
1252
|
+
issuer: identity.issuer ?? walletIdentityIssuer,
|
|
1253
|
+
}).catch((error) => {
|
|
1254
|
+
// Issuer and network failures must reach the request error signal.
|
|
1255
|
+
if (isIdentityTokenError(error)) return undefined
|
|
1256
|
+
throw error
|
|
1257
|
+
})
|
|
1258
|
+
if (!claims || !Address.validate(claims.subject, { strict: false }))
|
|
1259
|
+
return Response.error(c, {
|
|
1260
|
+
code: 'identity_invalid',
|
|
1261
|
+
message: 'Invalid identity token',
|
|
1262
|
+
status: 401,
|
|
1263
|
+
})
|
|
1264
|
+
|
|
1265
|
+
const address = Address.checksum(claims.subject)
|
|
1266
|
+
await Users.upsertByAddress(Db.get(db), { address })
|
|
1267
|
+
const issuedAt = Math.floor(Date.now() / 1_000)
|
|
1268
|
+
const token = Hex.fromBytes(crypto.getRandomValues(new Uint8Array(32))).slice(2)
|
|
1269
|
+
await kv.store.put(
|
|
1270
|
+
identitySessionKey(token),
|
|
1271
|
+
JSON.stringify({
|
|
1272
|
+
address,
|
|
1273
|
+
...(claims.email ? { email: claims.email } : {}),
|
|
1274
|
+
expiresAt: issuedAt + identitySessionTtl,
|
|
1275
|
+
issuedAt,
|
|
1276
|
+
} satisfies IdentitySession),
|
|
1277
|
+
{ ttl: identitySessionTtl * 1_000 },
|
|
1278
|
+
)
|
|
1279
|
+
setCookie(c, identityCookieName, token, {
|
|
1280
|
+
httpOnly: true,
|
|
1281
|
+
maxAge: identitySessionTtl,
|
|
1282
|
+
path: '/',
|
|
1283
|
+
sameSite: 'Lax',
|
|
1284
|
+
secure: new URL(c.req.url).protocol === 'https:',
|
|
1285
|
+
})
|
|
1286
|
+
return c.json({}, 200)
|
|
1287
|
+
},
|
|
1288
|
+
)
|
|
936
1289
|
app.post(
|
|
937
|
-
'/v1/auth/
|
|
938
|
-
|
|
1290
|
+
'/v1/auth/logout',
|
|
1291
|
+
policy(false),
|
|
1292
|
+
createMiddleware<App.Environment>(async (c, next) => {
|
|
1293
|
+
const auth = c.get('auth')
|
|
1294
|
+
const principal = principalFromPublic(c, auth)
|
|
1295
|
+
const result = await consumeRateLimit(auth, {
|
|
1296
|
+
key: `public:${principal.id}`,
|
|
1297
|
+
limit: auth.publicRateLimit ?? defaultPublicRateLimit,
|
|
1298
|
+
})
|
|
1299
|
+
if (result) {
|
|
1300
|
+
setRateLimitHeaders(c, result)
|
|
1301
|
+
if (!result.allowed) return rateLimitExceeded(c, result)
|
|
1302
|
+
}
|
|
1303
|
+
c.set('principal', principal)
|
|
1304
|
+
await next()
|
|
1305
|
+
return undefined
|
|
1306
|
+
}),
|
|
939
1307
|
OpenApi.describeRoute({
|
|
940
|
-
description: 'Revokes
|
|
1308
|
+
description: 'Revokes auth sessions and clears their cookies.',
|
|
941
1309
|
hide: false,
|
|
942
|
-
operationId: '
|
|
1310
|
+
operationId: 'logout',
|
|
943
1311
|
responses: {
|
|
944
|
-
204: { description: '
|
|
1312
|
+
204: { description: 'Sessions revoked and cookies cleared.' },
|
|
945
1313
|
429: OpenApi.standardError(429, 'Rate limited.'),
|
|
946
|
-
500: OpenApi.standardError(500, '
|
|
1314
|
+
500: OpenApi.standardError(500, 'Session logout failed.', ['session_logout_failed']),
|
|
947
1315
|
},
|
|
948
1316
|
summary: 'Sign out',
|
|
949
1317
|
tags: ['Authentication'],
|
|
950
1318
|
}),
|
|
1319
|
+
async (c) => {
|
|
1320
|
+
const walletHeaders = (() => {
|
|
1321
|
+
const authorization = c.req.header('authorization')
|
|
1322
|
+
const cookie = c.req.header('cookie')
|
|
1323
|
+
if (!authorization?.match(/^Bearer\s+.+$/i) || !cookie?.match(/(?:^|;\s*)accounts_auth=/))
|
|
1324
|
+
return [c.req.raw.headers]
|
|
1325
|
+
const bearer = new Headers(c.req.raw.headers)
|
|
1326
|
+
bearer.delete('cookie')
|
|
1327
|
+
const cookie_ = new Headers(c.req.raw.headers)
|
|
1328
|
+
cookie_.delete('authorization')
|
|
1329
|
+
return [bearer, cookie_]
|
|
1330
|
+
})()
|
|
1331
|
+
const [betterAuth, identityLogout, ...accounts] = await Promise.allSettled([
|
|
1332
|
+
BetterAuth.fromContext(c, options_betterAuth).api.signOut({
|
|
1333
|
+
headers: c.req.raw.headers,
|
|
1334
|
+
returnHeaders: true,
|
|
1335
|
+
}),
|
|
1336
|
+
(async () => {
|
|
1337
|
+
const token = getCookie(c, identityCookieName)
|
|
1338
|
+
deleteCookie(c, identityCookieName, { path: '/' })
|
|
1339
|
+
if (token) await kv.store.delete(identitySessionKey(token))
|
|
1340
|
+
})(),
|
|
1341
|
+
...walletHeaders.map((headers) =>
|
|
1342
|
+
handler.request(
|
|
1343
|
+
new Request(new URL('/logout', c.req.url), {
|
|
1344
|
+
headers,
|
|
1345
|
+
method: 'POST',
|
|
1346
|
+
}),
|
|
1347
|
+
),
|
|
1348
|
+
),
|
|
1349
|
+
])
|
|
1350
|
+
|
|
1351
|
+
if (betterAuth.status === 'fulfilled')
|
|
1352
|
+
for (const cookie of splitSetCookieHeader(
|
|
1353
|
+
betterAuth.value.headers.get('Set-Cookie') ?? '',
|
|
1354
|
+
))
|
|
1355
|
+
c.header('Set-Cookie', cookie, { append: true })
|
|
1356
|
+
for (const result of accounts)
|
|
1357
|
+
if (result.status === 'fulfilled')
|
|
1358
|
+
for (const cookie of splitSetCookieHeader(result.value.headers.get('Set-Cookie') ?? ''))
|
|
1359
|
+
c.header('Set-Cookie', cookie, { append: true })
|
|
1360
|
+
|
|
1361
|
+
const error = (() => {
|
|
1362
|
+
const rejected = [betterAuth, identityLogout, ...accounts].find(
|
|
1363
|
+
(result) => result.status === 'rejected',
|
|
1364
|
+
)
|
|
1365
|
+
if (rejected?.status === 'rejected')
|
|
1366
|
+
return rejected.reason instanceof Error
|
|
1367
|
+
? rejected.reason
|
|
1368
|
+
: new Error('Session logout failed', { cause: rejected.reason })
|
|
1369
|
+
const failed = accounts.find(
|
|
1370
|
+
(result) => result.status === 'fulfilled' && !result.value.ok,
|
|
1371
|
+
)
|
|
1372
|
+
if (failed?.status === 'fulfilled')
|
|
1373
|
+
return new Error(`Accounts session logout failed with status ${failed.value.status}`)
|
|
1374
|
+
return undefined
|
|
1375
|
+
})()
|
|
1376
|
+
if (error) {
|
|
1377
|
+
c.error = error
|
|
1378
|
+
return Response.error(c, {
|
|
1379
|
+
code: 'session_logout_failed',
|
|
1380
|
+
message: 'Session logout failed',
|
|
1381
|
+
status: 500,
|
|
1382
|
+
})
|
|
1383
|
+
}
|
|
1384
|
+
return c.body(null, 204)
|
|
1385
|
+
},
|
|
951
1386
|
)
|
|
1387
|
+
app.route('/v1/auth/siwe', handler)
|
|
1388
|
+
app.on(['GET', 'POST'], '/v1/auth/*', policy_public, describe, async (c, next) => {
|
|
1389
|
+
if (
|
|
1390
|
+
c.req.method === 'POST' &&
|
|
1391
|
+
stripBasePath(c.req.path, basePath(c)) === '/v1/auth/email-otp/send-verification-otp'
|
|
1392
|
+
) {
|
|
1393
|
+
const body: unknown = await c.req.raw
|
|
1394
|
+
.clone()
|
|
1395
|
+
.json()
|
|
1396
|
+
.catch(() => undefined)
|
|
1397
|
+
if (body && typeof body === 'object' && 'type' in body && body.type !== 'sign-in')
|
|
1398
|
+
return Response.error(c, {
|
|
1399
|
+
code: 'body_invalid',
|
|
1400
|
+
message: 'Only sign-in OTPs are supported',
|
|
1401
|
+
status: 400,
|
|
1402
|
+
})
|
|
1403
|
+
}
|
|
1404
|
+
const response = await BetterAuth.fromContext(c, options_betterAuth).handler(
|
|
1405
|
+
BetterAuth.request(c, options_betterAuth),
|
|
1406
|
+
)
|
|
1407
|
+
// Leave unmatched paths available to auth providers mounted by the host app.
|
|
1408
|
+
return response.status === 404 ? next() : response
|
|
1409
|
+
})
|
|
952
1410
|
return Object.assign(
|
|
953
1411
|
// The tag joins the `Management API` group at `management()`'s chosen slot;
|
|
954
1412
|
// group listings filter to defined tags, so it drops out when unmounted.
|
|
955
|
-
Metadata.attach(app
|
|
1413
|
+
Metadata.attach(app, {
|
|
1414
|
+
securitySchemes: {
|
|
1415
|
+
session: {
|
|
1416
|
+
description: 'Session cookie established by email OTP, Wallet identity, or SIWE sign-in. Browsers send `tempo_auth.session_token`, `tempo_identity`, or `accounts_auth`; Accounts sessions may also use `Authorization: Bearer <token>`.', // prettier-ignore
|
|
1417
|
+
in: 'header',
|
|
1418
|
+
name: 'Cookie',
|
|
1419
|
+
type: 'apiKey',
|
|
1420
|
+
},
|
|
1421
|
+
},
|
|
956
1422
|
tags: [{ name: 'Authentication', description: 'Authenticate into the Tempo Platform.' }],
|
|
957
1423
|
}),
|
|
958
1424
|
{ session },
|
|
959
1425
|
)
|
|
960
1426
|
})()
|
|
961
1427
|
|
|
1428
|
+
const resolve = createApiKeyResolver({
|
|
1429
|
+
apiKey: options_middleware.apiKey,
|
|
1430
|
+
db: options.db,
|
|
1431
|
+
scopeCatalog,
|
|
1432
|
+
})
|
|
1433
|
+
const defaults = laneDefaults(options_middleware)
|
|
1434
|
+
const base: require.Policy = {}
|
|
1435
|
+
const edgeRateLimit = (() => {
|
|
1436
|
+
if (options.auth === false || !options_edgeRateLimit) return undefined
|
|
1437
|
+
const superAdminTokenHash = options_middleware.superAdmin?.secret
|
|
1438
|
+
? ApiKey.hash(options_middleware.superAdmin.secret)
|
|
1439
|
+
: undefined
|
|
1440
|
+
|
|
1441
|
+
return createMiddleware(async (c, next) => {
|
|
1442
|
+
const credential = getApiKeyCredential(c)
|
|
1443
|
+
const resolved = resolveRequestPolicy(c, { base, defaults, options: options_middleware })
|
|
1444
|
+
const isSuperAdmin =
|
|
1445
|
+
credential &&
|
|
1446
|
+
superAdminTokenHash !== undefined &&
|
|
1447
|
+
ApiKey.hash(credential.token) === superAdminTokenHash
|
|
1448
|
+
const canUseApiKeyQuota =
|
|
1449
|
+
credential &&
|
|
1450
|
+
!isSuperAdmin &&
|
|
1451
|
+
!hasPaymentCredential(c) &&
|
|
1452
|
+
options_middleware.apiKey !== false &&
|
|
1453
|
+
resolved?.policy?.apiKey &&
|
|
1454
|
+
(!resolved.management || (options_middleware.mpp !== false && resolved.policy.mpp))
|
|
1455
|
+
const cached = canUseApiKeyQuota ? resolve.peek(c, credential.token) : undefined
|
|
1456
|
+
if (cached) return next()
|
|
1457
|
+
|
|
1458
|
+
const response = await Timing.time(c, 'edge_rate_limit', () =>
|
|
1459
|
+
options_edgeRateLimit(c.req.raw),
|
|
1460
|
+
)
|
|
1461
|
+
if (response) return response
|
|
1462
|
+
if (canUseApiKeyQuota && cached === undefined) await resolve.resolve(c, credential.token)
|
|
1463
|
+
return next()
|
|
1464
|
+
})
|
|
1465
|
+
})()
|
|
962
1466
|
const middleware_ =
|
|
963
1467
|
options.auth === false
|
|
964
1468
|
? undefined
|
|
965
|
-
:
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1469
|
+
: createAuthMiddleware(
|
|
1470
|
+
{
|
|
1471
|
+
...options_middleware,
|
|
1472
|
+
...(app ? { session: app.session } : {}),
|
|
1473
|
+
scopeCatalog,
|
|
1474
|
+
},
|
|
1475
|
+
resolve,
|
|
1476
|
+
)
|
|
970
1477
|
|
|
971
|
-
return { app, middleware: middleware_ }
|
|
1478
|
+
return { app, edgeRateLimit, middleware: middleware_ }
|
|
972
1479
|
}
|
|
973
1480
|
|
|
974
1481
|
export declare namespace install {
|
|
@@ -976,13 +1483,19 @@ export declare namespace install {
|
|
|
976
1483
|
type Options = {
|
|
977
1484
|
auth:
|
|
978
1485
|
| (Omit<middleware.Options, 'scopeCatalog' | 'session'> & {
|
|
979
|
-
/**
|
|
1486
|
+
/** Request backstop skipped for cached API keys on routes with per-key quotas. */
|
|
1487
|
+
edgeRateLimit?: EdgeRateLimit | undefined
|
|
1488
|
+
/** Session sign-in surface: mounts Better Auth, Wallet identity, and SIWE routes and enables the session lane. Requires `kv`. */
|
|
980
1489
|
session?: Session | undefined
|
|
981
1490
|
})
|
|
982
1491
|
| false
|
|
983
1492
|
| undefined
|
|
1493
|
+
/** Normalized path prefix that contains the auth surface. */
|
|
1494
|
+
basePath: string
|
|
984
1495
|
/** Authoritative database holding user rows. */
|
|
985
1496
|
db: Db.Source
|
|
1497
|
+
/** Resolves the transactional email sender shared by authentication and route groups. */
|
|
1498
|
+
email: () => Email.Sender | undefined
|
|
986
1499
|
/** Resolves the configured Tempo RPC client used for SIWE signature verification. */
|
|
987
1500
|
getClient: (chainId: number) => Viem.getClient.ReturnType
|
|
988
1501
|
/** KV state store, or undefined when key auth is closed. */
|
|
@@ -991,13 +1504,36 @@ export declare namespace install {
|
|
|
991
1504
|
scopeCatalog: Scope.Catalog
|
|
992
1505
|
}
|
|
993
1506
|
|
|
994
|
-
/** Session sign-in surface configuration
|
|
995
|
-
type Session =
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1507
|
+
/** Session sign-in surface configuration. */
|
|
1508
|
+
type Session = {
|
|
1509
|
+
/** Google OpenID Connect configuration. */
|
|
1510
|
+
google?:
|
|
1511
|
+
| {
|
|
1512
|
+
/** OAuth client identifier. */
|
|
1513
|
+
clientId: string
|
|
1514
|
+
/** OAuth client secret. */
|
|
1515
|
+
clientSecret: string
|
|
1516
|
+
}
|
|
1517
|
+
| undefined
|
|
1518
|
+
/** Wallet-issued OpenID Connect identity sign-in configuration. */
|
|
1519
|
+
identity?: Identity | undefined
|
|
1520
|
+
/** High-entropy secret used to protect Better Auth credentials. */
|
|
1521
|
+
secret: string
|
|
1522
|
+
/** Additional browser origins accepted by Better Auth. */
|
|
1523
|
+
trustedOrigins?: readonly string[] | undefined
|
|
1524
|
+
/** SIWE wallet sign-in configuration. */
|
|
1525
|
+
wallet?: Wallet | undefined
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
/** Wallet-issued OpenID Connect identity sign-in configuration. */
|
|
1529
|
+
type Identity = {
|
|
1530
|
+
/** Expected token audience, usually the Console origin. */
|
|
1531
|
+
audience: string
|
|
1532
|
+
/** Identity issuer override; defaults to Tempo Wallet. */
|
|
1533
|
+
issuer?: string | undefined
|
|
1534
|
+
/** Session lifetime in seconds. Defaults to 24 hours. */
|
|
1535
|
+
ttl?: number | undefined
|
|
1536
|
+
}
|
|
1001
1537
|
|
|
1002
1538
|
/** SIWE wallet sign-in configuration. */
|
|
1003
1539
|
type Wallet = {
|
|
@@ -1005,15 +1541,44 @@ export declare namespace install {
|
|
|
1005
1541
|
issuer?: string | undefined
|
|
1006
1542
|
/** Pinned absolute origin for SIWE domain binding. Required off-Workers; on Workers the edge proxy headers are trusted by default. */
|
|
1007
1543
|
origin?: string | undefined
|
|
1008
|
-
/** Reject sign-ins
|
|
1544
|
+
/** Reject sign-ins without a valid identity token. Defaults to false. */
|
|
1009
1545
|
requireEmail?: boolean | undefined
|
|
1010
1546
|
/** Session and challenge TTL overrides, in seconds. */
|
|
1011
1547
|
ttl?: { challenge?: number | undefined; session?: number | undefined } | undefined
|
|
1012
1548
|
}
|
|
1013
1549
|
}
|
|
1014
1550
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1551
|
+
function validateJsonRequest<const schema extends z.ZodMiniType>(
|
|
1552
|
+
schema: schema,
|
|
1553
|
+
): MiddlewareHandler {
|
|
1554
|
+
return async (c, next) => {
|
|
1555
|
+
if (!c.req.header('content-type')?.toLowerCase().startsWith('application/json'))
|
|
1556
|
+
return Response.error(c, {
|
|
1557
|
+
code: 'body_invalid',
|
|
1558
|
+
message: 'Invalid request body',
|
|
1559
|
+
status: 400,
|
|
1560
|
+
})
|
|
1561
|
+
const value = await (async () => {
|
|
1562
|
+
try {
|
|
1563
|
+
return await c.req.raw.clone().json()
|
|
1564
|
+
} catch {
|
|
1565
|
+
return undefined
|
|
1566
|
+
}
|
|
1567
|
+
})()
|
|
1568
|
+
const result = schema.safeParse(value)
|
|
1569
|
+
if (!result.success)
|
|
1570
|
+
return Response.error(c, {
|
|
1571
|
+
code: 'body_invalid',
|
|
1572
|
+
details: Response.validationDetails(result.error.issues),
|
|
1573
|
+
message: 'Invalid request body',
|
|
1574
|
+
status: 400,
|
|
1575
|
+
})
|
|
1576
|
+
return next()
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/** Creates route middleware that contributes an auth policy override, or bypasses auth when passed `false`. */
|
|
1581
|
+
export function policy(options: policy.Options | false): MiddlewareHandler {
|
|
1017
1582
|
const middleware = createMiddleware((_, next) => next()) as MiddlewareHandler & PolicyHandler
|
|
1018
1583
|
middleware[policySymbol] = options
|
|
1019
1584
|
return middleware
|
|
@@ -1042,7 +1607,7 @@ export function installMppManagementRoutes(
|
|
|
1042
1607
|
if (route.method !== 'GET') continue
|
|
1043
1608
|
const target = targets.get(route.path) ?? { path: route.path }
|
|
1044
1609
|
const override = policyFromRoute(route)
|
|
1045
|
-
if (override
|
|
1610
|
+
if (override && override.mpp !== undefined)
|
|
1046
1611
|
target.mpp = resolveMppLane(target.mpp, override.mpp, { session: {} })
|
|
1047
1612
|
|
|
1048
1613
|
const spec = openApiSpec(route) as MppManagementSpec | undefined
|
|
@@ -1066,7 +1631,9 @@ export function installMppManagementRoutes(
|
|
|
1066
1631
|
if (postPaths.has(target.path))
|
|
1067
1632
|
throw new Error(`MPP management POST conflicts with an existing route: ${target.path}`)
|
|
1068
1633
|
|
|
1069
|
-
const management = policy({
|
|
1634
|
+
const management = policy({
|
|
1635
|
+
mpp: { session: mpp.session },
|
|
1636
|
+
}) as MiddlewareHandler & MppManagementHandler
|
|
1070
1637
|
management[mppManagementSymbol] = { description: target.description }
|
|
1071
1638
|
app.post(
|
|
1072
1639
|
stripBasePath(target.path, options.basePath),
|
|
@@ -1127,7 +1694,7 @@ type OpenApiRoute = {
|
|
|
1127
1694
|
}
|
|
1128
1695
|
|
|
1129
1696
|
type PolicyHandler = {
|
|
1130
|
-
[policySymbol]?: policy.Options | undefined
|
|
1697
|
+
[policySymbol]?: policy.Options | false | undefined
|
|
1131
1698
|
}
|
|
1132
1699
|
|
|
1133
1700
|
type MppManagementHandler = {
|
|
@@ -1168,7 +1735,7 @@ function laneDefaults(options: middleware.Options): LaneDefaults {
|
|
|
1168
1735
|
scopes: apiKey?.scopes ?? [Scope.wildcard],
|
|
1169
1736
|
},
|
|
1170
1737
|
mpp: { session: {} },
|
|
1171
|
-
public: { rateLimit: public_?.rateLimit ??
|
|
1738
|
+
public: { rateLimit: public_?.rateLimit ?? defaultPublicRateLimit },
|
|
1172
1739
|
session: true,
|
|
1173
1740
|
}
|
|
1174
1741
|
}
|
|
@@ -1230,6 +1797,7 @@ function resolveApiKeyLane(
|
|
|
1230
1797
|
if (override === true) return current ?? default_
|
|
1231
1798
|
const base = current ?? default_
|
|
1232
1799
|
return {
|
|
1800
|
+
bucket: override.bucket ?? base.bucket,
|
|
1233
1801
|
rateLimit: override.rateLimit ?? base.rateLimit,
|
|
1234
1802
|
scopes: override.scopes ?? base.scopes,
|
|
1235
1803
|
}
|
|
@@ -1245,6 +1813,7 @@ function resolveMppLane(
|
|
|
1245
1813
|
if (override === true) return current ?? default_
|
|
1246
1814
|
const base = current ?? default_
|
|
1247
1815
|
return {
|
|
1816
|
+
bucket: override.bucket ?? base.bucket,
|
|
1248
1817
|
rateLimit: override.rateLimit ?? base.rateLimit,
|
|
1249
1818
|
session: { ...base.session, ...override.session },
|
|
1250
1819
|
}
|
|
@@ -1259,7 +1828,10 @@ function resolvePublicLane(
|
|
|
1259
1828
|
if (override === false) return undefined
|
|
1260
1829
|
if (override === true) return current ?? default_
|
|
1261
1830
|
const base = current ?? default_
|
|
1262
|
-
return {
|
|
1831
|
+
return {
|
|
1832
|
+
bucket: override.bucket ?? base.bucket,
|
|
1833
|
+
rateLimit: override.rateLimit ?? base.rateLimit,
|
|
1834
|
+
}
|
|
1263
1835
|
}
|
|
1264
1836
|
|
|
1265
1837
|
function resolveSessionLane(
|
|
@@ -1304,7 +1876,7 @@ function policies(c: hono_Context) {
|
|
|
1304
1876
|
return matchedRoutes(c)
|
|
1305
1877
|
.slice(c.req.routeIndex + 1)
|
|
1306
1878
|
.map(policyFromRoute)
|
|
1307
|
-
.filter((routePolicy): routePolicy is policy.Options => routePolicy !== undefined)
|
|
1879
|
+
.filter((routePolicy): routePolicy is policy.Options | false => routePolicy !== undefined)
|
|
1308
1880
|
}
|
|
1309
1881
|
|
|
1310
1882
|
function openApiSpec(route: RouterRoute) {
|
|
@@ -1328,6 +1900,8 @@ function mppManagementFromRoute(route: RouterRoute) {
|
|
|
1328
1900
|
export type OperationAccess = {
|
|
1329
1901
|
/** Whether API-key access is allowed. */
|
|
1330
1902
|
apiKey: boolean
|
|
1903
|
+
/** Whether this operation explicitly bypasses auth instead of inheriting document security. */
|
|
1904
|
+
bypass?: true | undefined
|
|
1331
1905
|
/** Whether MPP payment is accepted (enables the `402` payment-challenge response). */
|
|
1332
1906
|
mpp: boolean
|
|
1333
1907
|
/** Whether anonymous public-quota access is allowed (keeps the anonymous security option). */
|
|
@@ -1346,14 +1920,14 @@ export type OperationAccess = {
|
|
|
1346
1920
|
* operation surfaces only the lanes its route opts into via {@link policy}.
|
|
1347
1921
|
*/
|
|
1348
1922
|
export function describeAccess(app: Hono<any, any>): Record<string, OperationAccess> {
|
|
1349
|
-
const groups = new Map<string, { operationId?: string; overrides: PolicyOverride[] }>()
|
|
1923
|
+
const groups = new Map<string, { operationId?: string; overrides: (PolicyOverride | false)[] }>()
|
|
1350
1924
|
for (const route of app.routes) {
|
|
1351
1925
|
const key = `${route.method} ${route.path}`
|
|
1352
1926
|
const group = groups.get(key) ?? { overrides: [] }
|
|
1353
1927
|
const spec = openApiSpec(route) as { operationId?: unknown } | undefined
|
|
1354
1928
|
if (typeof spec?.operationId === 'string') group.operationId = spec.operationId
|
|
1355
1929
|
const override = policyFromRoute(route)
|
|
1356
|
-
if (override) group.overrides.push(override)
|
|
1930
|
+
if (override !== undefined) group.overrides.push(override)
|
|
1357
1931
|
groups.set(key, group)
|
|
1358
1932
|
}
|
|
1359
1933
|
|
|
@@ -1365,7 +1939,12 @@ export function describeAccess(app: Hono<any, any>): Record<string, OperationAcc
|
|
|
1365
1939
|
let public_ = false
|
|
1366
1940
|
let mpp = false
|
|
1367
1941
|
let session = false
|
|
1942
|
+
let bypass = false
|
|
1368
1943
|
for (const override of overrides) {
|
|
1944
|
+
if (override === false) {
|
|
1945
|
+
bypass = true
|
|
1946
|
+
break
|
|
1947
|
+
}
|
|
1369
1948
|
if (override.apiKey !== undefined) apiKey = override.apiKey !== false
|
|
1370
1949
|
if (override.apiKey && override.apiKey !== true && override.apiKey.scopes)
|
|
1371
1950
|
scopes = override.apiKey.scopes
|
|
@@ -1373,7 +1952,14 @@ export function describeAccess(app: Hono<any, any>): Record<string, OperationAcc
|
|
|
1373
1952
|
if (override.mpp !== undefined) mpp = override.mpp !== false
|
|
1374
1953
|
if (override.session !== undefined) session = override.session !== false
|
|
1375
1954
|
}
|
|
1376
|
-
access[operationId] = {
|
|
1955
|
+
access[operationId] = {
|
|
1956
|
+
apiKey,
|
|
1957
|
+
...(bypass ? { bypass: true } : {}),
|
|
1958
|
+
mpp,
|
|
1959
|
+
public: public_,
|
|
1960
|
+
scopes: apiKey ? scopes : [],
|
|
1961
|
+
session,
|
|
1962
|
+
}
|
|
1377
1963
|
}
|
|
1378
1964
|
return access
|
|
1379
1965
|
}
|
|
@@ -1417,16 +2003,23 @@ export function require<environment extends Environment = Environment>(
|
|
|
1417
2003
|
const hasQueryApiKey = new URL(c.req.url).searchParams.has('key')
|
|
1418
2004
|
// Auth owns `key`; strict route schemas must not validate it.
|
|
1419
2005
|
stripApiKeyQuery(c)
|
|
1420
|
-
// Reject unknown chains before MPP builds a chain-bound challenge. Route
|
|
1421
|
-
// groups publish their supported chains into the shared app context.
|
|
1422
2006
|
const chainId = explicitChainId(c)
|
|
1423
2007
|
const supportedChainIds = (c.var as Record<string, unknown>)['supportedChainIds']
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
2008
|
+
const unsupportedChain = (() => {
|
|
2009
|
+
if (
|
|
2010
|
+
chainId === undefined ||
|
|
2011
|
+
!(supportedChainIds instanceof Set) ||
|
|
2012
|
+
supportedChainIds.has(chainId)
|
|
2013
|
+
)
|
|
2014
|
+
return undefined
|
|
2015
|
+
return { chainId, supportedChainIds }
|
|
2016
|
+
})()
|
|
2017
|
+
if (unsupportedChain && !credential)
|
|
2018
|
+
return Response.unsupportedChainId(
|
|
2019
|
+
c,
|
|
2020
|
+
unsupportedChain.chainId,
|
|
2021
|
+
unsupportedChain.supportedChainIds,
|
|
2022
|
+
)
|
|
1430
2023
|
const proceed = async () => {
|
|
1431
2024
|
await next()
|
|
1432
2025
|
// Query credential responses must not enter shared caches.
|
|
@@ -1450,12 +2043,24 @@ export function require<environment extends Environment = Environment>(
|
|
|
1450
2043
|
// The super admin secret precedes key lookup: it is not a stored key.
|
|
1451
2044
|
// It must never reach KV resolution or scope/quota checks.
|
|
1452
2045
|
if (auth.superAdmin && ApiKey.hash(credential.token) === auth.superAdmin.tokenHash) {
|
|
2046
|
+
if (unsupportedChain)
|
|
2047
|
+
return Response.unsupportedChainId(
|
|
2048
|
+
c,
|
|
2049
|
+
unsupportedChain.chainId,
|
|
2050
|
+
unsupportedChain.supportedChainIds,
|
|
2051
|
+
)
|
|
1453
2052
|
c.set('principal', { actor: 'super_admin', id: 'super_admin', type: 'super_admin' })
|
|
1454
2053
|
return proceed()
|
|
1455
2054
|
}
|
|
1456
2055
|
|
|
1457
2056
|
const apiKey_resolved = await auth.apiKey?.resolve(c, credential.token)
|
|
1458
2057
|
if (!apiKey_resolved) {
|
|
2058
|
+
if (unsupportedChain)
|
|
2059
|
+
return Response.unsupportedChainId(
|
|
2060
|
+
c,
|
|
2061
|
+
unsupportedChain.chainId,
|
|
2062
|
+
unsupportedChain.supportedChainIds,
|
|
2063
|
+
)
|
|
1459
2064
|
// A bearer session token is indistinguishable from an API key at the
|
|
1460
2065
|
// header, so a failed key lookup falls through to the session lane
|
|
1461
2066
|
// before rejecting.
|
|
@@ -1498,6 +2103,34 @@ export function require<environment extends Environment = Environment>(
|
|
|
1498
2103
|
status: 403,
|
|
1499
2104
|
})
|
|
1500
2105
|
|
|
2106
|
+
// Non-paid requests consume API-key quota before rejection. Paid
|
|
2107
|
+
// requests use the MPP quota after access checks.
|
|
2108
|
+
const scope = policy.apiKey.scopes[0] ?? Scope.wildcard
|
|
2109
|
+
const throttled = apiKey.environment === 'sandbox' && apiKey.billingActive !== true
|
|
2110
|
+
const limit = throttled
|
|
2111
|
+
? (policy.public?.rateLimit ?? auth.publicRateLimit ?? { limit: 60, period: 'minute' })
|
|
2112
|
+
: resolveApiKeyLimit({ apiKey, auth, policy: policy.apiKey, scope })
|
|
2113
|
+
const paid = hasPayment && !throttled
|
|
2114
|
+
const result = paid
|
|
2115
|
+
? null
|
|
2116
|
+
: await consumeRateLimit(auth, {
|
|
2117
|
+
key: rateLimitKey(`api_key:${apiKey.id}:scope:${scope}`, policy.apiKey.bucket),
|
|
2118
|
+
limit,
|
|
2119
|
+
})
|
|
2120
|
+
if (result) {
|
|
2121
|
+
setRateLimitHeaders(c, result)
|
|
2122
|
+
// Surface the bucket so callers can correlate a 429 with the exhausted
|
|
2123
|
+
// quota. MPP challenges own their headers and drop these by design.
|
|
2124
|
+
c.header('RateLimit-Scope', scope)
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
if (unsupportedChain)
|
|
2128
|
+
return Response.unsupportedChainId(
|
|
2129
|
+
c,
|
|
2130
|
+
unsupportedChain.chainId,
|
|
2131
|
+
unsupportedChain.supportedChainIds,
|
|
2132
|
+
)
|
|
2133
|
+
|
|
1501
2134
|
if (
|
|
1502
2135
|
apiKey.allowedIps.length &&
|
|
1503
2136
|
!(await IpAllowlist.allows(c, {
|
|
@@ -1532,14 +2165,7 @@ export function require<environment extends Environment = Environment>(
|
|
|
1532
2165
|
status: 403,
|
|
1533
2166
|
})
|
|
1534
2167
|
|
|
1535
|
-
|
|
1536
|
-
// `billingActive` is snapshotted on the key record (stamped at mint,
|
|
1537
|
-
// re-synced when billing changes), so this needs no billing read on the
|
|
1538
|
-
// request path. Resolved before the paid lane so a payment credential
|
|
1539
|
-
// can't buy past the throttle: sandbox is non-billable testnet.
|
|
1540
|
-
const throttled = apiKey.environment === 'sandbox' && apiKey.billingActive !== true
|
|
1541
|
-
|
|
1542
|
-
if (hasPayment && !throttled)
|
|
2168
|
+
if (paid)
|
|
1543
2169
|
return requirePayment(c, proceed, {
|
|
1544
2170
|
auth,
|
|
1545
2171
|
payment: { reason: 'api_key_over_quota', type: 'mpp' },
|
|
@@ -1547,39 +2173,17 @@ export function require<environment extends Environment = Environment>(
|
|
|
1547
2173
|
principal,
|
|
1548
2174
|
})
|
|
1549
2175
|
|
|
1550
|
-
if (
|
|
1551
|
-
// A
|
|
1552
|
-
//
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
:
|
|
1560
|
-
const result = await consumeRateLimit(auth, {
|
|
1561
|
-
key: `api_key:${apiKey.id}:scope:${scope}`,
|
|
1562
|
-
limit,
|
|
2176
|
+
if (result && !result.allowed) {
|
|
2177
|
+
// A throttled sandbox key gets a plain 429, never an MPP challenge. It
|
|
2178
|
+
// must activate billing to lift the ceiling, not pay per request.
|
|
2179
|
+
if (throttled) return rateLimitExceeded(c, result)
|
|
2180
|
+
return requirePaymentOrRateLimit(c, proceed, {
|
|
2181
|
+
auth,
|
|
2182
|
+
payment: { reason: 'api_key_over_quota', type: 'mpp' },
|
|
2183
|
+
policy,
|
|
2184
|
+
principal,
|
|
2185
|
+
rateLimit: result,
|
|
1563
2186
|
})
|
|
1564
|
-
if (result) {
|
|
1565
|
-
setRateLimitHeaders(c, result)
|
|
1566
|
-
// Surface the bucket so callers can correlate a 429 with the exhausted
|
|
1567
|
-
// quota. Set before the over-quota branch so it rides the 429 (an MPP
|
|
1568
|
-
// 402 challenge is owned by mppx and drops these headers — by design).
|
|
1569
|
-
c.header('RateLimit-Scope', scope)
|
|
1570
|
-
}
|
|
1571
|
-
if (result && !result.allowed) {
|
|
1572
|
-
// A throttled sandbox key gets a plain 429, never an MPP challenge —
|
|
1573
|
-
// it must activate billing to lift the ceiling, not pay per request.
|
|
1574
|
-
if (throttled) return rateLimitExceeded(c, result)
|
|
1575
|
-
return requirePaymentOrRateLimit(c, proceed, {
|
|
1576
|
-
auth,
|
|
1577
|
-
payment: { reason: 'api_key_over_quota', type: 'mpp' },
|
|
1578
|
-
policy,
|
|
1579
|
-
principal,
|
|
1580
|
-
rateLimit: result,
|
|
1581
|
-
})
|
|
1582
|
-
}
|
|
1583
2187
|
}
|
|
1584
2188
|
|
|
1585
2189
|
return proceed()
|
|
@@ -1610,7 +2214,7 @@ export function require<environment extends Environment = Environment>(
|
|
|
1610
2214
|
const limit = policy.public?.rateLimit
|
|
1611
2215
|
if (limit) {
|
|
1612
2216
|
const result = await consumeRateLimit(auth, {
|
|
1613
|
-
key: `public:${publicPrincipal.id}`,
|
|
2217
|
+
key: rateLimitKey(`public:${publicPrincipal.id}`, policy.public?.bucket),
|
|
1614
2218
|
limit,
|
|
1615
2219
|
})
|
|
1616
2220
|
if (result) setRateLimitHeaders(c, result)
|
|
@@ -1653,6 +2257,8 @@ export declare namespace require {
|
|
|
1653
2257
|
/** API-key access policy. */
|
|
1654
2258
|
apiKey?:
|
|
1655
2259
|
| {
|
|
2260
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
2261
|
+
bucket?: string | undefined
|
|
1656
2262
|
/** API-key quota override for this route (a protective per-route cap). */
|
|
1657
2263
|
rateLimit?: RateLimit.Limit | undefined
|
|
1658
2264
|
/**
|
|
@@ -1666,6 +2272,8 @@ export declare namespace require {
|
|
|
1666
2272
|
/** MPP payment access policy. */
|
|
1667
2273
|
mpp?:
|
|
1668
2274
|
| {
|
|
2275
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
2276
|
+
bucket?: string | undefined
|
|
1669
2277
|
/** Paid-request quota override for this route (a protective per-route cap). */
|
|
1670
2278
|
rateLimit?: RateLimit.Limit | undefined
|
|
1671
2279
|
/** Tempo Session request policy. */
|
|
@@ -1675,11 +2283,13 @@ export declare namespace require {
|
|
|
1675
2283
|
/** Public access policy. */
|
|
1676
2284
|
public?:
|
|
1677
2285
|
| {
|
|
2286
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
2287
|
+
bucket?: string | undefined
|
|
1678
2288
|
/** Anonymous public quota for this route. */
|
|
1679
2289
|
rateLimit: RateLimit.Limit
|
|
1680
2290
|
}
|
|
1681
2291
|
| undefined
|
|
1682
|
-
/** Session access policy: `true` allows signed-in
|
|
2292
|
+
/** Session access policy: `true` allows signed-in sessions. */
|
|
1683
2293
|
session?: boolean | undefined
|
|
1684
2294
|
}
|
|
1685
2295
|
}
|
|
@@ -1709,7 +2319,8 @@ type RateLimitAccess = PaymentAccess & {
|
|
|
1709
2319
|
*/
|
|
1710
2320
|
const rateLimitConsumeTimeout = 300
|
|
1711
2321
|
|
|
1712
|
-
|
|
2322
|
+
/** Consumes one quota and returns null when its counter is unavailable, allowing callers to fail open. */
|
|
2323
|
+
export function consumeRateLimit(
|
|
1713
2324
|
auth: Context,
|
|
1714
2325
|
options: RateLimit.Store.ConsumeOptions,
|
|
1715
2326
|
): Promise<RateLimit.Result | null> {
|
|
@@ -1818,14 +2429,24 @@ function getApiKeyCredential(c: hono_Context): ApiKeyCredential | false | null {
|
|
|
1818
2429
|
}
|
|
1819
2430
|
|
|
1820
2431
|
function clientIp(c: hono_Context, auth: Context): string | undefined {
|
|
1821
|
-
return
|
|
2432
|
+
return (
|
|
2433
|
+
trustedClientIps.get(c.req.raw) ??
|
|
2434
|
+
(auth.publicClientIp ? auth.publicClientIp(c.req.raw) : c.req.header('cf-connecting-ip'))
|
|
2435
|
+
)
|
|
1822
2436
|
}
|
|
1823
2437
|
|
|
1824
2438
|
function trustedClientIp(c: hono_Context, auth: Context): string | undefined {
|
|
1825
|
-
|
|
2439
|
+
return trustedClientIps.get(c.req.raw) ?? resolveTrustedClientIp(c.req.raw, auth.publicClientIp)
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
function resolveTrustedClientIp(
|
|
2443
|
+
request: Request,
|
|
2444
|
+
resolve: ((request: Request) => string | undefined) | undefined,
|
|
2445
|
+
) {
|
|
2446
|
+
if (resolve) return resolve(request)
|
|
1826
2447
|
// Cloudflare supplies both the request metadata and this header.
|
|
1827
|
-
if (!('cf' in
|
|
1828
|
-
return
|
|
2448
|
+
if (!('cf' in request)) return undefined
|
|
2449
|
+
return request.headers.get('cf-connecting-ip') ?? undefined
|
|
1829
2450
|
}
|
|
1830
2451
|
|
|
1831
2452
|
/** Removes the reserved auth query parameter before route validation. */
|
|
@@ -1958,7 +2579,10 @@ async function requirePayment<environment extends Environment>(
|
|
|
1958
2579
|
) {
|
|
1959
2580
|
if (hasPaymentCredential(c)) {
|
|
1960
2581
|
const result = await consumeRateLimit(options.auth, {
|
|
1961
|
-
key:
|
|
2582
|
+
key: rateLimitKey(
|
|
2583
|
+
`mpp:${options.principal.type}:${options.principal.id}`,
|
|
2584
|
+
options.policy.mpp?.bucket,
|
|
2585
|
+
),
|
|
1962
2586
|
limit: options.policy.mpp?.rateLimit ?? options.auth.mpp?.rateLimit ?? defaultMppRateLimit,
|
|
1963
2587
|
})
|
|
1964
2588
|
if (result) {
|
|
@@ -2015,6 +2639,10 @@ function requirePaymentOrRateLimit<environment extends Environment>(
|
|
|
2015
2639
|
return rateLimitExceeded(c, options.rateLimit)
|
|
2016
2640
|
}
|
|
2017
2641
|
|
|
2642
|
+
function rateLimitKey(key: string, bucket: string | undefined) {
|
|
2643
|
+
return bucket === undefined ? key : `${key}:bucket:${bucket}`
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2018
2646
|
/** Emits a `429` with a `Retry-After` derived from the window reset. */
|
|
2019
2647
|
function rateLimitExceeded(c: hono_Context, result: RateLimit.Result) {
|
|
2020
2648
|
c.header('Retry-After', String(Math.max(result.reset - Math.ceil(Date.now() / 1_000), 1)))
|
|
@@ -2050,17 +2678,12 @@ export type Session = {
|
|
|
2050
2678
|
resolve: (c: hono_Context) => Promise<SessionPrincipal | null>
|
|
2051
2679
|
}
|
|
2052
2680
|
|
|
2053
|
-
// Resolve the session lane from the auth context's capability.
|
|
2054
|
-
//
|
|
2681
|
+
// Resolve the session lane from the auth context's capability. Dependency
|
|
2682
|
+
// failures propagate to the app error boundary instead of becoming a `401`.
|
|
2055
2683
|
async function resolveSession(c: hono_Context, auth: Context): Promise<SessionPrincipal | null> {
|
|
2056
2684
|
const session = auth.session
|
|
2057
2685
|
if (!session) return null
|
|
2058
|
-
|
|
2059
|
-
return await session.resolve(c)
|
|
2060
|
-
} catch (error) {
|
|
2061
|
-
console.error('[auth] session resolve failed; treating as no session', error)
|
|
2062
|
-
return null
|
|
2063
|
-
}
|
|
2686
|
+
return session.resolve(c)
|
|
2064
2687
|
}
|
|
2065
2688
|
|
|
2066
2689
|
/** Maximum resolve-cache entries held per isolate before eviction. */
|
|
@@ -2078,40 +2701,53 @@ const cachedMaxEntries = 10_000
|
|
|
2078
2701
|
function cachedResolve(
|
|
2079
2702
|
resolve: (c: hono_Context, token: string) => Promise<ApiKey.ApiKey | null>,
|
|
2080
2703
|
options: middleware.Cache,
|
|
2081
|
-
)
|
|
2704
|
+
) {
|
|
2082
2705
|
const { negativeTtl = 10_000, now = Date.now, ttl = 60_000 } = options
|
|
2083
2706
|
type Cell = { expiresAt: number; value: ApiKey.ApiKey | null }
|
|
2084
2707
|
const cells = new Map<string, Cell>()
|
|
2085
2708
|
const flights = new Map<string, Promise<ApiKey.ApiKey | null>>()
|
|
2086
2709
|
|
|
2087
|
-
return
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
// so
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2710
|
+
return {
|
|
2711
|
+
invalidate(token: string) {
|
|
2712
|
+
cells.delete(`v1:${ApiKey.hash(token)}`)
|
|
2713
|
+
},
|
|
2714
|
+
peek(token: string) {
|
|
2715
|
+
const key = `v1:${ApiKey.hash(token)}`
|
|
2716
|
+
const cell = cells.get(key)
|
|
2717
|
+
if (!cell) return undefined
|
|
2718
|
+
if (cell.expiresAt > now()) return cell.value
|
|
2719
|
+
cells.delete(key)
|
|
2720
|
+
return undefined
|
|
2721
|
+
},
|
|
2722
|
+
async resolve(c: hono_Context, token: string) {
|
|
2723
|
+
// Versioned so a future record-shape change can't serve stale shapes.
|
|
2724
|
+
const key = `v1:${ApiKey.hash(token)}`
|
|
2725
|
+
const cell = cells.get(key)
|
|
2726
|
+
if (cell && cell.expiresAt > now()) return cell.value
|
|
2727
|
+
if (cell) cells.delete(key)
|
|
2728
|
+
|
|
2729
|
+
const existing = flights.get(key)
|
|
2730
|
+
if (existing) return existing
|
|
2731
|
+
|
|
2732
|
+
const flight = (async () => {
|
|
2733
|
+
const value = await resolve(c, token)
|
|
2734
|
+
// Bound the cache: random invalid tokens each add a (negative) entry,
|
|
2735
|
+
// so sweep expired cells at the cap and then drop the oldest.
|
|
2736
|
+
if (cells.size >= cachedMaxEntries) {
|
|
2737
|
+
const time = now()
|
|
2738
|
+
for (const [name, entry] of cells) if (entry.expiresAt <= time) cells.delete(name)
|
|
2739
|
+
while (cells.size >= cachedMaxEntries) cells.delete(cells.keys().next().value as string)
|
|
2740
|
+
}
|
|
2741
|
+
cells.set(key, { expiresAt: now() + (value ? ttl : negativeTtl), value })
|
|
2742
|
+
return value
|
|
2743
|
+
})()
|
|
2744
|
+
flights.set(key, flight)
|
|
2745
|
+
try {
|
|
2746
|
+
return await flight
|
|
2747
|
+
} finally {
|
|
2748
|
+
flights.delete(key)
|
|
2105
2749
|
}
|
|
2106
|
-
|
|
2107
|
-
return value
|
|
2108
|
-
})()
|
|
2109
|
-
flights.set(key, flight)
|
|
2110
|
-
try {
|
|
2111
|
-
return await flight
|
|
2112
|
-
} finally {
|
|
2113
|
-
flights.delete(key)
|
|
2114
|
-
}
|
|
2750
|
+
},
|
|
2115
2751
|
}
|
|
2116
2752
|
}
|
|
2117
2753
|
|