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
|
@@ -5,14 +5,19 @@ import * as ApiKeys from '../../../ApiKeys.js'
|
|
|
5
5
|
import * as Db from '../../../db/Db.js'
|
|
6
6
|
import * as RoutesAccessRequests from '../../../db/tables/routesAccessRequests.js'
|
|
7
7
|
import * as Auth from '../../../internal/Auth.js'
|
|
8
|
+
import * as ExecutionContext from '../../../internal/ExecutionContext.js'
|
|
8
9
|
import * as OpenApi from '../../../internal/OpenApi.js'
|
|
9
10
|
import * as Response from '../../../internal/Response.js'
|
|
11
|
+
import * as RoutesCatalog from '../../../internal/routes/Catalog.js'
|
|
10
12
|
import * as Schema from '../../../internal/Schema.js'
|
|
11
13
|
import type { Environment } from '../App.js'
|
|
12
14
|
|
|
13
15
|
/** Most keys or routes one request may name. */
|
|
14
16
|
const maxItems = 50
|
|
15
17
|
|
|
18
|
+
/** Quiet period after an organization's request during which later requests skip the reviewer notice. */
|
|
19
|
+
const noticeCooldownMs = 10 * 60_000
|
|
20
|
+
|
|
16
21
|
/** OpenAPI schemas owned by Routes access requests. */
|
|
17
22
|
export namespace schema {
|
|
18
23
|
const id = (description: string, example: string) =>
|
|
@@ -44,12 +49,10 @@ export namespace schema {
|
|
|
44
49
|
export const RoutesAccessRequest = OpenApi.component(
|
|
45
50
|
Schema.describe(
|
|
46
51
|
z.object({
|
|
47
|
-
createdAt:
|
|
48
|
-
.
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
52
|
-
),
|
|
52
|
+
createdAt: Schema.dateTime().check(
|
|
53
|
+
z.describe('When the request was created (ISO 8601).'),
|
|
54
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
55
|
+
),
|
|
53
56
|
environment,
|
|
54
57
|
expectedVolume: z
|
|
55
58
|
.nullable(z.string())
|
|
@@ -100,7 +103,7 @@ export namespace schema {
|
|
|
100
103
|
z.meta({ examples: ['Approved for Base USDC only.', null] }),
|
|
101
104
|
),
|
|
102
105
|
reviewedAt: z
|
|
103
|
-
.nullable(
|
|
106
|
+
.nullable(Schema.dateTime())
|
|
104
107
|
.check(
|
|
105
108
|
z.describe('When the request was reviewed (ISO 8601), or null while pending.'),
|
|
106
109
|
z.meta({ examples: ['2026-01-02T00:00:00.000Z', null] }),
|
|
@@ -129,12 +132,10 @@ export namespace schema {
|
|
|
129
132
|
z.describe('Whether 1:1 subsidized delivery was requested.'),
|
|
130
133
|
z.meta({ examples: [true] }),
|
|
131
134
|
),
|
|
132
|
-
updatedAt:
|
|
133
|
-
.
|
|
134
|
-
.
|
|
135
|
-
|
|
136
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
137
|
-
),
|
|
135
|
+
updatedAt: Schema.dateTime().check(
|
|
136
|
+
z.describe('When the request was last changed (ISO 8601).'),
|
|
137
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
138
|
+
),
|
|
138
139
|
}),
|
|
139
140
|
"A project's request for Routes transfer access.",
|
|
140
141
|
),
|
|
@@ -286,7 +287,7 @@ const path =
|
|
|
286
287
|
'/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}/projects/:projectId{prj_[A-Za-z0-9_-]+}/routes-access-requests'
|
|
287
288
|
|
|
288
289
|
/** Mounts project Routes access request operations. */
|
|
289
|
-
export function routesAccessRequests() {
|
|
290
|
+
export function routesAccessRequests(options: routesAccessRequests.Options = {}) {
|
|
290
291
|
return new Hono<Environment>()
|
|
291
292
|
.post(
|
|
292
293
|
path,
|
|
@@ -341,7 +342,8 @@ export function routesAccessRequests() {
|
|
|
341
342
|
message: `Choose live ${body.environment} keys from this project (${unknown.join(', ')})`,
|
|
342
343
|
status: 400,
|
|
343
344
|
})
|
|
344
|
-
const
|
|
345
|
+
const db = Db.get(c.get('db'))
|
|
346
|
+
const record = await RoutesAccessRequests.create(db, {
|
|
345
347
|
environment: body.environment,
|
|
346
348
|
...(body.expectedVolume ? { expectedVolume: body.expectedVolume } : {}),
|
|
347
349
|
keyIds: [...new Set(body.keyIds)],
|
|
@@ -358,6 +360,7 @@ export function routesAccessRequests() {
|
|
|
358
360
|
message: 'This project already has a pending Routes access request',
|
|
359
361
|
status: 409,
|
|
360
362
|
})
|
|
363
|
+
dispatchNotice(c, { db, notify: options.notify, record })
|
|
361
364
|
return c.json(
|
|
362
365
|
Response.validated(schema.RoutesAccessRequest, RoutesAccessRequests.toRequest(record)),
|
|
363
366
|
200,
|
|
@@ -458,6 +461,87 @@ export function routesAccessRequests() {
|
|
|
458
461
|
)
|
|
459
462
|
}
|
|
460
463
|
|
|
464
|
+
export declare namespace routesAccessRequests {
|
|
465
|
+
/** Options for the Routes access request operations. */
|
|
466
|
+
type Options = {
|
|
467
|
+
/** Called in the background for each new request, so reviewers hear about it; failures never affect the response. */
|
|
468
|
+
notify?: ((notice: Notice) => Promise<void>) | undefined
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/** A new Routes access request, summarized for reviewers. */
|
|
472
|
+
type Notice = {
|
|
473
|
+
/** Environment the requested keys belong to. */
|
|
474
|
+
environment: RoutesAccessRequests.Record['environment']
|
|
475
|
+
/** Requester's expected monthly volume, as typed. */
|
|
476
|
+
expectedVolume?: string | undefined
|
|
477
|
+
/** Number of keys the request names. */
|
|
478
|
+
keyCount: number
|
|
479
|
+
/** Requester's note to reviewers. */
|
|
480
|
+
note?: string | undefined
|
|
481
|
+
/** Organization name. */
|
|
482
|
+
organization: string
|
|
483
|
+
/** Project name. */
|
|
484
|
+
project: string
|
|
485
|
+
/** Requester's verified email, when the session has one. */
|
|
486
|
+
requester?: string | undefined
|
|
487
|
+
/** Requested routes as `USDC on Base → OUSD on Tempo`; empty leaves the choice to Tempo. */
|
|
488
|
+
routes: readonly string[]
|
|
489
|
+
/** Whether the requester asked for 1:1 subsidized delivery. */
|
|
490
|
+
subsidy: boolean
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/** Hands a new request to the notifier after the response, labelling routes from the catalog. */
|
|
495
|
+
function dispatchNotice(c: Context<Environment>, options: dispatchNotice.Options) {
|
|
496
|
+
const { db, notify, record } = options
|
|
497
|
+
if (!notify) return
|
|
498
|
+
const principal = Auth.getPrincipal(c)
|
|
499
|
+
const organization = Auth.org(c).name
|
|
500
|
+
const project = Auth.project(c).name
|
|
501
|
+
const task = (async () => {
|
|
502
|
+
// A cancel-and-recreate loop would otherwise ping the reviewer every time; the queue still lists every request.
|
|
503
|
+
const since = new Date(Date.parse(record.createdAt) - noticeCooldownMs).toISOString()
|
|
504
|
+
const recent = await RoutesAccessRequests.hasRecent(db, {
|
|
505
|
+
excludeId: record.id,
|
|
506
|
+
orgId: record.orgId,
|
|
507
|
+
since,
|
|
508
|
+
}).catch(() => false)
|
|
509
|
+
if (recent) return
|
|
510
|
+
// Labels are best effort: a failed catalog read falls back to raw ids instead of dropping the notice.
|
|
511
|
+
const catalog = await RoutesCatalog.read(db).catch(() => undefined)
|
|
512
|
+
const label = (chainId: string, tokenId: string) =>
|
|
513
|
+
`${catalog?.tokensById.get(tokenId)?.symbol ?? tokenId} on ${(catalog && RoutesCatalog.getChain(catalog, chainId)?.name) ?? chainId}`
|
|
514
|
+
await notify({
|
|
515
|
+
environment: record.environment,
|
|
516
|
+
...(record.expectedVolume ? { expectedVolume: record.expectedVolume } : {}),
|
|
517
|
+
keyCount: record.keyIds.length,
|
|
518
|
+
...(record.note ? { note: record.note } : {}),
|
|
519
|
+
organization,
|
|
520
|
+
project,
|
|
521
|
+
...(principal?.type === 'session' && principal.email ? { requester: principal.email } : {}),
|
|
522
|
+
routes: record.routes.map(
|
|
523
|
+
(route) =>
|
|
524
|
+
`${label(route.sourceChainId, route.sourceTokenId)} → ${label(route.destinationChainId, route.destinationTokenId)}`,
|
|
525
|
+
),
|
|
526
|
+
subsidy: record.subsidy,
|
|
527
|
+
})
|
|
528
|
+
})().catch((error) => console.error('routes access request notice failed', error))
|
|
529
|
+
const waitUntil = ExecutionContext.waitUntil(c)
|
|
530
|
+
// Without an execution context (Node, tests) the floating promise settles on its own.
|
|
531
|
+
if (waitUntil) waitUntil(task)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
declare namespace dispatchNotice {
|
|
535
|
+
type Options = {
|
|
536
|
+
/** Database the request was written to; labels routes from its catalog. */
|
|
537
|
+
db: Db.Db
|
|
538
|
+
/** Reviewer notifier, when configured. */
|
|
539
|
+
notify: routesAccessRequests.Options['notify']
|
|
540
|
+
/** The request just created. */
|
|
541
|
+
record: RoutesAccessRequests.Record
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
461
545
|
function keysNotEnabled(c: Context<Environment>) {
|
|
462
546
|
return Response.error(c, {
|
|
463
547
|
code: 'api_keys_not_enabled',
|
|
@@ -85,7 +85,7 @@ describe('scopes', () => {
|
|
|
85
85
|
`"private, max-age=300, stale-while-revalidate=3600"`,
|
|
86
86
|
)
|
|
87
87
|
expect(body.data).toEqual(
|
|
88
|
-
[...Scope.catalog, Scope.
|
|
88
|
+
[...Scope.catalog, Scope.zoneWriteEntry].map((entry) => ({ ...entry })),
|
|
89
89
|
)
|
|
90
90
|
expect(body.data.map((entry) => entry.scope)).toMatchInlineSnapshot(`
|
|
91
91
|
[
|
|
@@ -103,7 +103,7 @@ describe('scopes', () => {
|
|
|
103
103
|
"webhooks:read",
|
|
104
104
|
"webhooks:write",
|
|
105
105
|
"zone:read",
|
|
106
|
-
"zone
|
|
106
|
+
"zone:write",
|
|
107
107
|
"zone:<chainId>:write",
|
|
108
108
|
]
|
|
109
109
|
`)
|
|
@@ -120,6 +120,6 @@ describe('scopes', () => {
|
|
|
120
120
|
const body = await TestApp.json(response, Scopes.schema.getScopes.Response)
|
|
121
121
|
|
|
122
122
|
expect(response.status).toBe(200)
|
|
123
|
-
expect(body.data).toEqual([...Scope.catalog, Scope.
|
|
123
|
+
expect(body.data).toEqual([...Scope.catalog, Scope.zoneWriteEntry, custom])
|
|
124
124
|
})
|
|
125
125
|
})
|
|
@@ -64,7 +64,7 @@ export namespace schema {
|
|
|
64
64
|
.optional(z.enum(['production', 'sandbox']))
|
|
65
65
|
.check(z.describe('Only include requests made with this API-key environment.'), z.meta({ examples: ['sandbox'] })), // prettier-ignore
|
|
66
66
|
from: z
|
|
67
|
-
.optional(
|
|
67
|
+
.optional(Schema.dateTime({ offset: true }))
|
|
68
68
|
.check(
|
|
69
69
|
z.describe('Only include requests at or after this ISO 8601 timestamp.'),
|
|
70
70
|
z.meta({ examples: ['2026-01-01T00:00:00Z'] }),
|
|
@@ -80,7 +80,7 @@ export namespace schema {
|
|
|
80
80
|
z.meta({ examples: ['prj_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
|
|
81
81
|
),
|
|
82
82
|
to: z
|
|
83
|
-
.optional(
|
|
83
|
+
.optional(Schema.dateTime({ offset: true }))
|
|
84
84
|
.check(
|
|
85
85
|
z.describe('Only include requests at or before this ISO 8601 timestamp.'),
|
|
86
86
|
z.meta({ examples: ['2026-01-31T23:59:59Z'] }),
|
|
@@ -125,12 +125,10 @@ export namespace schema {
|
|
|
125
125
|
requests: z
|
|
126
126
|
.number()
|
|
127
127
|
.check(z.int(), z.describe('Total requests.'), z.meta({ examples: [40] })),
|
|
128
|
-
time:
|
|
129
|
-
.
|
|
130
|
-
.
|
|
131
|
-
|
|
132
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
133
|
-
),
|
|
128
|
+
time: Schema.dateTime().check(
|
|
129
|
+
z.describe('Bucket start timestamp (ISO 8601).'),
|
|
130
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
131
|
+
),
|
|
134
132
|
})
|
|
135
133
|
.check(z.describe('One usage series point.')),
|
|
136
134
|
'RequestUsageSeriesPoint',
|
|
@@ -179,12 +177,10 @@ export namespace schema {
|
|
|
179
177
|
byKey: z.array(KeyBreakdown).check(z.describe('Usage grouped by API key.'), z.meta({ examples: [[]] })), // prettier-ignore
|
|
180
178
|
byRoute: z.array(RouteBreakdown).check(z.describe('Usage grouped by route.'), z.meta({ examples: [[]] })), // prettier-ignore
|
|
181
179
|
byStatus: z.array(StatusBreakdown).check(z.describe('Usage grouped by status code.'), z.meta({ examples: [[]] })), // prettier-ignore
|
|
182
|
-
from:
|
|
183
|
-
.
|
|
184
|
-
.
|
|
185
|
-
|
|
186
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
187
|
-
),
|
|
180
|
+
from: Schema.dateTime().check(
|
|
181
|
+
z.describe('Inclusive lower timestamp bound used for the read (ISO 8601).'),
|
|
182
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
183
|
+
),
|
|
188
184
|
interval: z
|
|
189
185
|
.enum(['day', 'hour'])
|
|
190
186
|
.check(
|
|
@@ -192,12 +188,10 @@ export namespace schema {
|
|
|
192
188
|
z.meta({ examples: ['day'] }),
|
|
193
189
|
),
|
|
194
190
|
series: z.array(SeriesPoint).check(z.describe('Usage grouped into time buckets.'), z.meta({ examples: [[]] })), // prettier-ignore
|
|
195
|
-
to:
|
|
196
|
-
.
|
|
197
|
-
.
|
|
198
|
-
|
|
199
|
-
z.meta({ examples: ['2026-01-31T23:59:59.000Z'] }),
|
|
200
|
-
),
|
|
191
|
+
to: Schema.dateTime().check(
|
|
192
|
+
z.describe('Inclusive upper timestamp bound used for the read (ISO 8601).'),
|
|
193
|
+
z.meta({ examples: ['2026-01-31T23:59:59.000Z'] }),
|
|
194
|
+
),
|
|
201
195
|
totals: Totals,
|
|
202
196
|
}),
|
|
203
197
|
'Request usage.',
|
|
@@ -238,12 +232,10 @@ export namespace schema {
|
|
|
238
232
|
z.describe('Committed fees for the bucket.'),
|
|
239
233
|
z.meta({ examples: [{ amount: '12.34', currency: 'usd' }] }),
|
|
240
234
|
),
|
|
241
|
-
timestamp:
|
|
242
|
-
.
|
|
243
|
-
.
|
|
244
|
-
|
|
245
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
246
|
-
),
|
|
235
|
+
timestamp: Schema.dateTime().check(
|
|
236
|
+
z.describe('Bucket start (ISO 8601), aligned to UTC calendar boundaries.'),
|
|
237
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
238
|
+
),
|
|
247
239
|
}),
|
|
248
240
|
'One time bucket of sponsorship usage.',
|
|
249
241
|
),
|
|
@@ -272,7 +264,7 @@ export namespace schema {
|
|
|
272
264
|
z.meta({ examples: ['production'] }),
|
|
273
265
|
),
|
|
274
266
|
from: z
|
|
275
|
-
.optional(
|
|
267
|
+
.optional(Schema.dateTime({ offset: true }))
|
|
276
268
|
.check(
|
|
277
269
|
z.describe('Window start (ISO 8601), inclusive. Defaults to 30 days before `to`.'),
|
|
278
270
|
z.meta({ examples: ['2026-01-01T00:00:00Z'] }),
|
|
@@ -290,7 +282,7 @@ export namespace schema {
|
|
|
290
282
|
z.meta({ examples: ['prj_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
|
|
291
283
|
),
|
|
292
284
|
to: z
|
|
293
|
-
.optional(
|
|
285
|
+
.optional(Schema.dateTime({ offset: true }))
|
|
294
286
|
.check(
|
|
295
287
|
z.describe('Window end (ISO 8601), exclusive. Defaults to now.'),
|
|
296
288
|
z.meta({ examples: ['2026-01-31T00:00:00Z'] }),
|
|
@@ -34,12 +34,10 @@ export namespace schema {
|
|
|
34
34
|
Schema.describe(
|
|
35
35
|
z.extend(tokenSchema.Input, {
|
|
36
36
|
chainId,
|
|
37
|
-
createdAt:
|
|
38
|
-
.
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
42
|
-
),
|
|
37
|
+
createdAt: Schema.dateTime().check(
|
|
38
|
+
z.describe('When the request was created (ISO 8601).'),
|
|
39
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
40
|
+
),
|
|
43
41
|
id: z
|
|
44
42
|
.string()
|
|
45
43
|
.check(
|
|
@@ -79,7 +77,7 @@ export namespace schema {
|
|
|
79
77
|
z.meta({ examples: ['Logo URL is unreachable.', null] }),
|
|
80
78
|
),
|
|
81
79
|
reviewedAt: z
|
|
82
|
-
.nullable(
|
|
80
|
+
.nullable(Schema.dateTime())
|
|
83
81
|
.check(
|
|
84
82
|
z.describe('When the request was reviewed (ISO 8601), or null while pending.'),
|
|
85
83
|
z.meta({ examples: ['2026-01-02T00:00:00.000Z', null] }),
|
|
@@ -87,12 +85,10 @@ export namespace schema {
|
|
|
87
85
|
status: z
|
|
88
86
|
.enum(['approved', 'denied', 'pending'])
|
|
89
87
|
.check(z.describe('Review status of the request.'), z.meta({ examples: ['pending'] })),
|
|
90
|
-
updatedAt:
|
|
91
|
-
.
|
|
92
|
-
.
|
|
93
|
-
|
|
94
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
95
|
-
),
|
|
88
|
+
updatedAt: Schema.dateTime().check(
|
|
89
|
+
z.describe('When the request was last changed (ISO 8601).'),
|
|
90
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
91
|
+
),
|
|
96
92
|
}),
|
|
97
93
|
"An organization's request to add a token to the curated verified list.",
|
|
98
94
|
),
|
|
@@ -41,11 +41,11 @@ test('publishes the list operation', async () => {
|
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
test('lists active delegations per environment for sessions and management keys', async () => {
|
|
44
|
-
const { app, cookie, db, kv, org, path
|
|
45
|
-
const base = { accountsAll: true, orgId: org.id,
|
|
44
|
+
const { app, cookie, db, kv, org, path } = await setup()
|
|
45
|
+
const base = { accountsAll: true, orgId: org.id, tokensAll: true } as const
|
|
46
46
|
const revoked = await ZoneDelegations.create(db, { ...base, chainId: 1_424_310_003, environment: 'production' }) // prettier-ignore
|
|
47
47
|
await ZoneDelegations.revoke(db, revoked.id)
|
|
48
|
-
await ZoneDelegations.create(db, { ...base, accountsAll: false, chainId: 421_700_002, environment: 'production'
|
|
48
|
+
await ZoneDelegations.create(db, { ...base, accountsAll: false, chainId: 421_700_002, environment: 'production' }) // prettier-ignore
|
|
49
49
|
await ZoneDelegations.create(db, { ...base, chainId: 421_700_001, environment: 'production' })
|
|
50
50
|
await ZoneDelegations.create(db, { ...base, chainId: 421_700_001, environment: 'sandbox' })
|
|
51
51
|
|
|
@@ -60,7 +60,6 @@ test('lists active delegations per environment for sessions and management keys'
|
|
|
60
60
|
createdAt: expect.any(String),
|
|
61
61
|
environment: 'production',
|
|
62
62
|
name: 'zone-mainnet-internal',
|
|
63
|
-
projects: 'all',
|
|
64
63
|
tokensAll: true,
|
|
65
64
|
},
|
|
66
65
|
{
|
|
@@ -69,7 +68,6 @@ test('lists active delegations per environment for sessions and management keys'
|
|
|
69
68
|
createdAt: expect.any(String),
|
|
70
69
|
environment: 'production',
|
|
71
70
|
name: 'zone-deel',
|
|
72
|
-
projects: [project.id],
|
|
73
71
|
tokensAll: true,
|
|
74
72
|
},
|
|
75
73
|
])
|
|
@@ -42,12 +42,10 @@ export namespace schema {
|
|
|
42
42
|
z.meta({ examples: [true] }),
|
|
43
43
|
),
|
|
44
44
|
chainId: z.int().check(z.describe('Zone chain id.'), z.meta({ examples: [421700001] })),
|
|
45
|
-
createdAt:
|
|
46
|
-
.
|
|
47
|
-
.
|
|
48
|
-
|
|
49
|
-
z.meta({ examples: ['2026-10-19T00:00:00.000Z'] }),
|
|
50
|
-
),
|
|
45
|
+
createdAt: Schema.dateTime().check(
|
|
46
|
+
z.describe('When the delegation was created (ISO 8601).'),
|
|
47
|
+
z.meta({ examples: ['2026-10-19T00:00:00.000Z'] }),
|
|
48
|
+
),
|
|
51
49
|
environment: ZoneDelegation.schema.Environment,
|
|
52
50
|
name: z
|
|
53
51
|
.optional(z.string())
|
|
@@ -55,7 +53,6 @@ export namespace schema {
|
|
|
55
53
|
z.describe('Zone name when the Zone is hosted by Tempo.'),
|
|
56
54
|
z.meta({ examples: ['zone-mainnet-internal'] }),
|
|
57
55
|
),
|
|
58
|
-
projects: ZoneDelegation.schema.Projects,
|
|
59
56
|
tokensAll: z
|
|
60
57
|
.boolean()
|
|
61
58
|
.check(
|
|
@@ -83,7 +80,6 @@ export namespace schema {
|
|
|
83
80
|
createdAt: '2026-10-19T00:00:00.000Z',
|
|
84
81
|
environment: 'production',
|
|
85
82
|
name: 'zone-mainnet-internal',
|
|
86
|
-
projects: 'all',
|
|
87
83
|
tokensAll: true,
|
|
88
84
|
},
|
|
89
85
|
],
|
|
@@ -170,7 +166,6 @@ export function zoneDelegations() {
|
|
|
170
166
|
createdAt: record.createdAt,
|
|
171
167
|
environment: record.environment,
|
|
172
168
|
...(name === undefined ? {} : { name }),
|
|
173
|
-
projects: record.projects,
|
|
174
169
|
tokensAll: record.tokensAll,
|
|
175
170
|
}
|
|
176
171
|
}),
|
package/src/apps/mpp/App.ts
CHANGED
|
@@ -45,7 +45,7 @@ export function mpp(options: mpp.Options) {
|
|
|
45
45
|
// Record the Zone decision here; the adapter re-checks without recording.
|
|
46
46
|
const response = await Timing.time(c, 'mpp_verify', async () => {
|
|
47
47
|
try {
|
|
48
|
-
Policy.assertChainAccess(c, {
|
|
48
|
+
await Policy.assertChainAccess(c, {
|
|
49
49
|
chainId,
|
|
50
50
|
supportedChainIds: c.get('supportedChainIds'),
|
|
51
51
|
zones: c.get('zones'),
|
|
@@ -168,7 +168,7 @@ async function authorizeBroadcast(
|
|
|
168
168
|
const chainId = Policy.chainId(input) ?? c.get('chainId')
|
|
169
169
|
const principal = Auth.getPrincipal(c) ?? undefined
|
|
170
170
|
try {
|
|
171
|
-
Policy.assertChainAccess(c, {
|
|
171
|
+
await Policy.assertChainAccess(c, {
|
|
172
172
|
chainId,
|
|
173
173
|
supportedChainIds: c.get('supportedChainIds'),
|
|
174
174
|
zones: c.get('zones'),
|
|
@@ -316,7 +316,7 @@ async function broadcast(c: Context<App.Environment>, options: broadcast.Options
|
|
|
316
316
|
async function reconcile(c: Context<App.Environment>, options: reconcile.Options) {
|
|
317
317
|
const { options: options_mpp, submission } = options
|
|
318
318
|
try {
|
|
319
|
-
Policy.assertChainAccess(c, {
|
|
319
|
+
await Policy.assertChainAccess(c, {
|
|
320
320
|
chainId: submission.chainId,
|
|
321
321
|
supportedChainIds: c.get('supportedChainIds'),
|
|
322
322
|
zones: c.get('zones'),
|
|
@@ -70,7 +70,7 @@ describe('MPP Zone authorization', () => {
|
|
|
70
70
|
expect(await response.json()).toEqual({
|
|
71
71
|
error: {
|
|
72
72
|
code: 'policy_denied',
|
|
73
|
-
message: `Broadcasting to zone ${zone.id} requires \`zone
|
|
73
|
+
message: `Broadcasting to zone ${zone.id} requires \`zone:write\` with a tag for Zone ${zone.id}, issued to an organization delegated that Zone.`,
|
|
74
74
|
},
|
|
75
75
|
success: false,
|
|
76
76
|
})
|
|
@@ -84,11 +84,14 @@ describe('MPP Zone authorization', () => {
|
|
|
84
84
|
)
|
|
85
85
|
|
|
86
86
|
test.each(['validate', 'broadcast'] as const)(
|
|
87
|
-
'%s confines
|
|
87
|
+
'%s confines tagged sandbox keys to testnet without requiring sponsorship',
|
|
88
88
|
async (operation) => {
|
|
89
89
|
const resolutions: number[] = []
|
|
90
|
+
const db = TestApp.database()
|
|
91
|
+
await TestApp.delegateZone(db, { chainIds: [zone.id], environment: 'sandbox', orgId: key.orgId }) // prettier-ignore
|
|
90
92
|
const app = TestApp.create({
|
|
91
|
-
auth: { keys: [{ ...key, environment: 'sandbox', scopes: ['
|
|
93
|
+
auth: { keys: [{ ...key, environment: 'sandbox', scopes: ['mpp:write', 'zone:write'], zoneTags: [zone.id] }] }, // prettier-ignore
|
|
94
|
+
db,
|
|
92
95
|
rpc: ({ chainId }) => {
|
|
93
96
|
resolutions.push(chainId)
|
|
94
97
|
return { url: runtime.zone.internalRpcUrl }
|
|
@@ -120,8 +123,11 @@ describe('MPP Zone authorization', () => {
|
|
|
120
123
|
|
|
121
124
|
test('requires active billing before mainnet Zone fee-payer access', async () => {
|
|
122
125
|
const resolutions: number[] = []
|
|
126
|
+
const db = TestApp.database()
|
|
127
|
+
await TestApp.delegateZone(db, { chainIds: [zone.id], orgId: key.orgId })
|
|
123
128
|
const app = TestApp.create({
|
|
124
|
-
auth: { keys: [{ ...key, scopes: ['mpp:write',
|
|
129
|
+
auth: { keys: [{ ...key, scopes: ['mpp:write', 'zone:write'], zoneTags: [zone.id] }] },
|
|
130
|
+
db,
|
|
125
131
|
mpp: { feePayer: Tempo.accounts[2], state: Store.memory() },
|
|
126
132
|
rpc: ({ chainId }) => {
|
|
127
133
|
resolutions.push(chainId)
|
|
@@ -143,28 +149,53 @@ describe('MPP Zone authorization', () => {
|
|
|
143
149
|
|
|
144
150
|
test('requires write scope to validate or broadcast Zone credentials', async () => {
|
|
145
151
|
const input = await credential()
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
})
|
|
150
|
-
for (const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
152
|
+
// A read scope never broadcasts, nor does a generic write scope without a tag for the Zone or
|
|
153
|
+
// without a delegation, nor the wildcard however it is tagged.
|
|
154
|
+
const db = TestApp.database()
|
|
155
|
+
await TestApp.delegateZone(db, { chainIds: [zone.id], orgId: key.orgId })
|
|
156
|
+
for (const reader of [
|
|
157
|
+
{ scopes: ['mpp:write', 'zone:read'], zoneTags: [zone.id] },
|
|
158
|
+
{ scopes: ['mpp:write', 'zone:write'] },
|
|
159
|
+
{ scopes: ['mpp:write', 'zone:write'], zoneTags: [zone.id + 1] },
|
|
160
|
+
{ orgId: 'org_undelegated', scopes: ['mpp:write', 'zone:write'], zoneTags: [zone.id] },
|
|
161
|
+
{ scopes: ['*'] },
|
|
162
|
+
{ scopes: ['*'], zoneTags: [zone.id] },
|
|
163
|
+
]) {
|
|
164
|
+
const app = TestApp.create({ auth: { keys: [{ ...key, ...reader }] }, db, zones: [zone] })
|
|
165
|
+
for (const operation of ['validate', 'broadcast'] as const)
|
|
166
|
+
expect(await (await post(app, operation, input)).json()).toEqual({
|
|
167
|
+
error: {
|
|
168
|
+
code: 'policy_denied',
|
|
169
|
+
message: `Broadcasting to zone ${zone.id} requires \`zone:write\` with a tag for Zone ${zone.id}, issued to an organization delegated that Zone.`,
|
|
170
|
+
},
|
|
171
|
+
success: false,
|
|
172
|
+
})
|
|
173
|
+
}
|
|
158
174
|
})
|
|
159
175
|
|
|
160
176
|
test.each([
|
|
161
177
|
{ environment: 'production', scopes: ['mpp:write', `zone:${zone.id}:write`], sourceId: 4217 },
|
|
162
|
-
|
|
178
|
+
// The wildcard grants no Zone on its own; it may sit beside the explicit write grant.
|
|
179
|
+
{ environment: 'production', scopes: ['*', `zone:${zone.id}:write`], sourceId: 4217 },
|
|
163
180
|
{ environment: 'sandbox', scopes: ['mpp:write', `zone:${zone.id}:write`], sourceId: 42431 },
|
|
181
|
+
{ environment: 'production', scopes: ['mpp:write', 'zone:write'], sourceId: 4217, zoneTags: [zone.id] }, // prettier-ignore
|
|
182
|
+
{ environment: 'sandbox', scopes: ['mpp:write', 'zone:write'], sourceId: 42431, zoneTags: [zone.id] }, // prettier-ignore
|
|
164
183
|
] as const)('allows authorized $environment Zone credentials with $scopes', async (options) => {
|
|
165
184
|
const input = await credential()
|
|
185
|
+
const db = TestApp.database()
|
|
186
|
+
await TestApp.delegateZone(db, { chainIds: [zone.id], environment: options.environment, orgId: key.orgId }) // prettier-ignore
|
|
166
187
|
const app = TestApp.create({
|
|
167
|
-
|
|
188
|
+
db,
|
|
189
|
+
auth: {
|
|
190
|
+
keys: [
|
|
191
|
+
{
|
|
192
|
+
...key,
|
|
193
|
+
environment: options.environment,
|
|
194
|
+
scopes: [...options.scopes],
|
|
195
|
+
...('zoneTags' in options ? { zoneTags: [...options.zoneTags] } : {}),
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
},
|
|
168
199
|
zones: [{ ...zone, sourceId: options.sourceId }],
|
|
169
200
|
})
|
|
170
201
|
for (const operation of ['validate', 'broadcast'] as const)
|
|
@@ -200,7 +200,7 @@ function isCanonical(serialized: Hex.Hex) {
|
|
|
200
200
|
if (!/^0x7[68]/.test(serialized)) return true
|
|
201
201
|
try {
|
|
202
202
|
const envelope = TxEnvelopeTempo.deserialize(serialized as TxEnvelopeTempo.Serialized)
|
|
203
|
-
// Fee-payer handoffs encode a sender address or, for
|
|
203
|
+
// Fee-payer handoffs encode a sender address or, for configurable account senders, the `0x00` marker; parsing recovers `from` either way.
|
|
204
204
|
const slot = (Rlp.toHex(Hex.slice(serialized, 1)) as readonly Hex.Hex[])[11]
|
|
205
205
|
const serialized_parsed = serialized.startsWith(TxEnvelopeTempo.feePayerMagic)
|
|
206
206
|
? TxEnvelopeTempo.serialize(envelope, {
|
|
@@ -4,6 +4,7 @@ import * as Mpp from '../Mpp.js'
|
|
|
4
4
|
import * as Confirmation from './Confirmation.js'
|
|
5
5
|
import * as MppError from './Error.js'
|
|
6
6
|
import * as Idempotency from './Idempotency.js'
|
|
7
|
+
import * as Policy from './Policy.js'
|
|
7
8
|
import * as ScreenManager from './ScreenManager.js'
|
|
8
9
|
|
|
9
10
|
describe('map', () => {
|
|
@@ -26,6 +27,8 @@ describe('map', () => {
|
|
|
26
27
|
Mpp.relayErrorCode.alreadyUsed,
|
|
27
28
|
],
|
|
28
29
|
[new Idempotency.LeaseLostError(), Mpp.relayErrorCode.temporarilyUnavailable],
|
|
30
|
+
[new Policy.AccessUnavailableError(), Mpp.relayErrorCode.temporarilyUnavailable],
|
|
31
|
+
[new Policy.PolicyDeniedError(), Mpp.relayErrorCode.policyDenied],
|
|
29
32
|
[new Confirmation.UnconfirmedError({ status: 502 }), Mpp.relayErrorCode.temporarilyUnavailable],
|
|
30
33
|
[new ScreenManager.RejectedError(), Mpp.relayErrorCode.screenRejected],
|
|
31
34
|
[new Error('Transaction simulation failed.'), Mpp.relayErrorCode.simulationFailed],
|
|
@@ -12,6 +12,7 @@ export function map(cause: unknown): Mpp.RelayError {
|
|
|
12
12
|
const message = cause instanceof Error ? cause.message : undefined
|
|
13
13
|
|
|
14
14
|
switch (true) {
|
|
15
|
+
case cause instanceof Policy.AccessUnavailableError:
|
|
15
16
|
case cause instanceof Idempotency.LeaseLostError:
|
|
16
17
|
// The transaction may still land; an idempotent retry reconciles it.
|
|
17
18
|
case cause instanceof Confirmation.UnconfirmedError:
|
|
@@ -87,32 +87,33 @@ describe('assertFeeMarketAdmission', () => {
|
|
|
87
87
|
})
|
|
88
88
|
|
|
89
89
|
describe('assertChainAccess', () => {
|
|
90
|
-
test('rejects chains outside the deployment allowlist', () => {
|
|
91
|
-
expect(
|
|
90
|
+
test('rejects chains outside the deployment allowlist', async () => {
|
|
91
|
+
await expect(
|
|
92
92
|
Policy.assertChainAccess(new Context(new Request('http://tempo-api.test/')), {
|
|
93
93
|
chainId: 1,
|
|
94
94
|
supportedChainIds: new Set([4217]),
|
|
95
95
|
zones,
|
|
96
96
|
}),
|
|
97
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
97
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
98
98
|
`[Mpp.Policy.UnsupportedChainError: Unsupported chain id 1.]`,
|
|
99
99
|
)
|
|
100
100
|
})
|
|
101
101
|
|
|
102
|
-
test('requires a Zone write scope; read
|
|
102
|
+
test('requires a Zone write scope; read grants never admit', async () => {
|
|
103
103
|
const chainId = Zones.zoneModeratoInternal.id
|
|
104
104
|
const c = new Context(new Request('http://tempo-api.test/'))
|
|
105
105
|
c.set(
|
|
106
106
|
'principal' as never,
|
|
107
107
|
{
|
|
108
108
|
...principal,
|
|
109
|
-
apiKey: { ...principal.apiKey, scopes: ['mpp:write',
|
|
109
|
+
apiKey: { ...principal.apiKey, scopes: ['mpp:write', 'zone:read'] },
|
|
110
|
+
zoneTags: [chainId],
|
|
110
111
|
} as never,
|
|
111
112
|
)
|
|
112
|
-
expect(
|
|
113
|
+
await expect(
|
|
113
114
|
Policy.assertChainAccess(c, { chainId, supportedChainIds: new Set([chainId]), zones }),
|
|
114
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
115
|
-
`[Mpp.Policy.PolicyDeniedError: Broadcasting to zone 1424310003 requires \`zone:1424310003
|
|
115
|
+
).rejects.toThrowErrorMatchingInlineSnapshot(
|
|
116
|
+
`[Mpp.Policy.PolicyDeniedError: Broadcasting to zone 1424310003 requires \`zone:write\` with a tag for Zone 1424310003, issued to an organization delegated that Zone.]`,
|
|
116
117
|
)
|
|
117
118
|
expect(c.get('zoneAccess' as never)).toMatchObject({ chainId, verb: 'write' })
|
|
118
119
|
})
|