tapimo 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -8
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +5 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +28 -1
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +34 -1
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +7532 -4850
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +11 -3
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +11 -2
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +14 -3
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +63 -53
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +7 -0
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/scopes.d.ts +8 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +3 -0
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +57 -57
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +13 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +151 -0
- package/dist/analytics/Analytics.d.ts.map +1 -0
- package/dist/analytics/Analytics.js +212 -0
- package/dist/analytics/Analytics.js.map +1 -0
- package/dist/analytics/tables/requestEvents.d.ts +215 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -0
- package/dist/analytics/tables/requestEvents.js +264 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -0
- package/dist/apps/data/App.d.ts +1049 -624
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +36 -0
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingRouteProviders.d.ts +54 -0
- package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -0
- package/dist/apps/data/FundingRouteProviders.js +355 -0
- package/dist/apps/data/FundingRouteProviders.js.map +1 -0
- package/dist/apps/data/index.d.ts +1 -0
- package/dist/apps/data/index.d.ts.map +1 -1
- package/dist/apps/data/index.js +1 -0
- package/dist/apps/data/index.js.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +45 -45
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/exchanges.d.ts +455 -455
- package/dist/apps/data/routes/fee-amm.d.ts +101 -101
- package/dist/apps/data/routes/funding.d.ts +843 -0
- package/dist/apps/data/routes/funding.d.ts.map +1 -0
- package/dist/apps/data/routes/funding.js +443 -0
- package/dist/apps/data/routes/funding.js.map +1 -0
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/receipts.d.ts.map +1 -1
- package/dist/apps/data/routes/receipts.js +2 -8
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +29 -36
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +29 -1
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +36 -36
- package/dist/apps/data/routes/transfers.d.ts +56 -56
- package/dist/apps/data/routes/verified-tokens.d.ts +36 -36
- package/dist/apps/data/routes/webhooks.d.ts +45 -45
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +8 -8
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/docs/App.d.ts +5 -3
- package/dist/apps/docs/App.d.ts.map +1 -1
- package/dist/apps/docs/App.js +28 -96
- package/dist/apps/docs/App.js.map +1 -1
- package/dist/apps/docs/reference.d.ts +21 -0
- package/dist/apps/docs/reference.d.ts.map +1 -0
- package/dist/apps/docs/reference.js +112 -0
- package/dist/apps/docs/reference.js.map +1 -0
- package/dist/apps/index.d.ts +3 -2
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +3 -2
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/{platform → management}/App.d.ts +3015 -738
- package/dist/apps/management/App.d.ts.map +1 -0
- package/dist/apps/{platform → management}/App.js +20 -10
- package/dist/apps/management/App.js.map +1 -0
- package/dist/apps/management/Billing.d.ts +279 -0
- package/dist/apps/management/Billing.d.ts.map +1 -0
- package/dist/apps/management/Billing.js +477 -0
- package/dist/apps/management/Billing.js.map +1 -0
- package/dist/apps/management/index.d.ts +3 -0
- package/dist/apps/management/index.d.ts.map +1 -0
- package/dist/apps/management/index.js +3 -0
- package/dist/apps/management/index.js.map +1 -0
- package/dist/apps/{platform → management}/routes/api-keys.d.ts +341 -49
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/api-keys.js +116 -14
- package/dist/apps/management/routes/api-keys.js.map +1 -0
- package/dist/apps/management/routes/billing.d.ts +1520 -0
- package/dist/apps/management/routes/billing.d.ts.map +1 -0
- package/dist/apps/management/routes/billing.js +795 -0
- package/dist/apps/management/routes/billing.js.map +1 -0
- package/dist/apps/{platform → management}/routes/invitations.d.ts +202 -84
- package/dist/apps/management/routes/invitations.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/invitations.js +59 -1
- package/dist/apps/management/routes/invitations.js.map +1 -0
- package/dist/apps/{platform → management}/routes/me.d.ts +17 -17
- package/dist/apps/management/routes/me.d.ts.map +1 -0
- package/dist/apps/management/routes/me.js.map +1 -0
- package/dist/apps/management/routes/members.d.ts.map +1 -0
- package/dist/apps/management/routes/members.js.map +1 -0
- package/dist/apps/{platform → management}/routes/orgs.d.ts +50 -36
- package/dist/apps/management/routes/orgs.d.ts.map +1 -0
- package/dist/apps/{platform → management}/routes/orgs.js +14 -3
- package/dist/apps/management/routes/orgs.js.map +1 -0
- package/dist/apps/{platform → management}/routes/projects.d.ts +97 -97
- package/dist/apps/{platform → management}/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js.map +1 -0
- package/dist/apps/management/routes/scopes.d.ts +107 -0
- package/dist/apps/management/routes/scopes.d.ts.map +1 -0
- package/dist/apps/management/routes/scopes.js +66 -0
- package/dist/apps/management/routes/scopes.js.map +1 -0
- package/dist/apps/management/routes/usage.d.ts +588 -0
- package/dist/apps/management/routes/usage.d.ts.map +1 -0
- package/dist/apps/management/routes/usage.js +391 -0
- package/dist/apps/management/routes/usage.js.map +1 -0
- package/dist/apps/mcp.d.ts +76 -0
- package/dist/apps/mcp.d.ts.map +1 -0
- package/dist/apps/mcp.js +188 -0
- package/dist/apps/mcp.js.map +1 -0
- package/dist/apps/relay/App.d.ts +4 -1
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +118 -10
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +2 -1
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/cli/Cli.d.ts +8 -1
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +11 -3
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +4 -0
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/admin.js +80 -1
- package/dist/cli/commands/admin.js.map +1 -1
- package/dist/db/Db.d.ts +7 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +126 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +79 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +88 -2
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/billingSettings.d.ts +55 -0
- package/dist/db/tables/billingSettings.d.ts.map +1 -0
- package/dist/db/tables/billingSettings.js +70 -0
- package/dist/db/tables/billingSettings.js.map +1 -0
- package/dist/db/tables/invitations.js +2 -2
- package/dist/db/tables/invitations.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +6 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +10 -4
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.js +2 -2
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +121 -0
- package/dist/db/tables/requestUsage.d.ts.map +1 -0
- package/dist/db/tables/requestUsage.js +150 -0
- package/dist/db/tables/requestUsage.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +119 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +155 -2
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/stripeCustomers.d.ts +81 -0
- package/dist/db/tables/stripeCustomers.d.ts.map +1 -0
- package/dist/db/tables/stripeCustomers.js +120 -0
- package/dist/db/tables/stripeCustomers.js.map +1 -0
- package/dist/db/tables/users.js +2 -2
- package/dist/db/tables/users.js.map +1 -1
- package/dist/handlers/internal/sponsorship.d.ts +5 -2
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
- package/dist/handlers/internal/sponsorship.js +19 -5
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/internal/utils.d.ts +10 -3
- package/dist/handlers/internal/utils.d.ts.map +1 -1
- package/dist/handlers/internal/utils.js +14 -6
- package/dist/handlers/internal/utils.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +18 -4
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +149 -77
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +4 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts +10 -0
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +39 -8
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/Fees.d.ts +27 -0
- package/dist/internal/Fees.d.ts.map +1 -0
- package/dist/internal/Fees.js +48 -0
- package/dist/internal/Fees.js.map +1 -0
- package/dist/internal/FundingRoutes.d.ts +915 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -0
- package/dist/internal/FundingRoutes.js +625 -0
- package/dist/internal/FundingRoutes.js.map +1 -0
- package/dist/internal/Id.d.ts +15 -0
- package/dist/internal/Id.d.ts.map +1 -0
- package/dist/internal/Id.js +22 -0
- package/dist/internal/Id.js.map +1 -0
- package/dist/internal/Log.d.ts +2 -0
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +3 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +10 -1
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +8 -1
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +25 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +51 -0
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Schema.d.ts +8 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +7 -0
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +3 -3
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +8 -7
- package/src/ApiKey.ts +9 -2
- package/src/ApiKeys.test.ts +51 -0
- package/src/ApiKeys.ts +50 -1
- package/src/App.test.ts +33 -86718
- package/src/App.ts +26 -8
- package/src/Client.test-d.ts +353 -2
- package/src/Scope.ts +16 -3
- package/src/admin/apps/scopes.test.ts +6 -0
- package/src/admin/apps/scopes.ts +3 -0
- package/src/admin/ui/src/components/Page.tsx +2 -3
- package/src/admin/ui/src/routes/__root.tsx +2 -2
- package/src/admin/ui/src/routes/api-keys.tsx +2 -2
- package/src/admin/ui.generated.ts +13 -13
- package/src/analytics/Analytics.test.ts +527 -0
- package/src/analytics/Analytics.ts +318 -0
- package/src/analytics/tables/requestEvents.ts +523 -0
- package/src/apps/composition.test.ts +26 -13
- package/src/apps/data/App.test.ts +72 -0
- package/src/apps/data/App.ts +37 -0
- package/src/apps/data/FundingRouteProviders.test.ts +281 -0
- package/src/apps/data/FundingRouteProviders.ts +459 -0
- package/src/apps/data/index.ts +1 -0
- package/src/apps/data/routes/funding.test.ts +314 -0
- package/src/apps/data/routes/funding.ts +698 -0
- package/src/apps/data/routes/receipts.ts +2 -9
- package/src/apps/data/routes/rpc.test.ts +78 -2
- package/src/apps/data/routes/rpc.ts +31 -1
- package/src/apps/data/routes/webhooks.test.ts +1 -1
- package/src/apps/data/routes/webhooks.ts +11 -8
- package/src/apps/docs/App.ts +30 -101
- package/src/apps/docs/reference.ts +132 -0
- package/src/apps/index.ts +3 -2
- package/src/apps/{platform → management}/App.ts +56 -17
- package/src/apps/management/Billing.test.ts +530 -0
- package/src/apps/management/Billing.ts +682 -0
- package/src/apps/management/index.ts +2 -0
- package/src/apps/{platform → management}/routes/api-keys.test.ts +172 -9
- package/src/apps/{platform → management}/routes/api-keys.ts +137 -21
- package/src/apps/management/routes/billing.test.ts +1100 -0
- package/src/apps/management/routes/billing.ts +966 -0
- package/src/apps/{platform → management}/routes/invitations.test.ts +55 -7
- package/src/apps/{platform → management}/routes/invitations.ts +69 -1
- package/src/apps/management/routes/me.test.ts +351 -0
- package/src/apps/{platform → management}/routes/orgs.ts +26 -4
- package/src/apps/management/routes/scopes.test.ts +29 -0
- package/src/apps/management/routes/scopes.ts +85 -0
- package/src/apps/management/routes/usage.test.ts +422 -0
- package/src/apps/management/routes/usage.ts +527 -0
- package/src/apps/mcp.test.ts +206 -0
- package/src/apps/mcp.ts +250 -0
- package/src/apps/relay/App.test.ts +457 -8
- package/src/apps/relay/App.ts +120 -12
- package/src/apps/relay/Sponsorships.test.ts +1 -1
- package/src/apps/relay/Sponsorships.ts +2 -1
- package/src/cli/Cli.test.ts +25 -2
- package/src/cli/Cli.ts +17 -2
- package/src/cli/commands/admin.test.ts +83 -0
- package/src/cli/commands/admin.ts +89 -1
- package/src/db/Db.ts +137 -0
- package/src/db/Schema.ts +104 -2
- package/src/db/tables/billingSettings.test.ts +87 -0
- package/src/db/tables/billingSettings.ts +108 -0
- package/src/db/tables/invitations.ts +2 -2
- package/src/db/tables/organizations.test.ts +1 -1
- package/src/db/tables/organizations.ts +15 -5
- package/src/db/tables/projects.ts +2 -2
- package/src/db/tables/requestUsage.ts +231 -0
- package/src/db/tables/sponsoredTransactions.test.ts +108 -1
- package/src/db/tables/sponsoredTransactions.ts +230 -2
- package/src/db/tables/stripeCustomers.test.ts +109 -0
- package/src/db/tables/stripeCustomers.ts +162 -0
- package/src/db/tables/users.ts +2 -2
- package/src/handlers/internal/sponsorship.ts +34 -7
- package/src/handlers/internal/utils.ts +19 -7
- package/src/index.ts +1 -0
- package/src/internal/Auth.test.ts +175 -25
- package/src/internal/Auth.ts +176 -87
- package/src/internal/Cache.ts +5 -1
- package/src/internal/EdgeCache.test.ts +27 -4
- package/src/internal/EdgeCache.ts +47 -9
- package/src/internal/Fees.test.ts +32 -0
- package/src/internal/Fees.ts +51 -0
- package/src/internal/FundingRoutes.test.ts +213 -0
- package/src/internal/FundingRoutes.ts +898 -0
- package/src/internal/Id.test.ts +17 -0
- package/src/internal/Id.ts +24 -0
- package/src/internal/Log.test.ts +1 -0
- package/src/internal/Log.ts +5 -0
- package/src/internal/OpenApi.ts +12 -1
- package/src/internal/RateLimit.test.ts +84 -0
- package/src/internal/RateLimit.ts +70 -0
- package/src/internal/Response.ts +1 -1
- package/src/internal/Schema.ts +8 -0
- package/src/internal/Webhooks.test.ts +3 -3
- package/src/internal/Webhooks.ts +3 -3
- package/dist/apps/platform/App.d.ts.map +0 -1
- package/dist/apps/platform/App.js.map +0 -1
- package/dist/apps/platform/index.d.ts +0 -2
- package/dist/apps/platform/index.d.ts.map +0 -1
- package/dist/apps/platform/index.js +0 -2
- package/dist/apps/platform/index.js.map +0 -1
- package/dist/apps/platform/routes/api-keys.d.ts.map +0 -1
- package/dist/apps/platform/routes/api-keys.js.map +0 -1
- package/dist/apps/platform/routes/invitations.d.ts.map +0 -1
- package/dist/apps/platform/routes/invitations.js.map +0 -1
- package/dist/apps/platform/routes/me.d.ts.map +0 -1
- package/dist/apps/platform/routes/me.js.map +0 -1
- package/dist/apps/platform/routes/members.d.ts.map +0 -1
- package/dist/apps/platform/routes/members.js.map +0 -1
- package/dist/apps/platform/routes/orgs.d.ts.map +0 -1
- package/dist/apps/platform/routes/orgs.js.map +0 -1
- package/dist/apps/platform/routes/projects.js.map +0 -1
- package/src/apps/platform/index.ts +0 -1
- package/src/apps/platform/routes/me.test.ts +0 -121
- /package/dist/apps/{platform → management}/routes/me.js +0 -0
- /package/dist/apps/{platform → management}/routes/members.d.ts +0 -0
- /package/dist/apps/{platform → management}/routes/members.js +0 -0
- /package/dist/apps/{platform → management}/routes/projects.js +0 -0
- /package/src/apps/{platform → management}/routes/me.ts +0 -0
- /package/src/apps/{platform → management}/routes/members.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/members.ts +0 -0
- /package/src/apps/{platform → management}/routes/orgs.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/projects.test.ts +0 -0
- /package/src/apps/{platform → management}/routes/projects.ts +0 -0
|
@@ -175,6 +175,7 @@ describe('require', () => {
|
|
|
175
175
|
expect(entries[0]?.errorCode).toMatchInlineSnapshot(`"api_key_forbidden"`)
|
|
176
176
|
expect(entries[0]?.principal).toMatchInlineSnapshot(`
|
|
177
177
|
{
|
|
178
|
+
"billingActive": false,
|
|
178
179
|
"environment": "production",
|
|
179
180
|
"id": "key_test",
|
|
180
181
|
"orgId": "org_test",
|
|
@@ -499,7 +500,15 @@ describe('require', () => {
|
|
|
499
500
|
describe('environment', () => {
|
|
500
501
|
const sandboxToken = 'secret_sandbox'
|
|
501
502
|
|
|
502
|
-
function createChainApp(
|
|
503
|
+
function createChainApp(
|
|
504
|
+
options: {
|
|
505
|
+
public?: boolean
|
|
506
|
+
publicRateLimit?: RateLimit.Limit
|
|
507
|
+
rateLimit?: RateLimit.Store
|
|
508
|
+
sandboxBillingActive?: boolean
|
|
509
|
+
mpp?: Auth.Context['mpp']
|
|
510
|
+
} = {},
|
|
511
|
+
) {
|
|
503
512
|
const auth: Auth.Context = {
|
|
504
513
|
apiKey: {
|
|
505
514
|
resolve: TestApp.resolver({
|
|
@@ -511,27 +520,33 @@ describe('require', () => {
|
|
|
511
520
|
orgId: 'org_test',
|
|
512
521
|
scopes: [Scope.wildcard],
|
|
513
522
|
token: sandboxToken,
|
|
523
|
+
...(options.sandboxBillingActive === undefined
|
|
524
|
+
? {}
|
|
525
|
+
: { billingActive: options.sandboxBillingActive }),
|
|
514
526
|
},
|
|
515
527
|
],
|
|
516
528
|
}),
|
|
517
529
|
},
|
|
518
|
-
rateLimit: RateLimit.memory(),
|
|
530
|
+
rateLimit: options.rateLimit ?? RateLimit.memory(),
|
|
531
|
+
...(options.publicRateLimit ? { publicRateLimit: options.publicRateLimit } : {}),
|
|
532
|
+
...(options.mpp ? { mpp: options.mpp } : {}),
|
|
519
533
|
}
|
|
520
534
|
const policy: Auth.require.Policy = {
|
|
521
535
|
apiKey: { scopes: [Scope.wildcard] },
|
|
522
536
|
...(options.public === false ? {} : { public: { rateLimit: { perMinute: 60 } } }),
|
|
537
|
+
...(options.mpp ? { mpp: { charge: { amount: '1' } } } : {}),
|
|
523
538
|
}
|
|
524
539
|
const app = new Hono<Auth.Environment>()
|
|
525
540
|
app.use('*', async (c, next) => {
|
|
526
541
|
c.set('auth', auth)
|
|
527
|
-
// Mirror the app default so
|
|
542
|
+
// Mirror the app default (mainnet) so the effective chain is observable.
|
|
528
543
|
c.set('chainId' as never, Viem.defaultChainId as never)
|
|
529
544
|
await next()
|
|
530
545
|
})
|
|
531
546
|
app.use('/protected', Auth.require(policy))
|
|
532
547
|
app.get('/protected', (c) => {
|
|
533
548
|
// Mirror how real handlers resolve the effective chain: explicit query
|
|
534
|
-
// wins, else the context default
|
|
549
|
+
// wins, else the context default. Auth no longer steers this value.
|
|
535
550
|
const raw = c.req.query('chainId')
|
|
536
551
|
const chainId = raw ? Number(raw) : ((c.get('chainId' as never) as number | null) ?? null)
|
|
537
552
|
return c.json({ chainId, principal: Auth.getPrincipal(c)?.type ?? null })
|
|
@@ -539,45 +554,39 @@ describe('require', () => {
|
|
|
539
554
|
return app
|
|
540
555
|
}
|
|
541
556
|
|
|
542
|
-
test('
|
|
557
|
+
test('rejects a sandbox key on explicit mainnet', async () => {
|
|
543
558
|
const app = createChainApp()
|
|
544
559
|
const response = await app.request('/protected?chainId=4217', {
|
|
545
560
|
headers: { 'tempo-api-key': sandboxToken },
|
|
546
561
|
})
|
|
547
|
-
expect(response.status).toMatchInlineSnapshot(`
|
|
548
|
-
// Treated as anonymous (public) rather than rejected; chain stays mainnet.
|
|
562
|
+
expect(response.status).toMatchInlineSnapshot(`403`)
|
|
549
563
|
expect(await response.json()).toMatchInlineSnapshot(`
|
|
550
564
|
{
|
|
551
|
-
"
|
|
552
|
-
|
|
565
|
+
"error": {
|
|
566
|
+
"code": "api_key_forbidden",
|
|
567
|
+
"message": "Sandbox API keys only support testnet. Pass a testnet \`chainId\`.",
|
|
568
|
+
},
|
|
553
569
|
}
|
|
554
570
|
`)
|
|
555
571
|
})
|
|
556
572
|
|
|
557
|
-
test('
|
|
573
|
+
test('rejects a sandbox key on the mainnet alias', async () => {
|
|
558
574
|
const app = createChainApp()
|
|
559
575
|
const response = await app.request('/protected?chainId=mainnet', {
|
|
560
576
|
headers: { 'tempo-api-key': sandboxToken },
|
|
561
577
|
})
|
|
562
|
-
expect(response.status).toMatchInlineSnapshot(`
|
|
563
|
-
expect((await response.json()).
|
|
578
|
+
expect(response.status).toMatchInlineSnapshot(`403`)
|
|
579
|
+
expect((await response.json()).error.code).toMatchInlineSnapshot(`"api_key_forbidden"`)
|
|
564
580
|
})
|
|
565
581
|
|
|
566
|
-
test('a sandbox key on mainnet with no public lane
|
|
582
|
+
test('rejects a sandbox key on explicit mainnet even with no public lane', async () => {
|
|
567
583
|
const app = createChainApp({ public: false })
|
|
568
584
|
const response = await app.request('/protected?chainId=4217', {
|
|
569
585
|
headers: { 'tempo-api-key': sandboxToken },
|
|
570
586
|
})
|
|
571
|
-
//
|
|
572
|
-
expect(response.status).toMatchInlineSnapshot(`
|
|
573
|
-
expect(await response.json()).toMatchInlineSnapshot(`
|
|
574
|
-
{
|
|
575
|
-
"error": {
|
|
576
|
-
"code": "api_key_missing",
|
|
577
|
-
"message": "Missing API key",
|
|
578
|
-
},
|
|
579
|
-
}
|
|
580
|
-
`)
|
|
587
|
+
// A resolved-but-forbidden key is a 403, not anonymous fall-through.
|
|
588
|
+
expect(response.status).toMatchInlineSnapshot(`403`)
|
|
589
|
+
expect((await response.json()).error.code).toMatchInlineSnapshot(`"api_key_forbidden"`)
|
|
581
590
|
})
|
|
582
591
|
|
|
583
592
|
test('uses a sandbox key on an explicit non-mainnet chain', async () => {
|
|
@@ -594,15 +603,17 @@ describe('require', () => {
|
|
|
594
603
|
`)
|
|
595
604
|
})
|
|
596
605
|
|
|
597
|
-
test('
|
|
606
|
+
test('authenticates a sandbox key with no query chain without steering', async () => {
|
|
598
607
|
const app = createChainApp()
|
|
599
608
|
const response = await app.request('/protected', {
|
|
600
609
|
headers: { 'tempo-api-key': sandboxToken },
|
|
601
610
|
})
|
|
611
|
+
// Auth no longer mutates `chainId`; the mainnet default is left for the
|
|
612
|
+
// data group's own sandbox chain guard to reject.
|
|
602
613
|
expect(response.status).toMatchInlineSnapshot(`200`)
|
|
603
614
|
expect(await response.json()).toMatchInlineSnapshot(`
|
|
604
615
|
{
|
|
605
|
-
"chainId":
|
|
616
|
+
"chainId": 4217,
|
|
606
617
|
"principal": "api_key",
|
|
607
618
|
}
|
|
608
619
|
`)
|
|
@@ -621,6 +632,85 @@ describe('require', () => {
|
|
|
621
632
|
}
|
|
622
633
|
`)
|
|
623
634
|
})
|
|
635
|
+
|
|
636
|
+
test('throttles a sandbox key to the public quota when billing is inactive', async () => {
|
|
637
|
+
const app = createChainApp({
|
|
638
|
+
public: true, // policy.public.rateLimit is { perMinute: 60 }
|
|
639
|
+
sandboxBillingActive: false,
|
|
640
|
+
})
|
|
641
|
+
const response = await app.request('/protected?chainId=42431', {
|
|
642
|
+
headers: { 'tempo-api-key': sandboxToken },
|
|
643
|
+
})
|
|
644
|
+
expect(response.status).toBe(200)
|
|
645
|
+
// The public ceiling (60), not the API-key default (100).
|
|
646
|
+
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"60"`)
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
test('grants a sandbox key the full API-key quota when billing is active', async () => {
|
|
650
|
+
const app = createChainApp({
|
|
651
|
+
public: true,
|
|
652
|
+
sandboxBillingActive: true,
|
|
653
|
+
})
|
|
654
|
+
const response = await app.request('/protected?chainId=42431', {
|
|
655
|
+
headers: { 'tempo-api-key': sandboxToken },
|
|
656
|
+
})
|
|
657
|
+
expect(response.status).toBe(200)
|
|
658
|
+
// The API-key default (100), not the public ceiling (60).
|
|
659
|
+
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"100"`)
|
|
660
|
+
})
|
|
661
|
+
|
|
662
|
+
test('throttles a sandbox key to the public quota when billing is unknown', async () => {
|
|
663
|
+
// A sandbox key minted before billing was ever active carries no
|
|
664
|
+
// `billingActive` flag; it falls back to the public quota.
|
|
665
|
+
const app = createChainApp({ public: true })
|
|
666
|
+
const response = await app.request('/protected?chainId=42431', {
|
|
667
|
+
headers: { 'tempo-api-key': sandboxToken },
|
|
668
|
+
})
|
|
669
|
+
expect(response.status).toBe(200)
|
|
670
|
+
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"60"`)
|
|
671
|
+
})
|
|
672
|
+
|
|
673
|
+
test('throttles to the configured public default on API-key-only routes', async () => {
|
|
674
|
+
const app = createChainApp({
|
|
675
|
+
public: false, // no per-route public lane
|
|
676
|
+
publicRateLimit: { perMinute: 7 },
|
|
677
|
+
sandboxBillingActive: false,
|
|
678
|
+
})
|
|
679
|
+
const response = await app.request('/protected?chainId=42431', {
|
|
680
|
+
headers: { 'tempo-api-key': sandboxToken },
|
|
681
|
+
})
|
|
682
|
+
expect(response.status).toBe(200)
|
|
683
|
+
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"7"`)
|
|
684
|
+
})
|
|
685
|
+
|
|
686
|
+
test('returns 429 (never a payment challenge) for a throttled sandbox key over quota', async () => {
|
|
687
|
+
const app = createChainApp({
|
|
688
|
+
mpp: createMppServer(),
|
|
689
|
+
rateLimit: overQuota(),
|
|
690
|
+
sandboxBillingActive: false,
|
|
691
|
+
})
|
|
692
|
+
const response = await app.request('/protected?chainId=42431', {
|
|
693
|
+
headers: { 'tempo-api-key': sandboxToken },
|
|
694
|
+
})
|
|
695
|
+
// A throttled sandbox key must activate billing, not pay per request, so
|
|
696
|
+
// the over-quota response is a plain 429 rather than a 402 MPP challenge.
|
|
697
|
+
expect(response.status).toMatchInlineSnapshot(`429`)
|
|
698
|
+
expect((await response.json()).error.code).toMatchInlineSnapshot(`"rate_limit_exceeded"`)
|
|
699
|
+
})
|
|
700
|
+
|
|
701
|
+
test('ignores a payment credential for a throttled sandbox key under quota', async () => {
|
|
702
|
+
const app = createChainApp({
|
|
703
|
+
mpp: createMppServer(),
|
|
704
|
+
sandboxBillingActive: false,
|
|
705
|
+
})
|
|
706
|
+
const response = await app.request('/protected?chainId=42431', {
|
|
707
|
+
headers: { 'tempo-api-key': sandboxToken, authorization: 'Payment paid' },
|
|
708
|
+
})
|
|
709
|
+
// The payment lane can't buy past the throttle; the request runs on the
|
|
710
|
+
// public quota instead of being charged.
|
|
711
|
+
expect(response.status).toBe(200)
|
|
712
|
+
expect(response.headers.get('RateLimit-Limit')).toMatchInlineSnapshot(`"60"`)
|
|
713
|
+
})
|
|
624
714
|
})
|
|
625
715
|
|
|
626
716
|
describe('mpp', () => {
|
|
@@ -921,6 +1011,65 @@ describe('require', () => {
|
|
|
921
1011
|
error.mockRestore()
|
|
922
1012
|
}
|
|
923
1013
|
})
|
|
1014
|
+
|
|
1015
|
+
test('fails open (at warn) when the rate-limit Durable Object errors retryably', async () => {
|
|
1016
|
+
const error = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
1017
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
1018
|
+
try {
|
|
1019
|
+
const app = createApp({
|
|
1020
|
+
auth: {
|
|
1021
|
+
apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
|
|
1022
|
+
rateLimit: {
|
|
1023
|
+
async consume() {
|
|
1024
|
+
// A transient transport fault whose single retry also failed.
|
|
1025
|
+
throw Object.assign(new Error('Network connection lost.'), { retryable: true })
|
|
1026
|
+
},
|
|
1027
|
+
},
|
|
1028
|
+
},
|
|
1029
|
+
policy: { public: { rateLimit: { perMinute: 1 } } },
|
|
1030
|
+
})
|
|
1031
|
+
const response = await app.request('/protected', {
|
|
1032
|
+
headers: { 'x-forwarded-for': '203.0.113.10' },
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
expect(response.status).toMatchInlineSnapshot(`200`)
|
|
1036
|
+
expect(response.headers.has('ratelimit-limit')).toMatchInlineSnapshot(`false`)
|
|
1037
|
+
expect(warn.mock.calls.length).toMatchInlineSnapshot(`1`)
|
|
1038
|
+
expect(error.mock.calls.length).toMatchInlineSnapshot(`0`)
|
|
1039
|
+
} finally {
|
|
1040
|
+
warn.mockRestore()
|
|
1041
|
+
error.mockRestore()
|
|
1042
|
+
}
|
|
1043
|
+
})
|
|
1044
|
+
|
|
1045
|
+
test('fails open (at warn) on a redacted Durable Object internal error', async () => {
|
|
1046
|
+
const error = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
1047
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
1048
|
+
try {
|
|
1049
|
+
const app = createApp({
|
|
1050
|
+
auth: {
|
|
1051
|
+
apiKey: { resolve: TestApp.resolver({ keys: [{ ...key, token }] }) },
|
|
1052
|
+
rateLimit: {
|
|
1053
|
+
async consume() {
|
|
1054
|
+
throw new Error(`internal error; reference = ${'ab12'.repeat(6)}`)
|
|
1055
|
+
},
|
|
1056
|
+
},
|
|
1057
|
+
},
|
|
1058
|
+
policy: { public: { rateLimit: { perMinute: 1 } } },
|
|
1059
|
+
})
|
|
1060
|
+
const response = await app.request('/protected', {
|
|
1061
|
+
headers: { 'x-forwarded-for': '203.0.113.10' },
|
|
1062
|
+
})
|
|
1063
|
+
|
|
1064
|
+
expect(response.status).toMatchInlineSnapshot(`200`)
|
|
1065
|
+
expect(response.headers.has('ratelimit-limit')).toMatchInlineSnapshot(`false`)
|
|
1066
|
+
expect(warn.mock.calls.length).toMatchInlineSnapshot(`1`)
|
|
1067
|
+
expect(error.mock.calls.length).toMatchInlineSnapshot(`0`)
|
|
1068
|
+
} finally {
|
|
1069
|
+
warn.mockRestore()
|
|
1070
|
+
error.mockRestore()
|
|
1071
|
+
}
|
|
1072
|
+
})
|
|
924
1073
|
})
|
|
925
1074
|
|
|
926
1075
|
describe('rateLimit per-scope', () => {
|
|
@@ -1113,6 +1262,7 @@ describe('require', () => {
|
|
|
1113
1262
|
expect(response.headers.get('ratelimit-limit')).toMatchInlineSnapshot(`"1"`)
|
|
1114
1263
|
expect(entries[0]?.principal).toMatchInlineSnapshot(`
|
|
1115
1264
|
{
|
|
1265
|
+
"billingActive": false,
|
|
1116
1266
|
"environment": "production",
|
|
1117
1267
|
"id": "key_test",
|
|
1118
1268
|
"orgId": "org_test",
|