tapimo 0.10.2 → 0.12.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/dist/App.d.ts +4896 -2166
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +2 -2
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +15 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +7 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Webhooks.d.ts +0 -75
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +1 -143
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +127 -78
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +115 -1
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +59 -6
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +3 -3
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +4 -2
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +83 -83
- 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 +151 -151
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/data/App.d.ts +5924 -4310
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +61 -9
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +62 -0
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
- package/dist/apps/data/ZoneSelection.js +44 -0
- package/dist/apps/data/ZoneSelection.js.map +1 -0
- package/dist/apps/data/routes/activities.d.ts +2368 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +423 -114
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +131 -0
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +25 -25
- package/dist/apps/data/routes/balances.js +1 -1
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +1 -1
- package/dist/apps/data/routes/blocks.js +1 -1
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/earn.d.ts +135 -10
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +157 -25
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +829 -123
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +16 -13
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +26 -26
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +9 -11
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +54 -54
- 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.js +24 -10
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +12 -12
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +16 -15
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts +17 -3
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +34 -15
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +1 -1
- package/dist/apps/data/routes/transactions.js +1 -1
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +13 -13
- package/dist/apps/data/routes/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +7 -9
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +21 -21
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1011 -151
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +126 -739
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +15 -15
- package/dist/apps/funding/App.d.ts +27 -27
- package/dist/apps/funding/routes/chains.d.ts.map +1 -1
- package/dist/apps/funding/routes/chains.js +5 -4
- package/dist/apps/funding/routes/chains.js.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.d.ts +18 -18
- package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/funding/routes/deposit-addresses.js +8 -8
- package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/funding/routes/providers.d.ts.map +1 -1
- package/dist/apps/funding/routes/providers.js +3 -2
- package/dist/apps/funding/routes/providers.js.map +1 -1
- package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
- package/dist/apps/funding/routes/quotes.js +2 -2
- package/dist/apps/funding/routes/quotes.js.map +1 -1
- package/dist/apps/funding/routes/transfers.d.ts +33 -33
- package/dist/apps/management/App.d.ts +1433 -322
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +19 -6
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +154 -94
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +76 -30
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +103 -30
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +91 -32
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +12 -12
- package/dist/apps/management/routes/faucet.d.ts.map +1 -1
- package/dist/apps/management/routes/faucet.js +23 -12
- package/dist/apps/management/routes/faucet.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +46 -13
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +79 -29
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts +128 -83
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +100 -41
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +5 -5
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +14 -10
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +68 -47
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +37 -18
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +48 -8
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +48 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +130 -68
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +72 -21
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +8 -5
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +38 -38
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +41 -31
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +34 -6
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +36 -17
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +1186 -197
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +106 -38
- package/dist/apps/management/routes/webhooks.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
- package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +12 -0
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/db/Db.d.ts +2 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +61 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +30 -2
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +28 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +5 -0
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +10 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
- package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
- package/dist/db/tables/webhookQueueCompletions.js +32 -0
- package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
- package/dist/db/tables/webhookQueueEvents.d.ts +16 -20
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +68 -43
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +47 -72
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +92 -105
- package/dist/db/tables/webhookSubscriptions.js.map +1 -1
- package/dist/internal/Auth.d.ts +8 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +13 -3
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +11 -7
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +41 -2
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +167 -0
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/MetricSink.d.ts +35 -125
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +50 -121
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +26 -22
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +128 -39
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/Response.d.ts +13 -8
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +16 -5
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +8 -8
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +10 -9
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/Store.d.ts +15 -6
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +45 -15
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Tidx.d.ts +2 -0
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +16 -4
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/WebhookTransfer.d.ts +1 -55
- package/dist/internal/WebhookTransfer.d.ts.map +1 -1
- package/dist/internal/WebhookTransfer.js +1 -239
- package/dist/internal/WebhookTransfer.js.map +1 -1
- package/dist/internal/Webhooks.d.ts +112 -56
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +124 -93
- package/dist/internal/Webhooks.js.map +1 -1
- package/dist/internal/funding/Deposit.d.ts +2 -2
- package/dist/internal/funding/Deposit.d.ts.map +1 -1
- package/dist/internal/funding/Deposit.js +9 -8
- package/dist/internal/funding/Deposit.js.map +1 -1
- package/dist/internal/funding/DepositAddress.d.ts +4 -4
- package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
- package/dist/internal/funding/DepositAddress.js +9 -8
- package/dist/internal/funding/DepositAddress.js.map +1 -1
- package/dist/internal/funding/DepositWebhook.d.ts +25 -0
- package/dist/internal/funding/DepositWebhook.d.ts.map +1 -0
- package/dist/internal/funding/DepositWebhook.js +74 -0
- package/dist/internal/funding/DepositWebhook.js.map +1 -0
- package/dist/internal/funding/Provider.d.ts.map +1 -1
- package/dist/internal/funding/Provider.js +13 -12
- package/dist/internal/funding/Provider.js.map +1 -1
- package/dist/internal/funding/Reconciliation.d.ts +6 -0
- package/dist/internal/funding/Reconciliation.d.ts.map +1 -1
- package/dist/internal/funding/Reconciliation.js +42 -10
- package/dist/internal/funding/Reconciliation.js.map +1 -1
- package/dist/internal/funding/index.d.ts +1 -0
- package/dist/internal/funding/index.d.ts.map +1 -1
- package/dist/internal/funding/index.js +1 -0
- package/dist/internal/funding/index.js.map +1 -1
- package/dist/internal/funding/providers/stargate.d.ts +19 -0
- package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
- package/dist/internal/funding/providers/stargate.js +143 -0
- package/dist/internal/funding/providers/stargate.js.map +1 -0
- package/dist/internal/webhookDestinations/slack.d.ts.map +1 -1
- package/dist/internal/webhookDestinations/slack.js +16 -0
- package/dist/internal/webhookDestinations/slack.js.map +1 -1
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +2 -2
- package/src/App.test.ts +48 -0
- package/src/App.ts +7 -2
- package/src/Assets.test.ts +18 -0
- package/src/Assets.ts +22 -0
- package/src/Client.test-d.ts +287 -17
- package/src/Webhooks.ts +1 -220
- package/src/admin/apps/earn-vaults.test.ts +143 -0
- package/src/admin/apps/earn-vaults.ts +83 -6
- package/src/admin/apps/organizations.ts +6 -2
- package/src/admin/ui/src/routes/api-keys.tsx +36 -0
- package/src/admin/ui.generated.ts +151 -189
- package/src/apps/data/App.test.ts +31 -0
- package/src/apps/data/App.ts +64 -10
- package/src/apps/data/ZoneSelection.test.ts +196 -0
- package/src/apps/data/ZoneSelection.ts +108 -0
- package/src/apps/data/routes/activities.test.ts +435 -12
- package/src/apps/data/routes/activities.ts +562 -125
- package/src/apps/data/routes/balances.ts +1 -1
- package/src/apps/data/routes/blocks.ts +1 -1
- package/src/apps/data/routes/earn.test.ts +183 -23
- package/src/apps/data/routes/earn.ts +225 -29
- package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
- package/src/apps/data/routes/exchanges.test.ts +31 -1
- package/src/apps/data/routes/exchanges.ts +19 -15
- package/src/apps/data/routes/fee-amm.ts +18 -11
- package/src/apps/data/routes/receipts.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +75 -0
- package/src/apps/data/routes/rpc.ts +23 -9
- package/src/apps/data/routes/tokenlist.ts +21 -18
- package/src/apps/data/routes/tokens.test.ts +29 -0
- package/src/apps/data/routes/tokens.ts +38 -15
- package/src/apps/data/routes/transactions.ts +1 -1
- package/src/apps/data/routes/transfers.test.ts +3 -3
- package/src/apps/data/routes/transfers.ts +12 -9
- package/src/apps/data/routes/webhooks.test.ts +179 -1497
- package/src/apps/data/routes/webhooks.ts +156 -976
- package/src/apps/data/routes/zones.test.ts +19 -13
- package/src/apps/funding/routes/chains.test.ts +211 -7
- package/src/apps/funding/routes/chains.ts +19 -12
- package/src/apps/funding/routes/deposit-addresses.test.ts +394 -0
- package/src/apps/funding/routes/deposit-addresses.ts +84 -72
- package/src/apps/funding/routes/providers.ts +9 -5
- package/src/apps/funding/routes/quotes.test.ts +46 -0
- package/src/apps/funding/routes/quotes.ts +8 -5
- package/src/apps/funding/routes/transfers.test.ts +35 -32
- package/src/apps/management/Billing.test.ts +26 -0
- package/src/apps/management/Billing.ts +24 -7
- package/src/apps/management/routes/api-keys.test.ts +178 -0
- package/src/apps/management/routes/api-keys.ts +203 -144
- package/src/apps/management/routes/billing.test.ts +209 -0
- package/src/apps/management/routes/billing.ts +254 -177
- package/src/apps/management/routes/faucet.test.ts +39 -0
- package/src/apps/management/routes/faucet.ts +75 -41
- package/src/apps/management/routes/invitations.test.ts +216 -0
- package/src/apps/management/routes/invitations.ts +186 -109
- package/src/apps/management/routes/invite-links.test.ts +263 -1
- package/src/apps/management/routes/invite-links.ts +295 -214
- package/src/apps/management/routes/me.test.ts +49 -0
- package/src/apps/management/routes/me.ts +42 -32
- package/src/apps/management/routes/members.test.ts +124 -1
- package/src/apps/management/routes/members.ts +81 -51
- package/src/apps/management/routes/orgs.test.ts +176 -0
- package/src/apps/management/routes/orgs.ts +101 -59
- package/src/apps/management/routes/projects.test.ts +183 -0
- package/src/apps/management/routes/projects.ts +124 -60
- package/src/apps/management/routes/scopes.test.ts +44 -0
- package/src/apps/management/routes/scopes.ts +37 -28
- package/src/apps/management/routes/usage.test.ts +92 -0
- package/src/apps/management/routes/usage.ts +186 -151
- package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
- package/src/apps/management/routes/verified-token-requests.ts +166 -133
- package/src/apps/management/routes/webhooks.test.ts +313 -1
- package/src/apps/management/routes/webhooks.ts +220 -71
- package/src/apps/mpp/internal/Adapter.ts +13 -1
- package/src/db/Db.test.ts +42 -5
- package/src/db/Db.ts +85 -0
- package/src/db/Schema.ts +41 -3
- package/src/db/tables/earnVaults.test.ts +22 -0
- package/src/db/tables/earnVaults.ts +11 -1
- package/src/db/tables/organizations.test.ts +5 -2
- package/src/db/tables/webhookDeliveries.ts +13 -0
- package/src/db/tables/webhookQueueCompletions.ts +55 -0
- package/src/db/tables/webhookQueueEvents.ts +97 -57
- package/src/db/tables/webhookSubscriptions.ts +134 -144
- package/src/internal/Auth.ts +23 -5
- package/src/internal/Cache.ts +14 -7
- package/src/internal/EarnVaults.capabilities.test.ts +33 -0
- package/src/internal/EarnVaults.test.ts +79 -0
- package/src/internal/EarnVaults.ts +277 -0
- package/src/internal/MetricSink.test.ts +41 -373
- package/src/internal/MetricSink.ts +92 -273
- package/src/internal/OpenApi.ts +165 -49
- package/src/internal/Response.test.ts +95 -0
- package/src/internal/Response.ts +40 -2
- package/src/internal/Schema.test.ts +34 -0
- package/src/internal/Schema.ts +20 -9
- package/src/internal/Store.test.ts +186 -0
- package/src/internal/Store.ts +57 -17
- package/src/internal/Tidx.test.ts +19 -0
- package/src/internal/Tidx.ts +16 -4
- package/src/internal/WebhookTransfer.ts +1 -351
- package/src/internal/Webhooks.test.ts +222 -145
- package/src/internal/Webhooks.ts +234 -135
- package/src/internal/funding/Deposit.ts +71 -64
- package/src/internal/funding/DepositAddress.ts +50 -43
- package/src/internal/funding/DepositWebhook.test.ts +131 -0
- package/src/internal/funding/DepositWebhook.ts +101 -0
- package/src/internal/funding/Provider.ts +164 -142
- package/src/internal/funding/Reconciliation.test.ts +14 -0
- package/src/internal/funding/Reconciliation.ts +161 -86
- package/src/internal/funding/index.test.ts +1 -0
- package/src/internal/funding/index.ts +1 -0
- package/src/internal/funding/providers/index.test.ts +185 -0
- package/src/internal/funding/providers/stargate.ts +184 -0
- package/src/internal/webhookDestinations/slack.ts +15 -0
- package/src/providers/index.test.ts +1 -0
- package/src/providers/index.ts +9 -0
- package/src/Webhooks.bench.ts +0 -714
- package/src/Webhooks.memory.bench.ts +0 -250
- package/src/Webhooks.test.ts +0 -146
|
@@ -149,6 +149,37 @@ describe('MPP session management', () => {
|
|
|
149
149
|
PaymentRequest.serialize({ _mppx_scope: 'GET /v1/scopes' }),
|
|
150
150
|
)
|
|
151
151
|
})
|
|
152
|
+
|
|
153
|
+
test('applies POST auth overrides to QUERY aliases', async () => {
|
|
154
|
+
const app = TestApp.create({
|
|
155
|
+
auth: {
|
|
156
|
+
overrides: {
|
|
157
|
+
'POST /v1/exchange/quotes': { mpp: false, public: false },
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
const post = await app.request('/v1/exchange/quotes', { method: 'POST' })
|
|
163
|
+
const query = await app.request('/v1/exchange/quotes', { method: 'QUERY' })
|
|
164
|
+
|
|
165
|
+
expect([post.status, query.status]).toEqual([401, 401])
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('prefers an explicit QUERY auth override', async () => {
|
|
169
|
+
const app = TestApp.create({
|
|
170
|
+
auth: {
|
|
171
|
+
overrides: {
|
|
172
|
+
'POST /v1/exchange/quotes': { mpp: false, public: false },
|
|
173
|
+
'QUERY /v1/exchange/quotes': false,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
const post = await app.request('/v1/exchange/quotes', { method: 'POST' })
|
|
179
|
+
const query = await app.request('/v1/exchange/quotes', { method: 'QUERY' })
|
|
180
|
+
|
|
181
|
+
expect([post.status, query.status]).toEqual([401, 400])
|
|
182
|
+
})
|
|
152
183
|
})
|
|
153
184
|
|
|
154
185
|
describe('zone chain gate', () => {
|
package/src/apps/data/App.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { matchedRoutes } from 'hono/route'
|
|
|
3
3
|
import { ZoneRpcAuthentication } from 'ox/tempo'
|
|
4
4
|
import * as z from 'zod/mini'
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import * as Assets from '../../Assets.js'
|
|
7
7
|
import type * as App from '../../App.js'
|
|
8
8
|
import * as Auth from '../../internal/Auth.js'
|
|
9
9
|
import * as EdgeCache from '../../internal/EdgeCache.js'
|
|
@@ -17,6 +17,7 @@ import * as Scope from '../../Scope.js'
|
|
|
17
17
|
import * as Metadata from '../metadata.js'
|
|
18
18
|
|
|
19
19
|
import type * as FxOracle from './FxOracle.js'
|
|
20
|
+
import * as ZoneSelection from './ZoneSelection.js'
|
|
20
21
|
|
|
21
22
|
import { transactions as transactionActivities } from './routes/activities.js'
|
|
22
23
|
import { addresses } from './routes/addresses.js'
|
|
@@ -58,9 +59,17 @@ export function data(options: data.Options = {}) {
|
|
|
58
59
|
const dataRouteHandlers = new Set<unknown>()
|
|
59
60
|
|
|
60
61
|
const getTidx = Tidx.createGetClient({ tidx })
|
|
62
|
+
const addresses_routes = addresses({ fx: options.fx })
|
|
61
63
|
const earn_routes = earn({ fx: options.fx })
|
|
62
64
|
const indexer_routes = indexer()
|
|
65
|
+
const transactionActivities_routes = transactionActivities({ fx: options.fx })
|
|
63
66
|
const indexerRouteHandlers = new Set(indexer_routes.routes.map((route) => route.handler))
|
|
67
|
+
const inferredZoneRouteHandlers = new Set([
|
|
68
|
+
...addresses_routes.routes
|
|
69
|
+
.filter((route) => route.path === '/v1/addresses/:address/activities')
|
|
70
|
+
.map((route) => route.handler),
|
|
71
|
+
...transactionActivities_routes.routes.map((route) => route.handler),
|
|
72
|
+
])
|
|
64
73
|
const rpcOnlyRouteHandlers = new Set(
|
|
65
74
|
earn_routes.routes
|
|
66
75
|
.filter((route) => route.path === '/v1/earn/vaults/:vaultId/positions/:address')
|
|
@@ -106,6 +115,7 @@ export function data(options: data.Options = {}) {
|
|
|
106
115
|
c,
|
|
107
116
|
defaultChainId,
|
|
108
117
|
handlers: dataRouteHandlers,
|
|
118
|
+
inferredZoneHandlers: inferredZoneRouteHandlers,
|
|
109
119
|
indexerHandlers: indexerRouteHandlers,
|
|
110
120
|
rpcOnlyHandlers: rpcOnlyRouteHandlers,
|
|
111
121
|
})
|
|
@@ -120,6 +130,30 @@ export function data(options: data.Options = {}) {
|
|
|
120
130
|
const rpc_config = c.get('rpc')
|
|
121
131
|
const tidx_config = c.get('tidx')
|
|
122
132
|
const zones = c.get('zones')
|
|
133
|
+
if (selection.inferredZones) {
|
|
134
|
+
if (principal?.type !== 'api_key')
|
|
135
|
+
return Response.error(c, {
|
|
136
|
+
code: 'api_key_forbidden',
|
|
137
|
+
message: '`include=zones` requires an API key with readable Zone scopes.',
|
|
138
|
+
status: 403,
|
|
139
|
+
})
|
|
140
|
+
const zoneChainIds = ZoneSelection.readableChainIds({
|
|
141
|
+
parentChainId: selection.chainId,
|
|
142
|
+
principal,
|
|
143
|
+
rpc: rpc_config,
|
|
144
|
+
tidx: tidx_config,
|
|
145
|
+
zones,
|
|
146
|
+
})
|
|
147
|
+
if (zoneChainIds.length === 0)
|
|
148
|
+
return Response.error(c, {
|
|
149
|
+
code: 'api_key_forbidden',
|
|
150
|
+
message: 'The API key has no readable configured Zones.',
|
|
151
|
+
status: 403,
|
|
152
|
+
})
|
|
153
|
+
c.set('supportedChainIds', new Set(zoneChainIds))
|
|
154
|
+
c.set('zoneChainIds', zoneChainIds)
|
|
155
|
+
return next()
|
|
156
|
+
}
|
|
123
157
|
// Raw passthroughs and RPC-only reads need only RPC; composed data routes
|
|
124
158
|
// require both upstreams to avoid falling through to unrelated defaults.
|
|
125
159
|
const narrowedChainIds = new Set(
|
|
@@ -147,10 +181,12 @@ export function data(options: data.Options = {}) {
|
|
|
147
181
|
c,
|
|
148
182
|
defaultChainId: c.get('chainId'),
|
|
149
183
|
handlers: dataRouteHandlers,
|
|
184
|
+
inferredZoneHandlers: inferredZoneRouteHandlers,
|
|
150
185
|
indexerHandlers: indexerRouteHandlers,
|
|
151
186
|
rpcOnlyHandlers: rpcOnlyRouteHandlers,
|
|
152
187
|
})
|
|
153
188
|
if (!selection.matched) return next()
|
|
189
|
+
if (selection.inferredZones) return next()
|
|
154
190
|
const chainId = c.get('chainId')
|
|
155
191
|
if (!zones.has(chainId)) return next()
|
|
156
192
|
|
|
@@ -187,10 +223,12 @@ export function data(options: data.Options = {}) {
|
|
|
187
223
|
c,
|
|
188
224
|
defaultChainId: c.get('chainId'),
|
|
189
225
|
handlers: dataRouteHandlers,
|
|
226
|
+
inferredZoneHandlers: inferredZoneRouteHandlers,
|
|
190
227
|
indexerHandlers: indexerRouteHandlers,
|
|
191
228
|
rpcOnlyHandlers: rpcOnlyRouteHandlers,
|
|
192
229
|
})
|
|
193
|
-
if (!selection.matched || !Viem.isMainnet(c.get('chainId')))
|
|
230
|
+
if (!selection.matched || selection.inferredZones || !Viem.isMainnet(c.get('chainId')))
|
|
231
|
+
return next()
|
|
194
232
|
|
|
195
233
|
return Response.error(c, {
|
|
196
234
|
code: 'api_key_forbidden',
|
|
@@ -211,7 +249,7 @@ export function data(options: data.Options = {}) {
|
|
|
211
249
|
'Content-Type': asset.contentType,
|
|
212
250
|
})
|
|
213
251
|
})
|
|
214
|
-
.route('/',
|
|
252
|
+
.route('/', addresses_routes)
|
|
215
253
|
.route('/', blocks())
|
|
216
254
|
.route('/', earn_routes)
|
|
217
255
|
.route('/', exchanges({ fx: options.fx }))
|
|
@@ -221,10 +259,16 @@ export function data(options: data.Options = {}) {
|
|
|
221
259
|
.route('/', tokenlist())
|
|
222
260
|
.route('/', tokens())
|
|
223
261
|
.route('/', transactions())
|
|
224
|
-
.route('/',
|
|
262
|
+
.route('/', transactionActivities_routes)
|
|
225
263
|
.route('/', transfers({ fx: options.fx }))
|
|
226
264
|
.route('/', verifiedTokens())
|
|
227
|
-
.route(
|
|
265
|
+
.route(
|
|
266
|
+
'/',
|
|
267
|
+
webhooks({
|
|
268
|
+
applicationEventTypes: webhook?.applicationEventTypes ?? [],
|
|
269
|
+
enabled: options.webhook !== false,
|
|
270
|
+
}),
|
|
271
|
+
)
|
|
228
272
|
.route('/', zones())
|
|
229
273
|
.route('/', rpc())
|
|
230
274
|
.route('/', coingecko())
|
|
@@ -234,14 +278,16 @@ export function data(options: data.Options = {}) {
|
|
|
234
278
|
c,
|
|
235
279
|
defaultChainId: c.get('chainId'),
|
|
236
280
|
handlers: dataRouteHandlers,
|
|
281
|
+
inferredZoneHandlers: inferredZoneRouteHandlers,
|
|
237
282
|
indexerHandlers: indexerRouteHandlers,
|
|
238
283
|
rpcOnlyHandlers: rpcOnlyRouteHandlers,
|
|
239
284
|
})
|
|
240
|
-
if (selection.matched && !selection.conflict && !selection.invalid)
|
|
285
|
+
if (selection.matched && !selection.conflict && !selection.inferredZones && !selection.invalid)
|
|
241
286
|
c.set('chainId', selection.chainId)
|
|
242
287
|
return (
|
|
243
288
|
selection.matched &&
|
|
244
289
|
!selection.conflict &&
|
|
290
|
+
!selection.inferredZones &&
|
|
245
291
|
!selection.invalid &&
|
|
246
292
|
!c.get('zones').has(selection.chainId)
|
|
247
293
|
)
|
|
@@ -296,6 +342,7 @@ function resolveChainSelector(options: {
|
|
|
296
342
|
c: Context<App.Environment>
|
|
297
343
|
defaultChainId: Viem.ChainId
|
|
298
344
|
handlers: ReadonlySet<unknown>
|
|
345
|
+
inferredZoneHandlers: ReadonlySet<unknown>
|
|
299
346
|
indexerHandlers: ReadonlySet<unknown>
|
|
300
347
|
rpcOnlyHandlers: ReadonlySet<unknown>
|
|
301
348
|
}) {
|
|
@@ -304,9 +351,11 @@ function resolveChainSelector(options: {
|
|
|
304
351
|
let rpc = false
|
|
305
352
|
let rpcOnly = false
|
|
306
353
|
let indexer = false
|
|
354
|
+
let inferredZonesAllowed = false
|
|
307
355
|
for (const route of matchedRoutes(options.c)) {
|
|
308
356
|
if (!options.handlers.has(route.handler)) continue
|
|
309
357
|
matched = true
|
|
358
|
+
if (options.inferredZoneHandlers.has(route.handler)) inferredZonesAllowed = true
|
|
310
359
|
if (options.indexerHandlers.has(route.handler)) indexer = true
|
|
311
360
|
if (options.rpcOnlyHandlers.has(route.handler)) rpcOnly = true
|
|
312
361
|
const selector = pathChainSelector(route.path, options.c.req.path)
|
|
@@ -320,6 +369,7 @@ function resolveChainSelector(options: {
|
|
|
320
369
|
return {
|
|
321
370
|
chainId: options.defaultChainId,
|
|
322
371
|
conflict: false,
|
|
372
|
+
inferredZones: false,
|
|
323
373
|
indexer: false,
|
|
324
374
|
invalid: false,
|
|
325
375
|
matched: false,
|
|
@@ -328,6 +378,10 @@ function resolveChainSelector(options: {
|
|
|
328
378
|
}
|
|
329
379
|
|
|
330
380
|
const search = new URL(options.c.req.url).searchParams
|
|
381
|
+
const include = inferredZonesAllowed
|
|
382
|
+
? search.getAll('include').flatMap((value) => value.split(',').map((part) => part.trim()))
|
|
383
|
+
: []
|
|
384
|
+
const inferredZones = include.includes('zones')
|
|
331
385
|
const raw = [
|
|
332
386
|
...(path === undefined ? [] : [path]),
|
|
333
387
|
...(rpc ? [] : search.getAll('chainId')),
|
|
@@ -338,6 +392,7 @@ function resolveChainSelector(options: {
|
|
|
338
392
|
return {
|
|
339
393
|
chainId: chainIds[0] ?? options.defaultChainId,
|
|
340
394
|
conflict: chainIds.length > 1,
|
|
395
|
+
inferredZones,
|
|
341
396
|
indexer,
|
|
342
397
|
invalid: parsed.some((result) => !result.success),
|
|
343
398
|
matched: true,
|
|
@@ -445,7 +500,7 @@ function webhooksBlock() {
|
|
|
445
500
|
'tempo-event-id',
|
|
446
501
|
'A unique, stable id for this event (`evt_…`). The same event may be delivered more than once, so use this id to skip duplicates.',
|
|
447
502
|
),
|
|
448
|
-
header('tempo-event-type', 'What happened: `token:transfer`, `transaction:included`, `log:emitted`, `block:created`, or `ping`.'), // prettier-ignore
|
|
503
|
+
header('tempo-event-type', 'What happened: `token:transfer`, `transaction:included`, `log:emitted`, `block:created`, `funding:deposit.updated`, or `ping`.'), // prettier-ignore
|
|
449
504
|
],
|
|
450
505
|
requestBody: {
|
|
451
506
|
content: { 'application/json': { schema: envelope } },
|
|
@@ -467,7 +522,6 @@ function createGetAsset(options: createGetAsset.Options): App.GetAsset {
|
|
|
467
522
|
const { assets, basePath, origin } = options
|
|
468
523
|
if (!assets) return () => undefined
|
|
469
524
|
const getAsset: App.GetAsset = async (chainId, path) => {
|
|
470
|
-
const pathname = Path.join(basePath, 'assets', String(chainId), path)
|
|
471
525
|
// `path` may be absolute (`Path.join` returns a leading slash); strip it so
|
|
472
526
|
// the key is `:chainId/:path`, not `:chainId//:path`.
|
|
473
527
|
const key = `${chainId}/${path.replace(/^\/+/, '')}`
|
|
@@ -477,7 +531,7 @@ function createGetAsset(options: createGetAsset.Options): App.GetAsset {
|
|
|
477
531
|
response: new globalThis.Response(asset.body, {
|
|
478
532
|
headers: { 'Content-Type': asset.contentType },
|
|
479
533
|
}),
|
|
480
|
-
uri:
|
|
534
|
+
uri: Assets.url({ basePath, chainId, origin, path }),
|
|
481
535
|
}
|
|
482
536
|
}
|
|
483
537
|
const list = assets.list
|
|
@@ -486,7 +540,7 @@ function createGetAsset(options: createGetAsset.Options): App.GetAsset {
|
|
|
486
540
|
const prefix = `${chainId}/${path.replace(/^\/+/, '')}`
|
|
487
541
|
return (await list(prefix)).map((key) => ({
|
|
488
542
|
key,
|
|
489
|
-
uri:
|
|
543
|
+
uri: Assets.url({ basePath, chainId, origin, path: key.slice(String(chainId).length + 1) }),
|
|
490
544
|
}))
|
|
491
545
|
}
|
|
492
546
|
return getAsset
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import * as ApiKey from '../../ApiKey.js'
|
|
2
|
+
import * as App from '../../App.js'
|
|
3
|
+
import * as Db from '../../db/Db.js'
|
|
4
|
+
import type * as Auth from '../../internal/Auth.js'
|
|
5
|
+
import * as Viem from '../../internal/Viem.js'
|
|
6
|
+
import * as Zones from '../Zones.js'
|
|
7
|
+
|
|
8
|
+
import * as Data from './App.js'
|
|
9
|
+
import * as ZoneSelection from './ZoneSelection.js'
|
|
10
|
+
import * as Activities from './routes/activities.js'
|
|
11
|
+
|
|
12
|
+
describe('transaction activity Zone query', () => {
|
|
13
|
+
test('accepts the Zones include with an optional parent chain', () => {
|
|
14
|
+
expect(
|
|
15
|
+
Activities.schema.getTransactionActivities.Query.parse({ include: 'zones' }).include,
|
|
16
|
+
).toStrictEqual(['zones'])
|
|
17
|
+
expect(
|
|
18
|
+
Activities.schema.getTransactionActivities.Query.parse({
|
|
19
|
+
chainId: '4217',
|
|
20
|
+
include: 'zones',
|
|
21
|
+
}),
|
|
22
|
+
).toMatchObject({ chainId: 4217, include: ['zones'] })
|
|
23
|
+
expect(
|
|
24
|
+
Activities.schema.getTransactionActivities.Query.safeParse({ includeZones: 'true' }).success,
|
|
25
|
+
).toBe(false)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('opts in only activity routes and accepts a parent chain', async () => {
|
|
29
|
+
const app = App.create({
|
|
30
|
+
auth: false,
|
|
31
|
+
db: Db.postgres({ connectionString: 'postgresql://unused@127.0.0.1:1/unused' }),
|
|
32
|
+
zones: [Zones.zoneModeratoInternal],
|
|
33
|
+
}).route('/', Data.data({ webhook: false }))
|
|
34
|
+
const address = '0x0000000000000000000000000000000000000001'
|
|
35
|
+
const hash = `0x${'00'.repeat(32)}`
|
|
36
|
+
const addressScoped = await app.request(
|
|
37
|
+
`/v1/addresses/${address}/activities?include=zones&chainId=${Viem.chainId.testnet}`,
|
|
38
|
+
)
|
|
39
|
+
const forbidden = await app.request(`/v1/transactions/${hash}/activities?include=zones`)
|
|
40
|
+
const scoped = await app.request(
|
|
41
|
+
`/v1/transactions/${hash}/activities?include=zones&chainId=${Viem.chainId.testnet}`,
|
|
42
|
+
)
|
|
43
|
+
const unsupported = await app.request('/v1/tokenlist?include=zones')
|
|
44
|
+
|
|
45
|
+
expect(forbidden.status).toBe(403)
|
|
46
|
+
expect(forbidden.headers.get('cache-control')).toBe('no-store')
|
|
47
|
+
expect(await addressScoped.json()).toMatchObject({ error: { code: 'api_key_forbidden' } })
|
|
48
|
+
expect(await scoped.json()).toMatchObject({ error: { code: 'api_key_forbidden' } })
|
|
49
|
+
expect(await unsupported.json()).toMatchObject({ error: { code: 'query_invalid' } })
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
describe('readableChainIds', () => {
|
|
54
|
+
test('intersects the parent chain, scopes, and configured routable Zones', () => {
|
|
55
|
+
const principal = apiKeyPrincipal({
|
|
56
|
+
scopes: [
|
|
57
|
+
'data:read',
|
|
58
|
+
`zone:${Zones.zoneMainnetInternal.id}:read`,
|
|
59
|
+
`zone:${Zones.zoneModeratoInternal.id}:write`,
|
|
60
|
+
],
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
expect(
|
|
64
|
+
ZoneSelection.readableChainIds({
|
|
65
|
+
parentChainId: Viem.chainId.testnet,
|
|
66
|
+
principal,
|
|
67
|
+
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
68
|
+
}),
|
|
69
|
+
).toStrictEqual([Zones.zoneModeratoInternal.id])
|
|
70
|
+
expect(
|
|
71
|
+
ZoneSelection.readableChainIds({
|
|
72
|
+
parentChainId: Viem.chainId.mainnet,
|
|
73
|
+
principal,
|
|
74
|
+
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
75
|
+
}),
|
|
76
|
+
).toStrictEqual([Zones.zoneMainnetInternal.id])
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('lets wildcard keys read every configured routable Zone of the parent chain', () => {
|
|
80
|
+
expect(
|
|
81
|
+
ZoneSelection.readableChainIds({
|
|
82
|
+
parentChainId: Viem.chainId.testnet,
|
|
83
|
+
principal: apiKeyPrincipal({ scopes: ['*'] }),
|
|
84
|
+
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
85
|
+
}),
|
|
86
|
+
).toStrictEqual([Zones.zoneModeratoInternal.id])
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('filters sandbox keys by each Zone parent chain', () => {
|
|
90
|
+
const principal = apiKeyPrincipal({
|
|
91
|
+
environment: 'sandbox',
|
|
92
|
+
scopes: [
|
|
93
|
+
'data:read',
|
|
94
|
+
`zone:${Zones.zoneMainnetInternal.id}:read`,
|
|
95
|
+
`zone:${Zones.zoneModeratoInternal.id}:read`,
|
|
96
|
+
],
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
expect(
|
|
100
|
+
ZoneSelection.readableChainIds({
|
|
101
|
+
parentChainId: Viem.chainId.testnet,
|
|
102
|
+
principal,
|
|
103
|
+
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
104
|
+
}),
|
|
105
|
+
).toStrictEqual([Zones.zoneModeratoInternal.id])
|
|
106
|
+
expect(
|
|
107
|
+
ZoneSelection.readableChainIds({
|
|
108
|
+
parentChainId: Viem.chainId.mainnet,
|
|
109
|
+
principal,
|
|
110
|
+
zones: new Map(Zones.chains.map((zone) => [zone.id, zone])),
|
|
111
|
+
}),
|
|
112
|
+
).toStrictEqual([])
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('requires data read access and both upstreams', () => {
|
|
116
|
+
const zone = {
|
|
117
|
+
...Zones.zoneModeratoInternal,
|
|
118
|
+
id: 1_424_310_099,
|
|
119
|
+
rpcUrls: { default: { http: ['https://zone.rpc.test'] } },
|
|
120
|
+
}
|
|
121
|
+
const zones = new Map([[zone.id, zone]])
|
|
122
|
+
|
|
123
|
+
expect(
|
|
124
|
+
ZoneSelection.readableChainIds({
|
|
125
|
+
parentChainId: zone.sourceId,
|
|
126
|
+
principal: apiKeyPrincipal({ scopes: [`zone:${zone.id}:read`] }),
|
|
127
|
+
zones,
|
|
128
|
+
}),
|
|
129
|
+
).toStrictEqual([])
|
|
130
|
+
expect(
|
|
131
|
+
ZoneSelection.readableChainIds({
|
|
132
|
+
parentChainId: zone.sourceId,
|
|
133
|
+
principal: apiKeyPrincipal({ scopes: ['data:read', `zone:${zone.id}:read`] }),
|
|
134
|
+
zones,
|
|
135
|
+
}),
|
|
136
|
+
).toStrictEqual([])
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
describe('uniqueMatch', () => {
|
|
141
|
+
test('selects one match after every Zone completes', () => {
|
|
142
|
+
expect(
|
|
143
|
+
ZoneSelection.uniqueMatch([
|
|
144
|
+
{ chainId: 1, value: null },
|
|
145
|
+
{ chainId: 2, value: 'receipt' },
|
|
146
|
+
]),
|
|
147
|
+
).toStrictEqual({ chainId: 2, kind: 'selected', value: 'receipt' })
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('distinguishes no match from ambiguous matches', () => {
|
|
151
|
+
expect(ZoneSelection.uniqueMatch([{ chainId: 1, value: null }])).toStrictEqual({
|
|
152
|
+
kind: 'not_found',
|
|
153
|
+
})
|
|
154
|
+
expect(
|
|
155
|
+
ZoneSelection.uniqueMatch([
|
|
156
|
+
{ chainId: 1, value: 'first' },
|
|
157
|
+
{ chainId: 2, value: 'second' },
|
|
158
|
+
]),
|
|
159
|
+
).toStrictEqual({ kind: 'ambiguous' })
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
test('fails the selection when any Zone lookup fails', () => {
|
|
163
|
+
const cause = new Error('unavailable')
|
|
164
|
+
expect(
|
|
165
|
+
ZoneSelection.uniqueMatch([
|
|
166
|
+
{ chainId: 1, value: 'receipt' },
|
|
167
|
+
{ cause, chainId: 2 },
|
|
168
|
+
]),
|
|
169
|
+
).toStrictEqual({ failures: [{ cause, chainId: 2 }], kind: 'failed' })
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
function apiKeyPrincipal(
|
|
174
|
+
options: apiKeyPrincipal.Options,
|
|
175
|
+
): Extract<Auth.Principal, { type: 'api_key' }> {
|
|
176
|
+
const apiKey = ApiKey.schema.ApiKey.parse({
|
|
177
|
+
environment: options.environment,
|
|
178
|
+
id: 'key_test',
|
|
179
|
+
orgId: 'org_test',
|
|
180
|
+
scopes: options.scopes,
|
|
181
|
+
})
|
|
182
|
+
return {
|
|
183
|
+
apiKey,
|
|
184
|
+
environment: apiKey.environment,
|
|
185
|
+
id: apiKey.id,
|
|
186
|
+
orgId: apiKey.orgId,
|
|
187
|
+
type: 'api_key',
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
declare namespace apiKeyPrincipal {
|
|
192
|
+
type Options = {
|
|
193
|
+
environment?: 'production' | 'sandbox' | undefined
|
|
194
|
+
scopes: readonly string[]
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Chain } from 'viem'
|
|
2
|
+
|
|
3
|
+
import type * as Auth from '../../internal/Auth.js'
|
|
4
|
+
import * as Tidx from '../../internal/Tidx.js'
|
|
5
|
+
import * as Viem from '../../internal/Viem.js'
|
|
6
|
+
import * as Scope from '../../Scope.js'
|
|
7
|
+
|
|
8
|
+
/** Returns configured and routable Zones that an API key may read. */
|
|
9
|
+
export function readableChainIds(options: readableChainIds.Options): readonly number[] {
|
|
10
|
+
const { parentChainId, principal, zones } = options
|
|
11
|
+
const scopes = principal.apiKey.scopes
|
|
12
|
+
if (!scopes.includes(Scope.wildcard) && !scopes.includes('data:read')) return []
|
|
13
|
+
|
|
14
|
+
const chainIds = [...zones.values()].flatMap((zone) => {
|
|
15
|
+
if (zone.sourceId !== parentChainId) return []
|
|
16
|
+
const allowed =
|
|
17
|
+
scopes.includes(Scope.wildcard) ||
|
|
18
|
+
scopes.includes(`zone:${zone.id}:read`) ||
|
|
19
|
+
scopes.includes(`zone:${zone.id}:write`)
|
|
20
|
+
if (!allowed) return []
|
|
21
|
+
if (
|
|
22
|
+
principal.environment === 'sandbox' &&
|
|
23
|
+
(zone.sourceId === undefined || Viem.isMainnet(zone.sourceId))
|
|
24
|
+
)
|
|
25
|
+
return []
|
|
26
|
+
|
|
27
|
+
const context = { chainId: zone.id, principal, zone }
|
|
28
|
+
if (Viem.resolveRpc(options.rpc, context).url === undefined) return []
|
|
29
|
+
if (Tidx.resolve(options.tidx, context).baseUrl === undefined) return []
|
|
30
|
+
return [zone.id]
|
|
31
|
+
})
|
|
32
|
+
return chainIds.sort((a, b) => a - b)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare namespace readableChainIds {
|
|
36
|
+
/** Inputs for resolving the readable inferred-Zone set. */
|
|
37
|
+
type Options = {
|
|
38
|
+
/** Parent Tempo chain whose Zones may be selected. */
|
|
39
|
+
parentChainId: Viem.ChainId
|
|
40
|
+
/** Authenticated API-key principal selecting Zones. */
|
|
41
|
+
principal: Extract<Auth.Principal, { type: 'api_key' }>
|
|
42
|
+
/** RPC configuration used to exclude unroutable Zones. */
|
|
43
|
+
rpc?: Viem.getClient.Rpc | undefined
|
|
44
|
+
/** TIDX configuration used to exclude unroutable Zones. */
|
|
45
|
+
tidx?: Tidx.getClient.Tidx | undefined
|
|
46
|
+
/** Hosted Zone metadata keyed by chain id. */
|
|
47
|
+
zones: ReadonlyMap<number, Chain>
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Resolves receipt probes without treating partial upstream results as complete. */
|
|
52
|
+
export function uniqueMatch<const value>(
|
|
53
|
+
probes: readonly uniqueMatch.Probe<value>[],
|
|
54
|
+
): uniqueMatch.Result<value> {
|
|
55
|
+
const failures = probes.flatMap((probe) => ('cause' in probe ? [probe] : []))
|
|
56
|
+
if (failures.length > 0) return { failures, kind: 'failed' }
|
|
57
|
+
|
|
58
|
+
const matches = probes.flatMap((probe) =>
|
|
59
|
+
'value' in probe && probe.value !== null
|
|
60
|
+
? [{ chainId: probe.chainId, value: probe.value }]
|
|
61
|
+
: [],
|
|
62
|
+
)
|
|
63
|
+
if (matches.length === 0) return { kind: 'not_found' }
|
|
64
|
+
if (matches.length > 1) return { kind: 'ambiguous' }
|
|
65
|
+
return { ...matches[0]!, kind: 'selected' }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export declare namespace uniqueMatch {
|
|
69
|
+
/** One completed Zone lookup. */
|
|
70
|
+
type Probe<value> =
|
|
71
|
+
| {
|
|
72
|
+
/** Zone that completed the lookup. */
|
|
73
|
+
chainId: number
|
|
74
|
+
/** Matching value, or null when the Zone did not contain the resource. */
|
|
75
|
+
value: value | null
|
|
76
|
+
}
|
|
77
|
+
| {
|
|
78
|
+
/** Upstream failure from this Zone. */
|
|
79
|
+
cause: unknown
|
|
80
|
+
/** Zone that failed the lookup. */
|
|
81
|
+
chainId: number
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Unique-match decision across every requested Zone. */
|
|
85
|
+
type Result<value> =
|
|
86
|
+
| {
|
|
87
|
+
/** Zone containing the unique match. */
|
|
88
|
+
chainId: number
|
|
89
|
+
/** Unique match result. */
|
|
90
|
+
kind: 'selected'
|
|
91
|
+
/** Value found in the selected Zone. */
|
|
92
|
+
value: value
|
|
93
|
+
}
|
|
94
|
+
| {
|
|
95
|
+
/** Every failed Zone lookup. */
|
|
96
|
+
failures: readonly Extract<Probe<value>, { cause: unknown }>[]
|
|
97
|
+
/** Partial failure result. */
|
|
98
|
+
kind: 'failed'
|
|
99
|
+
}
|
|
100
|
+
| {
|
|
101
|
+
/** Ambiguous match result. */
|
|
102
|
+
kind: 'ambiguous'
|
|
103
|
+
}
|
|
104
|
+
| {
|
|
105
|
+
/** No-match result. */
|
|
106
|
+
kind: 'not_found'
|
|
107
|
+
}
|
|
108
|
+
}
|