tapimo 0.19.0 → 0.20.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 +13 -5
- package/dist/ApiKey.d.ts +2 -2
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +2 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +85 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +218 -56
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +12543 -13912
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +4 -5
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +12 -20
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +20 -36
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +871 -828
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +14 -26
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +93 -186
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +3 -5
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/audit-logs.d.ts +18 -18
- package/dist/admin/apps/audit-logs.js +1 -1
- package/dist/admin/apps/audit-logs.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +27 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +11 -5
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +17 -17
- package/dist/admin/apps/prop-amms.d.ts +4 -4
- package/dist/admin/apps/routes-support.js +1 -38
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +153 -153
- package/dist/admin/apps/sentinel.d.ts +4 -4
- package/dist/admin/apps/verified-tokens.d.ts +24 -24
- package/dist/admin/apps/zone-delegation-requests.d.ts +332 -0
- package/dist/admin/apps/zone-delegation-requests.d.ts.map +1 -0
- package/dist/admin/apps/zone-delegation-requests.js +200 -0
- package/dist/admin/apps/zone-delegation-requests.js.map +1 -0
- package/dist/admin/apps/zone-delegations.d.ts +512 -52
- package/dist/admin/apps/zone-delegations.d.ts.map +1 -1
- package/dist/admin/apps/zone-delegations.js +134 -44
- package/dist/admin/apps/zone-delegations.js.map +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +341 -397
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +4 -2
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +11932 -13214
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +32 -13
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +1 -1
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
- package/dist/apps/data/ZoneSelection.js +2 -2
- package/dist/apps/data/ZoneSelection.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +60 -27
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +91 -16
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +893 -875
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +36 -36
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +3 -1
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +40 -40
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +3 -7
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +236 -236
- package/dist/apps/data/routes/earn-transactions.d.ts +14 -14
- package/dist/apps/data/routes/earn.d.ts +261 -1445
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +64 -490
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +144 -144
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +5 -15
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +3 -9
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +13 -13
- package/dist/apps/data/routes/receipts.d.ts +53 -53
- package/dist/apps/data/routes/receipts.js +1 -1
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +52 -0
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +19 -18
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +14 -14
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +1 -3
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +7 -5
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +281 -281
- package/dist/apps/data/routes/transactions.js +3 -3
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +12 -12
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +1 -3
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +30 -30
- package/dist/apps/data/routes/valuation.d.ts.map +1 -1
- package/dist/apps/data/routes/valuation.js +1 -3
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
- package/dist/apps/data/routes/webhooks.d.ts +102 -102
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +9 -23
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zone-deposits.d.ts +16 -16
- package/dist/apps/data/routes/zone-withdrawals.d.ts +31 -31
- package/dist/apps/data/routes/zones.d.ts +28 -28
- package/dist/apps/management/App.d.ts +18 -102
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +1 -1
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +253 -339
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +25 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +92 -92
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +5 -13
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/cli.d.ts.map +1 -1
- package/dist/apps/management/routes/cli.js +3 -9
- package/dist/apps/management/routes/cli.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +16 -16
- package/dist/apps/management/routes/fee-payer-usage.d.ts +38 -38
- package/dist/apps/management/routes/fee-payer-usage.d.ts.map +1 -1
- package/dist/apps/management/routes/fee-payer-usage.js +2 -4
- package/dist/apps/management/routes/fee-payer-usage.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +52 -52
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +4 -12
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +6 -14
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +3 -7
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +84 -84
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +2 -4
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +44 -44
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +2 -6
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +2 -6
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/route-usage.d.ts +34 -34
- package/dist/apps/management/routes/route-usage.d.ts.map +1 -1
- package/dist/apps/management/routes/route-usage.js +2 -4
- package/dist/apps/management/routes/route-usage.js.map +1 -1
- package/dist/apps/management/routes/routes-access-requests.d.ts +120 -91
- package/dist/apps/management/routes/routes-access-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/routes-access-requests.js +49 -9
- package/dist/apps/management/routes/routes-access-requests.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +8 -16
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +39 -39
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +3 -7
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +2089 -2089
- package/dist/apps/management/routes/zone-delegations.d.ts +14 -17
- package/dist/apps/management/routes/zone-delegations.d.ts.map +1 -1
- package/dist/apps/management/routes/zone-delegations.js +1 -6
- package/dist/apps/management/routes/zone-delegations.js.map +1 -1
- package/dist/apps/mpp/App.d.ts +44 -44
- package/dist/apps/mpp/App.js +3 -3
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +1 -1
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/apps/mpp/internal/Error.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Error.js +1 -0
- package/dist/apps/mpp/internal/Error.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts +5 -1
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +35 -13
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/relay/App.d.ts +2 -2
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +25 -16
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/routes/App.d.ts +311 -311
- package/dist/apps/routes/routes/deposit-addresses.d.ts +1099 -1099
- package/dist/apps/routes/routes/list.d.ts +74 -74
- package/dist/apps/routes/routes/transfers.d.ts +94 -94
- package/dist/cli/ApiKeys.d.ts +19 -26
- package/dist/cli/ApiKeys.d.ts.map +1 -1
- package/dist/db/Db.d.ts +3 -3
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +27 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +28 -62
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +18 -18
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts +21 -0
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +19 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/routesAccessRequests.d.ts +13 -0
- package/dist/db/tables/routesAccessRequests.d.ts.map +1 -1
- package/dist/db/tables/routesAccessRequests.js +12 -0
- package/dist/db/tables/routesAccessRequests.js.map +1 -1
- package/dist/db/tables/zoneDelegationRequests.d.ts +165 -0
- package/dist/db/tables/zoneDelegationRequests.d.ts.map +1 -0
- package/dist/db/tables/{zoneKeyRequests.js → zoneDelegationRequests.js} +43 -42
- package/dist/db/tables/zoneDelegationRequests.js.map +1 -0
- package/dist/db/tables/zoneDelegations.d.ts +11 -5
- package/dist/db/tables/zoneDelegations.d.ts.map +1 -1
- package/dist/db/tables/zoneDelegations.js +21 -3
- package/dist/db/tables/zoneDelegations.js.map +1 -1
- package/dist/handlers/internal/accounts.d.ts +7 -0
- package/dist/handlers/internal/accounts.d.ts.map +1 -0
- package/dist/handlers/internal/{multisig.js → accounts.js} +10 -10
- package/dist/handlers/internal/{multisig.js.map → accounts.js.map} +1 -1
- package/dist/handlers/internal/sponsorship.js +17 -17
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/relay.d.ts +6 -6
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +15 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +4 -8
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/EarnRates.d.ts.map +1 -1
- package/dist/internal/EarnRates.js +1 -3
- package/dist/internal/EarnRates.js.map +1 -1
- package/dist/internal/EarnVaults.js +2 -2
- package/dist/internal/Log.d.ts +2 -4
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +0 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +0 -3
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +11 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +24 -1
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/ZoneAccess.d.ts +70 -35
- package/dist/internal/ZoneAccess.d.ts.map +1 -1
- package/dist/internal/ZoneAccess.js +312 -131
- package/dist/internal/ZoneAccess.js.map +1 -1
- package/dist/internal/ZoneDelegation.d.ts +7 -19
- package/dist/internal/ZoneDelegation.d.ts.map +1 -1
- package/dist/internal/ZoneDelegation.js +8 -29
- package/dist/internal/ZoneDelegation.js.map +1 -1
- package/dist/internal/{ZoneKeyApproval.d.ts → ZoneDelegationApproval.d.ts} +3 -5
- package/dist/internal/ZoneDelegationApproval.d.ts.map +1 -0
- package/dist/internal/ZoneDelegationApproval.js +16 -0
- package/dist/internal/ZoneDelegationApproval.js.map +1 -0
- package/dist/internal/ZoneKeyRewrite.d.ts +98 -0
- package/dist/internal/ZoneKeyRewrite.d.ts.map +1 -0
- package/dist/internal/ZoneKeyRewrite.js +151 -0
- package/dist/internal/ZoneKeyRewrite.js.map +1 -0
- package/dist/internal/rewards/Campaigns.d.ts +2 -0
- package/dist/internal/rewards/Campaigns.d.ts.map +1 -1
- package/dist/internal/rewards/Campaigns.js.map +1 -1
- package/dist/internal/rewards/Distributions.d.ts.map +1 -1
- package/dist/internal/rewards/Distributions.js +2 -6
- package/dist/internal/rewards/Distributions.js.map +1 -1
- package/dist/internal/rewards/Monitor.d.ts +4 -1
- package/dist/internal/rewards/Monitor.d.ts.map +1 -1
- package/dist/internal/rewards/Monitor.js +19 -2
- package/dist/internal/rewards/Monitor.js.map +1 -1
- package/dist/internal/rewards/Runner.d.ts.map +1 -1
- package/dist/internal/rewards/Runner.js +9 -1
- package/dist/internal/rewards/Runner.js.map +1 -1
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +2 -3
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Deposit.d.ts.map +1 -1
- package/dist/internal/routes/Deposit.js +2 -6
- package/dist/internal/routes/Deposit.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +4 -10
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Policy.d.ts.map +1 -1
- package/dist/internal/routes/Policy.js +2 -1
- package/dist/internal/routes/Policy.js.map +1 -1
- package/dist/internal/routes/Provider.js +8 -8
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +3 -2
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +4 -12
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/UniversalDepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/UniversalDepositAddress.js +3 -6
- package/dist/internal/routes/UniversalDepositAddress.js.map +1 -1
- package/dist/internal/routes/providers/SquidOrder.d.ts.map +1 -1
- package/dist/internal/routes/providers/SquidOrder.js +3 -2
- package/dist/internal/routes/providers/SquidOrder.js.map +1 -1
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +4 -3
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/package.json +20 -5
- package/src/ApiKey.ts +2 -2
- package/src/ApiKeys.test.ts +284 -51
- package/src/ApiKeys.ts +297 -64
- package/src/App.ts +4 -5
- package/src/Client.test-d.ts +33 -126
- package/src/Scope.test.ts +26 -45
- package/src/Scope.ts +24 -37
- package/src/admin/App.test.ts +51 -4
- package/src/admin/App.ts +25 -33
- package/src/admin/Mcp.test.ts +2 -1
- package/src/admin/apps/api-keys.test.ts +90 -20
- package/src/admin/apps/api-keys.ts +5 -8
- package/src/admin/apps/audit-logs.ts +1 -1
- package/src/admin/apps/earn-vaults.test.ts +19 -19
- package/src/admin/apps/earn-vaults.ts +11 -5
- package/src/admin/apps/routes-support.test.ts +254 -3
- package/src/admin/apps/routes-support.ts +1 -44
- package/src/admin/apps/scopes.test.ts +3 -3
- package/src/admin/apps/zone-delegation-requests.test.ts +246 -0
- package/src/admin/apps/zone-delegation-requests.ts +240 -0
- package/src/admin/apps/zone-delegations.test.ts +218 -58
- package/src/admin/apps/zone-delegations.ts +146 -46
- package/src/admin/index.ts +1 -1
- package/src/admin/ui/src/components/ApiKeyForm.tsx +4 -3
- package/src/admin/ui/src/lib/config.ts +3 -3
- package/src/admin/ui/src/lib/query-client.ts +1 -1
- package/src/admin/ui/src/lib/review-queues.ts +10 -10
- package/src/admin/ui/src/lib/routes-setup.test.ts +1 -2
- package/src/admin/ui/src/lib/routes-setup.ts +3 -5
- package/src/admin/ui/src/lib/scopes.test.ts +3 -6
- package/src/admin/ui/src/lib/scopes.ts +2 -9
- package/src/admin/ui/src/lib/{zone-key-requests.ts → zone-delegation-requests.ts} +27 -31
- package/src/admin/ui/src/routeTree.gen.ts +17 -17
- package/src/admin/ui/src/routes/__root.tsx +1 -1
- package/src/admin/ui/src/routes/api-keys.tsx +2 -15
- package/src/admin/ui/src/routes/audit-logs.tsx +2 -2
- package/src/admin/ui/src/routes/index.tsx +11 -11
- package/src/admin/ui/src/routes/organizations.tsx +3 -1
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +3 -1
- package/src/admin/ui/src/routes/organizations_.$orgId_.setup.tsx +1 -3
- package/src/admin/ui/src/routes/{zone-key-requests.tsx → zone-delegation-requests.tsx} +228 -172
- package/src/admin/ui/vite.config.ts +14 -1
- package/src/admin/ui.generated.ts +412 -583
- package/src/analytics/tables/requestEvents.test.ts +13 -3
- package/src/analytics/tables/requestEvents.ts +4 -3
- package/src/apps/data/App.test.ts +72 -35
- package/src/apps/data/App.ts +29 -13
- package/src/apps/data/ZoneSelection.test.ts +53 -70
- package/src/apps/data/ZoneSelection.ts +2 -2
- package/src/apps/data/routes/activities.test.ts +140 -6
- package/src/apps/data/routes/activities.ts +124 -18
- package/src/apps/data/routes/balances.ts +5 -1
- package/src/apps/data/routes/blocks.ts +9 -13
- package/src/apps/data/routes/earn-transactions.local.test.ts +6 -1
- package/src/apps/data/routes/earn-transactions.test.ts +7 -3
- package/src/apps/data/routes/earn.bench.ts +0 -14
- package/src/apps/data/routes/earn.discovery.test.ts +4 -39
- package/src/apps/data/routes/earn.local.test.ts +27 -34
- package/src/apps/data/routes/earn.test.ts +172 -490
- package/src/apps/data/routes/earn.ts +103 -652
- package/src/apps/data/routes/exchanges.ts +20 -30
- package/src/apps/data/routes/fee-amm.ts +12 -18
- package/src/apps/data/routes/indexer.test.ts +14 -12
- package/src/apps/data/routes/receipts.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +23 -18
- package/src/apps/data/routes/rpc.ts +21 -21
- package/src/apps/data/routes/rpc.zone.test.ts +60 -6
- package/src/apps/data/routes/tokenlist.ts +4 -6
- package/src/apps/data/routes/tokens.test.ts +20 -0
- package/src/apps/data/routes/tokens.ts +10 -5
- package/src/apps/data/routes/transactions.ts +3 -3
- package/src/apps/data/routes/transfers.ts +4 -6
- package/src/apps/data/routes/valuation.test.ts +2 -4
- package/src/apps/data/routes/valuation.ts +4 -6
- package/src/apps/data/routes/webhooks.test.ts +1 -5
- package/src/apps/data/routes/webhooks.ts +30 -44
- package/src/apps/data/routes/zones.test.ts +35 -19
- package/src/apps/management/App.ts +3 -1
- package/src/apps/management/routes/api-keys.test.ts +112 -22
- package/src/apps/management/routes/api-keys.ts +30 -15
- package/src/apps/management/routes/billing.ts +17 -25
- package/src/apps/management/routes/cli.ts +12 -18
- package/src/apps/management/routes/fee-payer-usage.ts +5 -4
- package/src/apps/management/routes/invitations.ts +16 -21
- package/src/apps/management/routes/invite-links.ts +18 -26
- package/src/apps/management/routes/me.ts +9 -13
- package/src/apps/management/routes/members.ts +5 -7
- package/src/apps/management/routes/orgs.ts +8 -12
- package/src/apps/management/routes/projects.ts +8 -12
- package/src/apps/management/routes/route-usage.ts +5 -4
- package/src/apps/management/routes/routes-access-requests.test.ts +64 -2
- package/src/apps/management/routes/routes-access-requests.ts +99 -15
- package/src/apps/management/routes/scopes.test.ts +3 -3
- package/src/apps/management/routes/usage.ts +20 -28
- package/src/apps/management/routes/verified-token-requests.ts +9 -13
- package/src/apps/management/routes/zone-delegations.test.ts +3 -5
- package/src/apps/management/routes/zone-delegations.ts +4 -9
- package/src/apps/mpp/App.ts +3 -3
- package/src/apps/mpp/Mpp.zone.test.ts +49 -18
- package/src/apps/mpp/internal/Adapter.ts +1 -1
- package/src/apps/mpp/internal/Error.test.ts +3 -0
- package/src/apps/mpp/internal/Error.ts +1 -0
- package/src/apps/mpp/internal/Policy.test.ts +9 -8
- package/src/apps/mpp/internal/Policy.ts +37 -14
- package/src/apps/relay/App.sandbox.test.ts +15 -14
- package/src/apps/relay/App.test.ts +120 -61
- package/src/apps/relay/App.ts +28 -18
- package/src/apps/relay/App.zone-billing.test.ts +9 -4
- package/src/apps/routes/App.test.ts +21 -22
- package/src/db/Db.ts +34 -3
- package/src/db/Schema.ts +26 -26
- package/src/db/tables/rewardRuns.ts +39 -0
- package/src/db/tables/routesAccessRequests.test.ts +65 -0
- package/src/db/tables/routesAccessRequests.ts +25 -0
- package/src/db/tables/{zoneKeyRequests.test.ts → zoneDelegationRequests.test.ts} +36 -77
- package/src/db/tables/{zoneKeyRequests.ts → zoneDelegationRequests.ts} +69 -52
- package/src/db/tables/zoneDelegations.test.ts +5 -6
- package/src/db/tables/zoneDelegations.ts +25 -8
- package/src/handlers/internal/{multisig.store.test.ts → accounts.store.test.ts} +16 -16
- package/src/handlers/internal/{multisig.test.ts → accounts.test.ts} +85 -82
- package/src/handlers/internal/{multisig.ts → accounts.ts} +9 -9
- package/src/handlers/internal/sponsorship.ts +20 -20
- package/src/handlers/relay.test.ts +48 -46
- package/src/handlers/relay.ts +26 -26
- package/src/internal/Auth.test.ts +6 -2
- package/src/internal/Auth.ts +4 -10
- package/src/internal/EarnRates.ts +4 -6
- package/src/internal/EarnVaults.ts +2 -2
- package/src/internal/Log.test-d.ts +1 -0
- package/src/internal/Log.test.ts +4 -6
- package/src/internal/Log.ts +2 -6
- package/src/internal/Response.ts +0 -3
- package/src/internal/Schema.test.ts +42 -0
- package/src/internal/Schema.ts +36 -1
- package/src/internal/ZoneAccess.test.ts +515 -312
- package/src/internal/ZoneAccess.ts +410 -158
- package/src/internal/ZoneDelegation.test.ts +1 -41
- package/src/internal/ZoneDelegation.ts +10 -48
- package/src/internal/ZoneDelegationApproval.test.ts +22 -0
- package/src/internal/{ZoneKeyApproval.ts → ZoneDelegationApproval.ts} +4 -11
- package/src/internal/ZoneKeyRewrite.ts +231 -0
- package/src/internal/rewards/Campaigns.ts +2 -0
- package/src/internal/rewards/Distributions.ts +8 -12
- package/src/internal/rewards/Monitor.test.ts +64 -0
- package/src/internal/rewards/Monitor.ts +27 -4
- package/src/internal/rewards/Runner.ts +9 -1
- package/src/internal/routes/Action.ts +5 -6
- package/src/internal/routes/Deposit.ts +8 -12
- package/src/internal/routes/DepositAddress.ts +13 -19
- package/src/internal/routes/Policy.ts +2 -1
- package/src/internal/routes/Provider.ts +8 -8
- package/src/internal/routes/Reconciliation.ts +3 -2
- package/src/internal/routes/Transfer.ts +16 -24
- package/src/internal/routes/UniversalDepositAddress.ts +9 -12
- package/src/internal/routes/providers/SquidOrder.ts +3 -2
- package/src/internal/routes/providers/relay.ts +4 -3
- package/dist/admin/apps/zone-key-requests.d.ts +0 -406
- package/dist/admin/apps/zone-key-requests.d.ts.map +0 -1
- package/dist/admin/apps/zone-key-requests.js +0 -183
- package/dist/admin/apps/zone-key-requests.js.map +0 -1
- package/dist/db/tables/zoneKeyRequests.d.ts +0 -289
- package/dist/db/tables/zoneKeyRequests.d.ts.map +0 -1
- package/dist/db/tables/zoneKeyRequests.js.map +0 -1
- package/dist/handlers/internal/multisig.d.ts +0 -7
- package/dist/handlers/internal/multisig.d.ts.map +0 -1
- package/dist/internal/ZoneKeyApproval.d.ts.map +0 -1
- package/dist/internal/ZoneKeyApproval.js +0 -21
- package/dist/internal/ZoneKeyApproval.js.map +0 -1
- package/src/admin/apps/zone-key-requests.test.ts +0 -272
- package/src/admin/apps/zone-key-requests.ts +0 -231
- package/src/internal/ZoneKeyApproval.test.ts +0 -46
|
@@ -78,6 +78,13 @@ describe('readBillableCounts', () => {
|
|
|
78
78
|
request_id: 'request-client-canceled',
|
|
79
79
|
status: 499,
|
|
80
80
|
},
|
|
81
|
+
// A Zone request refused because delegations could not be read never bills, nor do its retries.
|
|
82
|
+
{
|
|
83
|
+
...rows[0]!,
|
|
84
|
+
error_code: 'zone_access_unavailable',
|
|
85
|
+
request_id: 'request-zone-access-unavailable',
|
|
86
|
+
status: 503,
|
|
87
|
+
},
|
|
81
88
|
// Admitted handlers may already have reached upstreams, so the cancellation bills.
|
|
82
89
|
{
|
|
83
90
|
...rows[0]!,
|
|
@@ -103,7 +110,7 @@ describe('readBillableCounts', () => {
|
|
|
103
110
|
.toMatchInlineSnapshot(`
|
|
104
111
|
[
|
|
105
112
|
{
|
|
106
|
-
"count":
|
|
113
|
+
"count": 18,
|
|
107
114
|
},
|
|
108
115
|
]
|
|
109
116
|
`)
|
|
@@ -554,9 +561,12 @@ describe('createQueueSink', () => {
|
|
|
554
561
|
test('stores the Zone access decision and trusted client IP', async () => {
|
|
555
562
|
const chainId = 421_700_001
|
|
556
563
|
const rows: RequestEvents.Table[] = []
|
|
557
|
-
const key = { ...TestApp.key, scopes: ['data:read',
|
|
564
|
+
const key = TestApp.zoneReader({ ...TestApp.key, scopes: ['data:read'] }, [chainId])
|
|
565
|
+
const db = TestApp.database()
|
|
566
|
+
await TestApp.delegateZone(db, { chainIds: [chainId] })
|
|
558
567
|
const app = TestApp.create({
|
|
559
568
|
auth: { keys: [key] },
|
|
569
|
+
db,
|
|
560
570
|
metrics: Metrics.cloudflare({
|
|
561
571
|
analytics: RequestEvents.createQueueSink({
|
|
562
572
|
async send(row) {
|
|
@@ -591,7 +601,7 @@ describe('createQueueSink', () => {
|
|
|
591
601
|
"principal_type": "api_key",
|
|
592
602
|
"zone_accounts": [],
|
|
593
603
|
"zone_chain_id": 421700001,
|
|
594
|
-
"zone_grant": "
|
|
604
|
+
"zone_grant": "delegation",
|
|
595
605
|
},
|
|
596
606
|
{
|
|
597
607
|
"client_ip": null,
|
|
@@ -507,7 +507,8 @@ export async function readBillableCounts(
|
|
|
507
507
|
'client_canceled',
|
|
508
508
|
'forbidden',
|
|
509
509
|
'payment_required',
|
|
510
|
-
'rate_limit_exceeded'
|
|
510
|
+
'rate_limit_exceeded',
|
|
511
|
+
'zone_access_unavailable'
|
|
511
512
|
)
|
|
512
513
|
AND key_environment = ${ClickHouseValue.literal(options.environment)}
|
|
513
514
|
${sandboxGate}
|
|
@@ -582,8 +583,8 @@ function event(entry: Log.Entry, context: Metrics.cloudflare.Context): Table {
|
|
|
582
583
|
timings: entry.timings ?? {},
|
|
583
584
|
zone_accounts: entry.zoneAccounts ?? [],
|
|
584
585
|
zone_chain_id: entry.zoneChainId ?? null,
|
|
585
|
-
|
|
586
|
-
|
|
586
|
+
// Retired column: delegations decide admission, so there is no scope decision to compare against.
|
|
587
|
+
zone_decision_agreement: null,
|
|
587
588
|
zone_delegation_decision: entry.zoneDelegationDecision ?? null,
|
|
588
589
|
zone_delegation_id: entry.zoneDelegationId ?? null,
|
|
589
590
|
zone_grant: entry.zoneGrant ?? null,
|
|
@@ -211,12 +211,15 @@ describe('zone chain gate', () => {
|
|
|
211
211
|
/** A second zone, isolating per-zone grants. */
|
|
212
212
|
const zoneB = 4_217_000_002
|
|
213
213
|
|
|
214
|
-
const legacyModeratoReader =
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
const legacyModeratoReader = TestApp.zoneReader(
|
|
215
|
+
{
|
|
216
|
+
id: 'key_legacy_moderato',
|
|
217
|
+
orgId: 'org_test',
|
|
218
|
+
scopes: ['data:read', 'indexer:query'],
|
|
219
|
+
token: 'secret_legacy_moderato',
|
|
220
|
+
},
|
|
221
|
+
[moderato],
|
|
222
|
+
)
|
|
220
223
|
|
|
221
224
|
function zoneOptions(
|
|
222
225
|
chainId: number,
|
|
@@ -229,21 +232,22 @@ describe('zone chain gate', () => {
|
|
|
229
232
|
})
|
|
230
233
|
}
|
|
231
234
|
|
|
232
|
-
/** Zone reader:
|
|
233
|
-
const zoneReader =
|
|
234
|
-
id: 'key_zone',
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
token: 'secret_zone',
|
|
238
|
-
} satisfies TestApp.kvStore.Key
|
|
235
|
+
/** Zone reader: tagged for `zone` (only) under a delegated organization. */
|
|
236
|
+
const zoneReader = TestApp.zoneReader(
|
|
237
|
+
{ id: 'key_zone', orgId: 'org_test', scopes: ['data:read'], token: 'secret_zone' },
|
|
238
|
+
[zone],
|
|
239
|
+
)
|
|
239
240
|
|
|
240
241
|
/** Zone reader owned by an organization outside the OIDC rollout. */
|
|
241
|
-
const otherOrganizationReader =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
242
|
+
const otherOrganizationReader = TestApp.zoneReader(
|
|
243
|
+
{
|
|
244
|
+
id: 'key_other_organization',
|
|
245
|
+
orgId: 'org_other',
|
|
246
|
+
scopes: ['data:read'],
|
|
247
|
+
token: 'secret_other_organization',
|
|
248
|
+
},
|
|
249
|
+
[zone],
|
|
250
|
+
)
|
|
247
251
|
|
|
248
252
|
/** Zone writer: broadcasts signed transactions to `zone` without reading its data. */
|
|
249
253
|
const zoneWriter = {
|
|
@@ -253,14 +257,40 @@ describe('zone chain gate', () => {
|
|
|
253
257
|
token: 'secret_zone_writer',
|
|
254
258
|
} satisfies TestApp.kvStore.Key
|
|
255
259
|
|
|
256
|
-
/**
|
|
260
|
+
/** Zone writer through the generic scope, tagged for `zone`. */
|
|
261
|
+
const taggedZoneWriter = {
|
|
262
|
+
id: 'key_tagged_zone_writer',
|
|
263
|
+
orgId: 'org_test',
|
|
264
|
+
scopes: ['data:read', 'zone:write'],
|
|
265
|
+
token: 'secret_tagged_zone_writer',
|
|
266
|
+
zoneTags: [zone],
|
|
267
|
+
} satisfies TestApp.kvStore.Key
|
|
268
|
+
|
|
269
|
+
/** Full-access key: the wildcard reads Zones only through an explicit `zone:read` plus tags. */
|
|
257
270
|
const admin = {
|
|
258
271
|
id: 'key_admin',
|
|
259
272
|
orgId: 'org_test',
|
|
260
|
-
scopes: ['*'],
|
|
273
|
+
scopes: ['*', 'zone:read'],
|
|
261
274
|
token: 'secret_admin',
|
|
275
|
+
zoneTags: [zone, zoneB],
|
|
262
276
|
} satisfies TestApp.kvStore.Key
|
|
263
277
|
|
|
278
|
+
/** Wildcard key with tags but no `zone:read`: the wildcard grants no Zone. */
|
|
279
|
+
const adminUntagged = {
|
|
280
|
+
id: 'key_admin_untagged',
|
|
281
|
+
orgId: 'org_test',
|
|
282
|
+
scopes: ['*'],
|
|
283
|
+
token: 'secret_admin_untagged',
|
|
284
|
+
zoneTags: [zone],
|
|
285
|
+
} satisfies TestApp.kvStore.Key
|
|
286
|
+
|
|
287
|
+
/** Organizations of the readers hold whole-Zone delegations. */
|
|
288
|
+
const db = TestApp.database()
|
|
289
|
+
beforeAll(async () => {
|
|
290
|
+
await TestApp.delegateZone(db, { chainIds: [zone, zoneB, moderato] })
|
|
291
|
+
await TestApp.delegateZone(db, { chainIds: [zone], orgId: 'org_other' })
|
|
292
|
+
})
|
|
293
|
+
|
|
264
294
|
/** Data reader without any zone grant. */
|
|
265
295
|
const outsider = {
|
|
266
296
|
id: 'key_outsider',
|
|
@@ -272,7 +302,8 @@ describe('zone chain gate', () => {
|
|
|
272
302
|
/** A deployment serving two zones. */
|
|
273
303
|
function zoneApp() {
|
|
274
304
|
return TestApp.create({
|
|
275
|
-
auth: { keys: [admin, outsider, zoneReader, zoneWriter] },
|
|
305
|
+
auth: { keys: [admin, adminUntagged, outsider, taggedZoneWriter, zoneReader, zoneWriter] },
|
|
306
|
+
db,
|
|
276
307
|
zones: [zoneOptions(zone), zoneOptions(zoneB)],
|
|
277
308
|
})
|
|
278
309
|
}
|
|
@@ -366,6 +397,7 @@ describe('zone chain gate', () => {
|
|
|
366
397
|
.sign(privateKey)
|
|
367
398
|
const app = TestApp.create({
|
|
368
399
|
auth: { keys: [admin, otherOrganizationReader, zoneReader] },
|
|
400
|
+
db,
|
|
369
401
|
logger: (entry) => void entries.push(entry),
|
|
370
402
|
vercelOidc,
|
|
371
403
|
zones: [
|
|
@@ -443,7 +475,7 @@ describe('zone chain gate', () => {
|
|
|
443
475
|
expect(entries[4]).not.toHaveProperty('vercelOidc')
|
|
444
476
|
})
|
|
445
477
|
|
|
446
|
-
test('the legacy Moderato id
|
|
478
|
+
test('the legacy Moderato id routes to current upstreams', async () => {
|
|
447
479
|
const fetch = vi
|
|
448
480
|
.spyOn(globalThis, 'fetch')
|
|
449
481
|
.mockResolvedValueOnce(Response.json({ id: 1, jsonrpc: '2.0', result: '0x54e89ac3' }))
|
|
@@ -451,6 +483,7 @@ describe('zone chain gate', () => {
|
|
|
451
483
|
try {
|
|
452
484
|
const app = TestApp.create({
|
|
453
485
|
auth: { keys: [legacyModeratoReader] },
|
|
486
|
+
db,
|
|
454
487
|
rpc: { url: (chainId) => `https://${chainId}.rpc.test` },
|
|
455
488
|
tidx: { baseUrl: (chainId) => `https://${chainId}.tidx.test` },
|
|
456
489
|
zones: true,
|
|
@@ -476,9 +509,11 @@ describe('zone chain gate', () => {
|
|
|
476
509
|
})
|
|
477
510
|
|
|
478
511
|
test('a Zone write scope cannot read Zone data', async () => {
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
512
|
+
for (const writer of [zoneWriter, taggedZoneWriter]) {
|
|
513
|
+
const response = await zoneApp().request(`/v1/tokenlist?chainId=${zone}`, as(writer))
|
|
514
|
+
expect(response.status).toBe(403)
|
|
515
|
+
expect(await response.json()).toMatchObject({ error: { code: 'api_key_forbidden' } })
|
|
516
|
+
}
|
|
482
517
|
})
|
|
483
518
|
|
|
484
519
|
test('zone authorization applies to every data route', async () => {
|
|
@@ -497,30 +532,32 @@ describe('zone chain gate', () => {
|
|
|
497
532
|
}
|
|
498
533
|
})
|
|
499
534
|
|
|
500
|
-
test('
|
|
535
|
+
test('a wildcard key reads only the delegated zones its explicit zone:read and tags name', async () => {
|
|
501
536
|
const app = zoneApp()
|
|
502
537
|
expect((await app.request(`/v1/tokenlist?chainId=${zone}`, as(admin))).status).toBe(200)
|
|
503
538
|
expect((await app.request(`/v1/tokenlist?chainId=${zoneB}`, as(admin))).status).toBe(200)
|
|
539
|
+
// The wildcard alone grants no Zone, tags or not.
|
|
540
|
+
expect((await app.request(`/v1/tokenlist?chainId=${zone}`, as(adminUntagged))).status).toBe(403) // prettier-ignore
|
|
504
541
|
})
|
|
505
542
|
|
|
506
|
-
test('a key without the zone
|
|
543
|
+
test('a key without the zone grant is refused, naming the grant', async () => {
|
|
507
544
|
const app = zoneApp()
|
|
508
545
|
const response = await app.request(`/v1/transfers?chainId=${zone}`, as(outsider))
|
|
509
546
|
const body = (await response.json()) as { error: { code: string; message: string } }
|
|
510
547
|
|
|
511
548
|
expect(response.status).toBe(403)
|
|
512
549
|
expect(body.error.code).toBe('api_key_forbidden')
|
|
513
|
-
expect(body.error.message).toContain(
|
|
550
|
+
expect(body.error.message).toContain(`\`zone:read\` and tagged for Zone ${zone}`)
|
|
514
551
|
expect(body.error.message).not.toContain('X-Authorization-Token')
|
|
515
552
|
})
|
|
516
553
|
|
|
517
|
-
test('a zone
|
|
554
|
+
test('a zone tag does not grant another zone', async () => {
|
|
518
555
|
const app = zoneApp()
|
|
519
556
|
const response = await app.request(`/v1/transfers?chainId=${zoneB}`, as(zoneReader))
|
|
520
557
|
const body = (await response.json()) as { error: { code: string; message: string } }
|
|
521
558
|
|
|
522
559
|
expect(response.status).toBe(403)
|
|
523
|
-
expect(body.error.message).toContain(`
|
|
560
|
+
expect(body.error.message).toContain(`tagged for Zone ${zoneB}`)
|
|
524
561
|
})
|
|
525
562
|
|
|
526
563
|
test('a caller-signed Zone token cannot authorize REST data', async () => {
|
|
@@ -638,12 +675,12 @@ describe('sandbox chain guard', () => {
|
|
|
638
675
|
})
|
|
639
676
|
|
|
640
677
|
test('rejects a sandbox key on a mainnet-backed Zone', async () => {
|
|
641
|
-
const key = {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
} satisfies TestApp.kvStore.Key
|
|
678
|
+
const key = TestApp.zoneReader({ ...sandbox, scopes: ['data:read'] }, [mainnetZone])
|
|
679
|
+
const db = TestApp.database()
|
|
680
|
+
await TestApp.delegateZone(db, { chainIds: [mainnetZone], environment: 'sandbox', orgId: key.orgId }) // prettier-ignore
|
|
645
681
|
const client = TestApp.client({
|
|
646
682
|
auth: { keys: [key] },
|
|
683
|
+
db,
|
|
647
684
|
zones: [
|
|
648
685
|
TestApp.zone({
|
|
649
686
|
chainId: mainnetZone,
|
package/src/apps/data/App.ts
CHANGED
|
@@ -190,6 +190,7 @@ export function data(options: data.Options = {}) {
|
|
|
190
190
|
message: '`include=zones` requires an API key with readable Zone scopes.',
|
|
191
191
|
status: 403,
|
|
192
192
|
})
|
|
193
|
+
await ZoneAccess.ensure(c)
|
|
193
194
|
const zoneChainIds = ZoneSelection.readableChainIds(c, {
|
|
194
195
|
parentChainId: selection.chainId,
|
|
195
196
|
principal,
|
|
@@ -197,23 +198,33 @@ export function data(options: data.Options = {}) {
|
|
|
197
198
|
tidx: tidx_config,
|
|
198
199
|
zones,
|
|
199
200
|
})
|
|
200
|
-
|
|
201
|
+
// Each candidate Zone is decided on its own against the request's
|
|
202
|
+
// addresses; the selection keeps the admitted ones and the recorded
|
|
203
|
+
// decision is an admitted one, before workload identity runs.
|
|
204
|
+
const zoneChainIds_readable: number[] = []
|
|
205
|
+
let unavailable: ZoneAccess.check.Denial | undefined
|
|
206
|
+
for (const zoneChainId of zoneChainIds) {
|
|
207
|
+
const access = await ZoneAccess.authorize(c, { ...pathAddresses(c), chainId: zoneChainId, verb: 'read' }) // prettier-ignore
|
|
208
|
+
if (access.allowed) zoneChainIds_readable.push(zoneChainId)
|
|
209
|
+
else if (access.error.status === 503) unavailable = access.error
|
|
210
|
+
}
|
|
211
|
+
// Answering with only the Zones that could be verified would silently drop the rest.
|
|
212
|
+
if (unavailable) return Response.error(c, unavailable)
|
|
213
|
+
if (zoneChainIds_readable.length === 0)
|
|
201
214
|
return Response.error(c, {
|
|
202
215
|
code: 'api_key_forbidden',
|
|
203
216
|
message: 'The API key has no readable configured Zones.',
|
|
204
217
|
status: 403,
|
|
205
218
|
})
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
for (const zoneChainId of zoneChainIds)
|
|
209
|
-
ZoneAccess.authorize(c, { ...pathAddresses(c), chainId: zoneChainId, verb: 'read' })
|
|
219
|
+
const last = zoneChainIds_readable.at(-1)
|
|
220
|
+
c.set('zoneAccess', c.get('zoneAccessDecisions')?.find((decision) => decision.chainId === last)) // prettier-ignore
|
|
210
221
|
const policy = c.get('vercelOidc')
|
|
211
222
|
if (policy?.applies(principal)) {
|
|
212
223
|
const results = await Auth.check(c, {
|
|
213
224
|
allows: (results) => results.every((result) => !VercelOidc.authorizationError(result)),
|
|
214
225
|
fn: () =>
|
|
215
226
|
Promise.all(
|
|
216
|
-
|
|
227
|
+
zoneChainIds_readable.flatMap((chainId) => {
|
|
217
228
|
const zone = zones.get(chainId)
|
|
218
229
|
if (zone?.sourceId === undefined || !Viem.isMainnet(zone.sourceId)) return []
|
|
219
230
|
return [policy.verify(c.req.raw, zone)]
|
|
@@ -230,8 +241,8 @@ export function data(options: data.Options = {}) {
|
|
|
230
241
|
return Response.error(c, error)
|
|
231
242
|
}
|
|
232
243
|
}
|
|
233
|
-
c.set('supportedChainIds', new Set([selection.chainId, ...
|
|
234
|
-
c.set('zoneChainIds',
|
|
244
|
+
c.set('supportedChainIds', new Set([selection.chainId, ...zoneChainIds_readable]))
|
|
245
|
+
c.set('zoneChainIds', zoneChainIds_readable)
|
|
235
246
|
return next()
|
|
236
247
|
}
|
|
237
248
|
c.set('chainId', selection.chainId)
|
|
@@ -260,7 +271,7 @@ export function data(options: data.Options = {}) {
|
|
|
260
271
|
// Record the attempt first so a workload-identity refusal keeps its Zone
|
|
261
272
|
// attribution; the raw RPC handler re-records per method afterwards.
|
|
262
273
|
const zoneToken = Boolean(c.req.header(ZoneRpcAuthentication.headerName)?.trim())
|
|
263
|
-
const access = ZoneAccess.authorize(c, {
|
|
274
|
+
const access = await ZoneAccess.authorize(c, {
|
|
264
275
|
...pathAddresses(c),
|
|
265
276
|
chainId,
|
|
266
277
|
verb: 'read',
|
|
@@ -281,15 +292,20 @@ export function data(options: data.Options = {}) {
|
|
|
281
292
|
return Response.error(c, error)
|
|
282
293
|
}
|
|
283
294
|
}
|
|
284
|
-
// Raw RPC decides and records per method
|
|
285
|
-
// refuses callers holding no Zone grant at all.
|
|
295
|
+
// Raw RPC decides and records per method with the batch's accounts in its
|
|
296
|
+
// handler; this gate only refuses callers holding no Zone grant at all.
|
|
286
297
|
if (selection.rpc) {
|
|
298
|
+
const write = ZoneAccess.check(c, { chainId, verb: 'write', zoneToken })
|
|
299
|
+
// An unreadable delegation passes too: the handler answers broadcasts 503 and reads the key cannot perform 403.
|
|
287
300
|
const granted =
|
|
288
|
-
access.allowed ||
|
|
301
|
+
access.allowed ||
|
|
302
|
+
ZoneAccess.eligible(c, { chainId }) ||
|
|
303
|
+
write.allowed ||
|
|
304
|
+
write.error.status === 503
|
|
289
305
|
if (!granted) {
|
|
290
306
|
return Response.error(c, {
|
|
291
307
|
code: 'api_key_forbidden',
|
|
292
|
-
message: `Chain ID ${chainId} is a Zone. Use an API key granting \`zone
|
|
308
|
+
message: `Chain ID ${chainId} is a Zone. Use an API key granting \`zone:read\` and tagged for Zone ${chainId}, issued to an organization delegated that Zone (or \`zone:write\` with a tag for Zone ${chainId} for broadcasts), or pass a Zone token via \`X-Authorization-Token\`.`,
|
|
293
309
|
status: 403,
|
|
294
310
|
})
|
|
295
311
|
}
|
|
@@ -53,29 +53,23 @@ describe('transaction activity Zone query', () => {
|
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
describe('readableChainIds', () => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
scopes: [
|
|
59
|
-
'data:read',
|
|
60
|
-
`zone:${Zones.zoneMainnetInternal.id}:read`,
|
|
61
|
-
`zone:${Zones.zoneModeratoInternal.id}:read`,
|
|
62
|
-
],
|
|
63
|
-
})
|
|
56
|
+
const both = [Zones.zoneMainnetInternal.id, Zones.zoneModeratoInternal.id]
|
|
57
|
+
const hosted = new Map(Zones.chains.map((zone) => [zone.id, zone]))
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
).toStrictEqual([
|
|
59
|
+
test('intersects the parent chain, tags, delegations, and configured routable Zones', () => {
|
|
60
|
+
const principal = apiKeyPrincipal({ scopes: ['data:read', 'zone:read'], zoneTags: both })
|
|
61
|
+
|
|
62
|
+
expect(readable({ parentChainId: Viem.chainId.testnet, principal, zones: hosted }, both)).toStrictEqual([Zones.zoneModeratoInternal.id]) // prettier-ignore
|
|
63
|
+
expect(readable({ parentChainId: Viem.chainId.mainnet, principal, zones: hosted }, both)).toStrictEqual([Zones.zoneMainnetInternal.id]) // prettier-ignore
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('requires both a tag and a delegation for each Zone', () => {
|
|
67
|
+
const tagged = apiKeyPrincipal({ scopes: ['data:read', 'zone:read'], zoneTags: [Zones.zoneModeratoInternal.id] }) // prettier-ignore
|
|
68
|
+
const untagged = apiKeyPrincipal({ scopes: ['data:read', 'zone:read'] })
|
|
69
|
+
|
|
70
|
+
expect(readable({ parentChainId: Viem.chainId.testnet, principal: tagged, zones: hosted }, both)).toStrictEqual([Zones.zoneModeratoInternal.id]) // prettier-ignore
|
|
71
|
+
expect(readable({ parentChainId: Viem.chainId.testnet, principal: tagged, zones: hosted }, [Zones.zoneMainnetInternal.id])).toStrictEqual([]) // prettier-ignore
|
|
72
|
+
expect(readable({ parentChainId: Viem.chainId.testnet, principal: untagged, zones: hosted }, both)).toStrictEqual([]) // prettier-ignore
|
|
79
73
|
})
|
|
80
74
|
|
|
81
75
|
test('never treats broadcast-only Zone write scopes as readable', () => {
|
|
@@ -88,49 +82,26 @@ describe('readableChainIds', () => {
|
|
|
88
82
|
})
|
|
89
83
|
|
|
90
84
|
for (const parentChainId of [Viem.chainId.mainnet, Viem.chainId.testnet])
|
|
91
|
-
expect(
|
|
92
|
-
readable({
|
|
93
|
-
parentChainId,
|
|
94
|
-
principal,
|
|
95
|
-
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
96
|
-
}),
|
|
97
|
-
).toStrictEqual([])
|
|
85
|
+
expect(readable({ parentChainId, principal, zones: hosted }, both)).toStrictEqual([])
|
|
98
86
|
})
|
|
99
87
|
|
|
100
|
-
test('lets wildcard keys read
|
|
88
|
+
test('lets wildcard keys read delegated Zones only through an explicit zone:read and tags', () => {
|
|
101
89
|
expect(
|
|
102
|
-
readable(
|
|
103
|
-
parentChainId: Viem.chainId.testnet,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}),
|
|
90
|
+
readable(
|
|
91
|
+
{ parentChainId: Viem.chainId.testnet, principal: apiKeyPrincipal({ scopes: ['*', 'zone:read'], zoneTags: both }), zones: hosted }, // prettier-ignore
|
|
92
|
+
both,
|
|
93
|
+
),
|
|
107
94
|
).toStrictEqual([Zones.zoneModeratoInternal.id])
|
|
95
|
+
expect(
|
|
96
|
+
readable({ parentChainId: Viem.chainId.testnet, principal: apiKeyPrincipal({ scopes: ['*'], zoneTags: both }), zones: hosted }, both), // prettier-ignore
|
|
97
|
+
).toStrictEqual([])
|
|
108
98
|
})
|
|
109
99
|
|
|
110
100
|
test('filters sandbox keys by each Zone parent chain', () => {
|
|
111
|
-
const principal = apiKeyPrincipal({
|
|
112
|
-
environment: 'sandbox',
|
|
113
|
-
scopes: [
|
|
114
|
-
'data:read',
|
|
115
|
-
`zone:${Zones.zoneMainnetInternal.id}:read`,
|
|
116
|
-
`zone:${Zones.zoneModeratoInternal.id}:read`,
|
|
117
|
-
],
|
|
118
|
-
})
|
|
101
|
+
const principal = apiKeyPrincipal({ environment: 'sandbox', scopes: ['data:read', 'zone:read'], zoneTags: both }) // prettier-ignore
|
|
119
102
|
|
|
120
|
-
expect(
|
|
121
|
-
|
|
122
|
-
parentChainId: Viem.chainId.testnet,
|
|
123
|
-
principal,
|
|
124
|
-
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
125
|
-
}),
|
|
126
|
-
).toStrictEqual([Zones.zoneModeratoInternal.id])
|
|
127
|
-
expect(
|
|
128
|
-
readable({
|
|
129
|
-
parentChainId: Viem.chainId.mainnet,
|
|
130
|
-
principal,
|
|
131
|
-
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
132
|
-
}),
|
|
133
|
-
).toStrictEqual([])
|
|
103
|
+
expect(readable({ parentChainId: Viem.chainId.testnet, principal, zones: hosted }, both)).toStrictEqual([Zones.zoneModeratoInternal.id]) // prettier-ignore
|
|
104
|
+
expect(readable({ parentChainId: Viem.chainId.mainnet, principal, zones: hosted }, both)).toStrictEqual([]) // prettier-ignore
|
|
134
105
|
})
|
|
135
106
|
|
|
136
107
|
test('requires data read access and both upstreams', () => {
|
|
@@ -142,18 +113,16 @@ describe('readableChainIds', () => {
|
|
|
142
113
|
const zones = new Map([[zone.id, zone]])
|
|
143
114
|
|
|
144
115
|
expect(
|
|
145
|
-
readable(
|
|
146
|
-
parentChainId: zone.sourceId,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}),
|
|
116
|
+
readable(
|
|
117
|
+
{ parentChainId: zone.sourceId, principal: apiKeyPrincipal({ scopes: ['zone:read'], zoneTags: [zone.id] }), zones }, // prettier-ignore
|
|
118
|
+
[zone.id],
|
|
119
|
+
),
|
|
150
120
|
).toStrictEqual([])
|
|
151
121
|
expect(
|
|
152
|
-
readable(
|
|
153
|
-
parentChainId: zone.sourceId,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}),
|
|
122
|
+
readable(
|
|
123
|
+
{ parentChainId: zone.sourceId, principal: apiKeyPrincipal({ scopes: ['data:read', 'zone:read'], zoneTags: [zone.id] }), zones }, // prettier-ignore
|
|
124
|
+
[zone.id],
|
|
125
|
+
),
|
|
157
126
|
).toStrictEqual([])
|
|
158
127
|
})
|
|
159
128
|
})
|
|
@@ -191,12 +160,24 @@ describe('uniqueMatch', () => {
|
|
|
191
160
|
})
|
|
192
161
|
})
|
|
193
162
|
|
|
194
|
-
/** Runs `readableChainIds` on a context carrying the principal. */
|
|
195
|
-
function readable(options: ZoneSelection.readableChainIds.Options) {
|
|
163
|
+
/** Runs `readableChainIds` on a context carrying the principal and its organization's whole-Zone delegations. */
|
|
164
|
+
function readable(options: ZoneSelection.readableChainIds.Options, delegated: readonly number[]) {
|
|
196
165
|
const c = new Context(new Request('http://tempo-api.test/'))
|
|
197
166
|
c.set('principal' as never, options.principal as never)
|
|
167
|
+
const records = delegated.map((chainId) => ({
|
|
168
|
+
accountsAll: true,
|
|
169
|
+
chainId,
|
|
170
|
+
createdAt: '2026-01-01T00:00:00.000Z',
|
|
171
|
+
environment: options.principal.environment,
|
|
172
|
+
id: `zd_${chainId}`,
|
|
173
|
+
orgId: options.principal.orgId,
|
|
174
|
+
projects: 'all',
|
|
175
|
+
tokensAll: true,
|
|
176
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
177
|
+
}))
|
|
178
|
+
c.set('zoneDelegations' as never, { records } as never)
|
|
198
179
|
const chainIds = ZoneSelection.readableChainIds(c as never, options)
|
|
199
|
-
// Filtering decides
|
|
180
|
+
// Filtering decides eligibility only; the data gate decides and records the selected Zones.
|
|
200
181
|
expect(c.get('zoneAccess' as never)).toBeUndefined()
|
|
201
182
|
return chainIds
|
|
202
183
|
}
|
|
@@ -216,6 +197,7 @@ function apiKeyPrincipal(
|
|
|
216
197
|
id: apiKey.id,
|
|
217
198
|
orgId: apiKey.orgId,
|
|
218
199
|
type: 'api_key',
|
|
200
|
+
...(options.zoneTags === undefined ? {} : { zoneTags: options.zoneTags }),
|
|
219
201
|
}
|
|
220
202
|
}
|
|
221
203
|
|
|
@@ -223,5 +205,6 @@ declare namespace apiKeyPrincipal {
|
|
|
223
205
|
type Options = {
|
|
224
206
|
environment?: 'production' | 'sandbox' | undefined
|
|
225
207
|
scopes: readonly string[]
|
|
208
|
+
zoneTags?: readonly number[] | undefined
|
|
226
209
|
}
|
|
227
210
|
}
|
|
@@ -7,7 +7,7 @@ import * as Viem from '../../internal/Viem.js'
|
|
|
7
7
|
import * as ZoneAccess from '../../internal/ZoneAccess.js'
|
|
8
8
|
import * as Scope from '../../Scope.js'
|
|
9
9
|
|
|
10
|
-
/** Returns configured and routable Zones
|
|
10
|
+
/** Returns configured and routable Zones an API key is eligible to read, after `ZoneAccess.ensure` settled; the gate decides each with the request addresses. */
|
|
11
11
|
export function readableChainIds<environment extends ZoneAccess.Environment>(
|
|
12
12
|
c: Context<environment>,
|
|
13
13
|
options: readableChainIds.Options,
|
|
@@ -18,7 +18,7 @@ export function readableChainIds<environment extends ZoneAccess.Environment>(
|
|
|
18
18
|
|
|
19
19
|
const chainIds = [...zones.values()].flatMap((zone) => {
|
|
20
20
|
if (zone.sourceId !== parentChainId) return []
|
|
21
|
-
if (!ZoneAccess.
|
|
21
|
+
if (!ZoneAccess.eligible(c, { chainId: zone.id })) return []
|
|
22
22
|
if (
|
|
23
23
|
principal.environment === 'sandbox' &&
|
|
24
24
|
(zone.sourceId === undefined || Viem.isMainnet(zone.sourceId))
|