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
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import * as z from 'zod/mini'
|
|
12
12
|
|
|
13
13
|
import type * as App from '../../../App.js'
|
|
14
|
+
import * as Scope from '../../../Scope.js'
|
|
14
15
|
import * as Db from '../../../db/Db.js'
|
|
15
16
|
import * as core_EarnVaults from '../../../db/tables/earnVaults.js'
|
|
16
17
|
import * as Auth from '../../../internal/Auth.js'
|
|
@@ -90,6 +91,22 @@ export declare namespace discoveryBatchLimit {
|
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
/** Returns whether API-key scopes grant read access to one private Zone. */
|
|
95
|
+
export function hasZoneAccess(options: hasZoneAccess.Options): boolean {
|
|
96
|
+
const scopes = options.scopes ?? []
|
|
97
|
+
return scopes.includes(Scope.wildcard) || scopes.includes(`zone:${options.chainId}:read`)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export declare namespace hasZoneAccess {
|
|
101
|
+
/** Inputs selecting one Zone against an optional API-key scope set. */
|
|
102
|
+
type Options = {
|
|
103
|
+
/** Private Zone chain id. */
|
|
104
|
+
chainId: number
|
|
105
|
+
/** API-key scopes, absent for every other principal. */
|
|
106
|
+
scopes?: readonly string[] | undefined
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
93
110
|
/** Zod schemas owned by the public Earn-vault resource. */
|
|
94
111
|
export namespace schema {
|
|
95
112
|
const capability = z
|
|
@@ -131,7 +148,7 @@ export namespace schema {
|
|
|
131
148
|
)
|
|
132
149
|
|
|
133
150
|
const include = z
|
|
134
|
-
.enum(['access', 'apy', 'capabilities', 'token.logoUri', 'tvl', 'zone'])
|
|
151
|
+
.enum(['access', 'apy', 'capabilities', 'token.logoUri', 'tvl', 'zone', 'zones'])
|
|
135
152
|
.check(z.describe('Optional vault fields to embed via `include`.'))
|
|
136
153
|
|
|
137
154
|
const includeQuery = Schema.includeQuery(
|
|
@@ -142,7 +159,7 @@ export namespace schema {
|
|
|
142
159
|
// `apy` and `tvl` need indexer and FX access, so surfaces lacking either
|
|
143
160
|
// select from this reduced set instead.
|
|
144
161
|
const baseInclude = z
|
|
145
|
-
.enum(['access', 'capabilities', 'token.logoUri', 'zone'])
|
|
162
|
+
.enum(['access', 'capabilities', 'token.logoUri', 'zone', 'zones'])
|
|
146
163
|
.check(z.describe('Optional vault fields to embed via `include`.'))
|
|
147
164
|
|
|
148
165
|
const baseIncludeQuery = Schema.includeQuery(
|
|
@@ -174,6 +191,42 @@ export namespace schema {
|
|
|
174
191
|
})
|
|
175
192
|
.check(z.describe('Private Zone route configured for a verified vault.'))
|
|
176
193
|
|
|
194
|
+
const zoneRoute = z
|
|
195
|
+
.strictObject({
|
|
196
|
+
chainId: Schema.ChainId.check(
|
|
197
|
+
z.describe('Private Zone chain id.'),
|
|
198
|
+
z.meta({ examples: [1424310001] }),
|
|
199
|
+
),
|
|
200
|
+
deploymentBlock: z
|
|
201
|
+
.number()
|
|
202
|
+
.check(
|
|
203
|
+
z.int(),
|
|
204
|
+
z.nonnegative(),
|
|
205
|
+
z.describe('Parent-chain block that deployed the Earn router.'),
|
|
206
|
+
z.meta({ examples: [31039238] }),
|
|
207
|
+
),
|
|
208
|
+
earnRouter: Schema.Address.check(
|
|
209
|
+
z.describe('Parent-chain router for this Zone and Earn vault.'),
|
|
210
|
+
z.meta({ examples: ['0x9144086a79dea966d8bf1b52125ebed8919fc45c'] }),
|
|
211
|
+
),
|
|
212
|
+
inputTokens: z
|
|
213
|
+
.array(Schema.Address)
|
|
214
|
+
.check(
|
|
215
|
+
z.describe('Tokens accepted by private deposits.'),
|
|
216
|
+
z.meta({ examples: [['0x20c000000000000000000000ff04042ee92fd449']] }),
|
|
217
|
+
),
|
|
218
|
+
name: z
|
|
219
|
+
.string()
|
|
220
|
+
.check(z.describe('Private Zone name.'), z.meta({ examples: ['zone-moderato-internal'] })),
|
|
221
|
+
outputTokens: z
|
|
222
|
+
.array(Schema.Address)
|
|
223
|
+
.check(
|
|
224
|
+
z.describe('Tokens returned by private redemptions.'),
|
|
225
|
+
z.meta({ examples: [['0x20c000000000000000000000ff04042ee92fd449']] }),
|
|
226
|
+
),
|
|
227
|
+
})
|
|
228
|
+
.check(z.describe('Verified Earn route through one private Zone.'))
|
|
229
|
+
|
|
177
230
|
const value = z.strictObject({
|
|
178
231
|
amount: Schema.DecimalString.check(
|
|
179
232
|
z.describe('Value in base units at `decimals` precision.'),
|
|
@@ -268,6 +321,23 @@ export namespace schema {
|
|
|
268
321
|
zone: z
|
|
269
322
|
.optional(z.nullable(zone))
|
|
270
323
|
.check(z.describe('Curated private Zone route, when requested, or null when absent.')),
|
|
324
|
+
zones: z.optional(z.array(zoneRoute)).check(
|
|
325
|
+
z.describe('Curated private Zone routes, when requested.'),
|
|
326
|
+
z.meta({
|
|
327
|
+
examples: [
|
|
328
|
+
[
|
|
329
|
+
{
|
|
330
|
+
chainId: 1424310001,
|
|
331
|
+
deploymentBlock: 31039238,
|
|
332
|
+
earnRouter: '0x9144086a79dea966d8bf1b52125ebed8919fc45c',
|
|
333
|
+
inputTokens: ['0x20c000000000000000000000ff04042ee92fd449'],
|
|
334
|
+
name: 'zone-moderato-internal',
|
|
335
|
+
outputTokens: ['0x20c000000000000000000000ff04042ee92fd449'],
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
],
|
|
339
|
+
}),
|
|
340
|
+
),
|
|
271
341
|
})
|
|
272
342
|
|
|
273
343
|
/** One compatible Earn vault resolved from current chain state. */
|
|
@@ -736,8 +806,8 @@ export function earn(options: earn.Options = {}) {
|
|
|
736
806
|
// as current-state rather than slow-changing metadata.
|
|
737
807
|
Cache.response<App.Environment>({
|
|
738
808
|
cacheControl: Cache.policies.state,
|
|
739
|
-
key: (c) =>
|
|
740
|
-
name: 'tempo-api:earn-vaults:
|
|
809
|
+
key: (c) => vaultCacheKey(c, schema.getEarnVaults.Query),
|
|
810
|
+
name: 'tempo-api:earn-vaults:v3',
|
|
741
811
|
}),
|
|
742
812
|
async (c) => {
|
|
743
813
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -780,8 +850,8 @@ export function earn(options: earn.Options = {}) {
|
|
|
780
850
|
}),
|
|
781
851
|
Cache.response<App.Environment>({
|
|
782
852
|
cacheControl: Cache.policies.state,
|
|
783
|
-
key: (c) =>
|
|
784
|
-
name: 'tempo-api:earn-vaults:
|
|
853
|
+
key: (c) => vaultCacheKey(c, schema.getVerifiedEarnVaults.Query),
|
|
854
|
+
name: 'tempo-api:earn-vaults:v3',
|
|
785
855
|
}),
|
|
786
856
|
async (c) => {
|
|
787
857
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -1114,8 +1184,8 @@ export function earn(options: earn.Options = {}) {
|
|
|
1114
1184
|
}),
|
|
1115
1185
|
Cache.response<App.Environment>({
|
|
1116
1186
|
cacheControl: Cache.policies.state,
|
|
1117
|
-
key: (c) =>
|
|
1118
|
-
name: 'tempo-api:earn-vaults:
|
|
1187
|
+
key: (c) => vaultCacheKey(c, schema.getEarnVault.Query),
|
|
1188
|
+
name: 'tempo-api:earn-vaults:v3',
|
|
1119
1189
|
}),
|
|
1120
1190
|
async (c) => {
|
|
1121
1191
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
@@ -2080,12 +2150,18 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
|
|
|
2080
2150
|
page.items.map(async (item) => {
|
|
2081
2151
|
const record = registry.get(item.vaultAddress.toLowerCase())
|
|
2082
2152
|
try {
|
|
2083
|
-
const
|
|
2153
|
+
const discovered = await resolveVaultDiscovery(c, {
|
|
2084
2154
|
chainId: options.chainId,
|
|
2085
2155
|
include: discoveryInclude(options),
|
|
2086
2156
|
vaultAddress: item.vaultAddress,
|
|
2087
2157
|
})
|
|
2088
|
-
|
|
2158
|
+
const { discovery, zoneRoutes } = await resolveVaultRoutes(c, {
|
|
2159
|
+
capability: options.capability,
|
|
2160
|
+
discovery: discovered,
|
|
2161
|
+
include,
|
|
2162
|
+
record,
|
|
2163
|
+
})
|
|
2164
|
+
return { discovery, position: item.position, record, zoneRoutes }
|
|
2089
2165
|
} catch (cause) {
|
|
2090
2166
|
if (!record && isIncompatible(cause)) return undefined
|
|
2091
2167
|
throw cause
|
|
@@ -2132,8 +2208,8 @@ export async function listVaults(c: Context<App.Environment>, options: listVault
|
|
|
2132
2208
|
])
|
|
2133
2209
|
for (const [vault, apy] of missingApy ?? []) apyByVault.set(vault, apy)
|
|
2134
2210
|
const apy = include.includes('apy') ? apyByVault : undefined
|
|
2135
|
-
const data =
|
|
2136
|
-
resolveVault(c, { ...match, apy, include, rates, snapshot, tokens }),
|
|
2211
|
+
const data = await Promise.all(
|
|
2212
|
+
page.map((match) => resolveVault(c, { ...match, apy, include, rates, snapshot, tokens })),
|
|
2137
2213
|
)
|
|
2138
2214
|
const last = matches[options.limit - 1]
|
|
2139
2215
|
const nextPosition =
|
|
@@ -2151,6 +2227,7 @@ export declare namespace listVaults {
|
|
|
2151
2227
|
discovery: EarnVaults.Discovery
|
|
2152
2228
|
position: Position
|
|
2153
2229
|
record?: RegistryRecord | undefined
|
|
2230
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
2154
2231
|
}
|
|
2155
2232
|
|
|
2156
2233
|
/** Options for listing compatible Earn vaults. */
|
|
@@ -2179,6 +2256,7 @@ export async function listVerifiedVaults(
|
|
|
2179
2256
|
const candidates = records.filter(
|
|
2180
2257
|
(record) => !cursor || record.vaultAddress.toLowerCase() > cursor,
|
|
2181
2258
|
)
|
|
2259
|
+
const include = vaultInclude(options)
|
|
2182
2260
|
const matches: listVerifiedVaults.Match[] = []
|
|
2183
2261
|
|
|
2184
2262
|
let offset = 0
|
|
@@ -2192,14 +2270,20 @@ export async function listVerifiedVaults(
|
|
|
2192
2270
|
const batch = candidates.slice(offset, offset + batchSize)
|
|
2193
2271
|
offset += batch.length
|
|
2194
2272
|
const discovered = await Promise.all(
|
|
2195
|
-
batch.map(async (record) =>
|
|
2196
|
-
|
|
2273
|
+
batch.map(async (record) => {
|
|
2274
|
+
const discovered = await resolveVaultDiscovery(c, {
|
|
2197
2275
|
chainId: options.chainId,
|
|
2198
2276
|
include: discoveryInclude(options),
|
|
2199
2277
|
vaultAddress: Schema.Address.parse(record.vaultAddress.toLowerCase()),
|
|
2200
|
-
})
|
|
2201
|
-
|
|
2202
|
-
|
|
2278
|
+
})
|
|
2279
|
+
const { discovery, zoneRoutes } = await resolveVaultRoutes(c, {
|
|
2280
|
+
capability: options.capability,
|
|
2281
|
+
discovery: discovered,
|
|
2282
|
+
include,
|
|
2283
|
+
record,
|
|
2284
|
+
})
|
|
2285
|
+
return { discovery, record, zoneRoutes }
|
|
2286
|
+
}),
|
|
2203
2287
|
)
|
|
2204
2288
|
for (const match of discovered) {
|
|
2205
2289
|
if (!matchesVaultFilters(match.discovery, options)) continue
|
|
@@ -2209,7 +2293,6 @@ export async function listVerifiedVaults(
|
|
|
2209
2293
|
|
|
2210
2294
|
const page = matches.slice(0, options.limit)
|
|
2211
2295
|
const discoveries = page.map(({ discovery }) => discovery)
|
|
2212
|
-
const include = vaultInclude(options)
|
|
2213
2296
|
const [apy, rates, tokens] = await Promise.all([
|
|
2214
2297
|
resolvePageApy(c, {
|
|
2215
2298
|
chainId: options.chainId,
|
|
@@ -2220,10 +2303,12 @@ export async function listVerifiedVaults(
|
|
|
2220
2303
|
resolvePageRates(c, { discoveries, include, oracle: options.oracle, snapshot }),
|
|
2221
2304
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
2222
2305
|
])
|
|
2223
|
-
const data =
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2306
|
+
const data = await Promise.all(
|
|
2307
|
+
page.map(async (match) =>
|
|
2308
|
+
Response.validated(
|
|
2309
|
+
schema.VerifiedVault,
|
|
2310
|
+
await resolveVault(c, { ...match, apy, include, rates, snapshot, tokens }),
|
|
2311
|
+
),
|
|
2227
2312
|
),
|
|
2228
2313
|
)
|
|
2229
2314
|
const last = matches[options.limit - 1]
|
|
@@ -2240,6 +2325,7 @@ export declare namespace listVerifiedVaults {
|
|
|
2240
2325
|
type Match = {
|
|
2241
2326
|
discovery: EarnVaults.Discovery
|
|
2242
2327
|
record: RegistryRecord
|
|
2328
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
2243
2329
|
}
|
|
2244
2330
|
|
|
2245
2331
|
/** Options for listing verified Earn vaults. */
|
|
@@ -2525,13 +2611,19 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
|
|
|
2525
2611
|
VerifiedTokens.snapshot(c, options.chainId),
|
|
2526
2612
|
])
|
|
2527
2613
|
try {
|
|
2528
|
-
const
|
|
2614
|
+
const discovered = await resolveVaultDiscovery(c, {
|
|
2529
2615
|
chainId: options.chainId,
|
|
2530
2616
|
include: discoveryInclude({ capability: [], include: options.include }),
|
|
2531
2617
|
vaultAddress: options.vaultAddress,
|
|
2532
2618
|
})
|
|
2533
|
-
const discoveries = [discovery]
|
|
2534
2619
|
const include = vaultInclude(options)
|
|
2620
|
+
const { discovery, zoneRoutes } = await resolveVaultRoutes(c, {
|
|
2621
|
+
capability: [],
|
|
2622
|
+
discovery: discovered,
|
|
2623
|
+
include,
|
|
2624
|
+
record,
|
|
2625
|
+
})
|
|
2626
|
+
const discoveries = [discovery]
|
|
2535
2627
|
const [apy, rates, tokens] = await Promise.all([
|
|
2536
2628
|
resolvePageApy(c, {
|
|
2537
2629
|
chainId: options.chainId,
|
|
@@ -2543,7 +2635,7 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
|
|
|
2543
2635
|
resolvePageTokens(c, { chainId: options.chainId, discoveries, include, snapshot }),
|
|
2544
2636
|
])
|
|
2545
2637
|
return {
|
|
2546
|
-
...resolveVault(c, {
|
|
2638
|
+
...(await resolveVault(c, {
|
|
2547
2639
|
apy,
|
|
2548
2640
|
discovery,
|
|
2549
2641
|
include,
|
|
@@ -2551,7 +2643,8 @@ export async function getVault(c: Context<App.Environment>, options: getVault.Op
|
|
|
2551
2643
|
record,
|
|
2552
2644
|
snapshot,
|
|
2553
2645
|
tokens,
|
|
2554
|
-
|
|
2646
|
+
zoneRoutes,
|
|
2647
|
+
})),
|
|
2555
2648
|
...(rates ? { meta: { valuation: Valuation.pricing(rates, options.oracle) } } : {}),
|
|
2556
2649
|
}
|
|
2557
2650
|
} catch (cause) {
|
|
@@ -2586,6 +2679,24 @@ declare namespace vaultInclude {
|
|
|
2586
2679
|
type Options = Pick<z.output<typeof schema.getEarnVault.Query>, 'apy.window' | 'include'>
|
|
2587
2680
|
}
|
|
2588
2681
|
|
|
2682
|
+
/** Builds an Earn-vault cache key partitioned by Zone-visible API keys. */
|
|
2683
|
+
export function vaultCacheKey<const query extends z.ZodMiniType>(
|
|
2684
|
+
c: Context<App.Environment>,
|
|
2685
|
+
query: query,
|
|
2686
|
+
): string {
|
|
2687
|
+
const key = Cache.urlKey(c, query)
|
|
2688
|
+
const url = new URL(key)
|
|
2689
|
+
const includesRoutes = url.searchParams
|
|
2690
|
+
.getAll('include')
|
|
2691
|
+
.some((include) => include === 'zone' || include === 'zones')
|
|
2692
|
+
if (!includesRoutes) return key
|
|
2693
|
+
|
|
2694
|
+
const principal = Auth.getPrincipal(c)
|
|
2695
|
+
if (principal?.type !== 'api_key') return key
|
|
2696
|
+
url.searchParams.set('principal', `${principal.type}:${principal.id}`)
|
|
2697
|
+
return url.toString()
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2589
2700
|
function discoveryInclude(
|
|
2590
2701
|
options: discoveryInclude.Options,
|
|
2591
2702
|
): readonly EarnVaults.resolve.Include[] {
|
|
@@ -2638,6 +2749,60 @@ declare namespace resolveVaultDiscovery {
|
|
|
2638
2749
|
}
|
|
2639
2750
|
}
|
|
2640
2751
|
|
|
2752
|
+
async function resolveVaultRoutes(
|
|
2753
|
+
c: Context<App.Environment>,
|
|
2754
|
+
options: resolveVaultRoutes.Options,
|
|
2755
|
+
): Promise<resolveVaultRoutes.Result> {
|
|
2756
|
+
const { discovery, record } = options
|
|
2757
|
+
if (!record || record.zones.length === 0) return { discovery, zoneRoutes: [] }
|
|
2758
|
+
|
|
2759
|
+
const principal = Auth.getPrincipal(c)
|
|
2760
|
+
const scopes = principal?.type === 'api_key' ? principal.apiKey.scopes : undefined
|
|
2761
|
+
const includesRoutes = options.include.includes('zone') || options.include.includes('zones')
|
|
2762
|
+
const needsCapabilities =
|
|
2763
|
+
options.include.includes('capabilities') ||
|
|
2764
|
+
options.capability.includes('privateRouting') ||
|
|
2765
|
+
options.capability.includes('routerSwaps')
|
|
2766
|
+
const visibleRoutes = record.zones.filter((route) =>
|
|
2767
|
+
hasZoneAccess({ chainId: route.chainId, scopes }),
|
|
2768
|
+
)
|
|
2769
|
+
// Capabilities describe the vault; API-key scopes limit only the route metadata.
|
|
2770
|
+
const routes = needsCapabilities ? record.zones : includesRoutes ? visibleRoutes : []
|
|
2771
|
+
if (routes.length === 0) return { discovery, zoneRoutes: [] }
|
|
2772
|
+
|
|
2773
|
+
const resolved = await EarnVaults.resolveZoneRoutes({
|
|
2774
|
+
discovery,
|
|
2775
|
+
getClient: c.get('getClient'),
|
|
2776
|
+
routes,
|
|
2777
|
+
zones: [...c.get('zones').values()],
|
|
2778
|
+
})
|
|
2779
|
+
const capabilities = discovery.capabilities
|
|
2780
|
+
if (needsCapabilities && !capabilities)
|
|
2781
|
+
throw new Error('Earn vault capabilities were not resolved.')
|
|
2782
|
+
return {
|
|
2783
|
+
discovery: capabilities
|
|
2784
|
+
? { ...discovery, capabilities: EarnVaults.addZoneRouteCapabilities(capabilities) }
|
|
2785
|
+
: discovery,
|
|
2786
|
+
zoneRoutes: includesRoutes
|
|
2787
|
+
? resolved.filter((route) => hasZoneAccess({ chainId: route.chainId, scopes }))
|
|
2788
|
+
: [],
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
declare namespace resolveVaultRoutes {
|
|
2793
|
+
type Options = {
|
|
2794
|
+
capability: z.output<typeof schema.getEarnVaults.Query>['capability']
|
|
2795
|
+
discovery: EarnVaults.Discovery
|
|
2796
|
+
include: z.output<typeof schema.getEarnVault.Query>['include']
|
|
2797
|
+
record?: RegistryRecord | undefined
|
|
2798
|
+
}
|
|
2799
|
+
|
|
2800
|
+
type Result = {
|
|
2801
|
+
discovery: EarnVaults.Discovery
|
|
2802
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2641
2806
|
// Measuring a rate costs indexer boundary queries plus historical quotes against
|
|
2642
2807
|
// an archive node, so an unrequested rate reaches neither.
|
|
2643
2808
|
function resolvePageApy(c: Context<App.Environment>, options: resolvePageApy.Options) {
|
|
@@ -2718,8 +2883,13 @@ declare namespace resolvePageTokens {
|
|
|
2718
2883
|
}
|
|
2719
2884
|
}
|
|
2720
2885
|
|
|
2721
|
-
function resolveVault(c: Context<App.Environment>, options: resolveVault.Options) {
|
|
2886
|
+
async function resolveVault(c: Context<App.Environment>, options: resolveVault.Options) {
|
|
2722
2887
|
const { discovery, record } = options
|
|
2888
|
+
const principal = Auth.getPrincipal(c)
|
|
2889
|
+
const scopes = principal?.type === 'api_key' ? principal.apiKey.scopes : undefined
|
|
2890
|
+
const zones = [...c.get('zones').values()].filter((zone) =>
|
|
2891
|
+
hasZoneAccess({ chainId: zone.id, scopes }),
|
|
2892
|
+
)
|
|
2723
2893
|
const valued = options.include.includes('tvl')
|
|
2724
2894
|
? Valuation.valuationFor({
|
|
2725
2895
|
amount: BigInt(discovery.state.totalAssets),
|
|
@@ -2743,7 +2913,8 @@ function resolveVault(c: Context<App.Environment>, options: resolveVault.Options
|
|
|
2743
2913
|
formatted: valued.amount,
|
|
2744
2914
|
}
|
|
2745
2915
|
: null,
|
|
2746
|
-
|
|
2916
|
+
zoneRoutes: options.zoneRoutes,
|
|
2917
|
+
zones,
|
|
2747
2918
|
})
|
|
2748
2919
|
}
|
|
2749
2920
|
|
|
@@ -2756,6 +2927,7 @@ declare namespace resolveVault {
|
|
|
2756
2927
|
record?: RegistryRecord | undefined
|
|
2757
2928
|
snapshot: VerifiedTokens.Snapshot
|
|
2758
2929
|
tokens: Tokens.resolveTokens.ReturnType
|
|
2930
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
2759
2931
|
}
|
|
2760
2932
|
}
|
|
2761
2933
|
|
|
@@ -2797,8 +2969,18 @@ export function serializeVault(options: serializeVault.Options): z.output<typeof
|
|
|
2797
2969
|
vaultAddress,
|
|
2798
2970
|
verified: record !== undefined,
|
|
2799
2971
|
...(options.include.includes('zone')
|
|
2800
|
-
? {
|
|
2972
|
+
? {
|
|
2973
|
+
zone: record
|
|
2974
|
+
? resolveZone({
|
|
2975
|
+
discovery,
|
|
2976
|
+
record,
|
|
2977
|
+
zoneRoutes: options.zoneRoutes,
|
|
2978
|
+
zones: options.zones,
|
|
2979
|
+
})
|
|
2980
|
+
: null,
|
|
2981
|
+
}
|
|
2801
2982
|
: {}),
|
|
2983
|
+
...(options.include.includes('zones') ? { zones: record ? options.zoneRoutes : [] } : {}),
|
|
2802
2984
|
})
|
|
2803
2985
|
}
|
|
2804
2986
|
|
|
@@ -2819,12 +3001,24 @@ export declare namespace serializeVault {
|
|
|
2819
3001
|
shareToken: z.output<typeof Tokens.schema.Token>
|
|
2820
3002
|
/** USD value of the assets, or null when unpriced; omitted unless `include` carries `tvl`. */
|
|
2821
3003
|
tvl: z.output<typeof schema.Vault>['tvl']
|
|
3004
|
+
/** Verified Zone routes with immutable router bindings. */
|
|
3005
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
2822
3006
|
/** Private Zones available to the vault. */
|
|
2823
3007
|
zones: readonly Chain[]
|
|
2824
3008
|
}
|
|
2825
3009
|
}
|
|
2826
3010
|
|
|
2827
3011
|
function resolveZone(options: resolveZone.Options): z.output<typeof schema.Vault.shape.zone> {
|
|
3012
|
+
if (options.record.zones.length > 0) {
|
|
3013
|
+
if (options.zoneRoutes.length !== 1) return null
|
|
3014
|
+
const route = options.zoneRoutes[0]!
|
|
3015
|
+
return {
|
|
3016
|
+
chainId: route.chainId,
|
|
3017
|
+
inputTokens: [...route.inputTokens],
|
|
3018
|
+
name: route.name,
|
|
3019
|
+
outputTokens: [...route.outputTokens],
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
2828
3022
|
if (!options.discovery.capabilities?.privateRouting) return null
|
|
2829
3023
|
const hasInputs = options.record.privateInputTokens.length > 0
|
|
2830
3024
|
const hasOutputs = options.record.privateOutputTokens.length > 0
|
|
@@ -2833,6 +3027,7 @@ function resolveZone(options: resolveZone.Options): z.output<typeof schema.Vault
|
|
|
2833
3027
|
throw new Error('Private input and output tokens must both be configured.')
|
|
2834
3028
|
|
|
2835
3029
|
const configured = options.zones.filter((zone) => zone.sourceId === options.record.chainId)
|
|
3030
|
+
if (configured.length === 0) return null
|
|
2836
3031
|
if (configured.length !== 1)
|
|
2837
3032
|
throw new Error(`Expected one Earn Zone for chain ${options.record.chainId}.`)
|
|
2838
3033
|
const zone = configured[0]!
|
|
@@ -2852,6 +3047,7 @@ declare namespace resolveZone {
|
|
|
2852
3047
|
type Options = {
|
|
2853
3048
|
discovery: EarnVaults.Discovery
|
|
2854
3049
|
record: RegistryRecord
|
|
3050
|
+
zoneRoutes: readonly EarnVaults.ResolvedZoneRoute[]
|
|
2855
3051
|
zones: readonly Chain[]
|
|
2856
3052
|
}
|
|
2857
3053
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
|
|
3
|
+
import * as Earn from './earn.js'
|
|
4
|
+
|
|
5
|
+
describe('hasZoneAccess', () => {
|
|
6
|
+
test('matches every Zone granted by read or wildcard scopes', () => {
|
|
7
|
+
const scopes = ['data:read', 'zone:1424310001:read', 'zone:1424310003:write']
|
|
8
|
+
const visible = [1424310001, 1424310002, 1424310003].filter((chainId) =>
|
|
9
|
+
Earn.hasZoneAccess({ chainId, scopes }),
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
expect(visible).toStrictEqual([1424310001])
|
|
13
|
+
expect(Earn.hasZoneAccess({ chainId: 1424310002, scopes: ['*'] })).toBe(true)
|
|
14
|
+
expect(Earn.hasZoneAccess({ chainId: 1424310003, scopes })).toBe(false)
|
|
15
|
+
expect(Earn.hasZoneAccess({ chainId: 1424310001 })).toBe(false)
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe('vaultCacheKey', () => {
|
|
20
|
+
test('partitions Zone projections by API key after query credentials are stripped', async () => {
|
|
21
|
+
const app = new Hono()
|
|
22
|
+
app.use('*', async (c, next) => {
|
|
23
|
+
c.set('chainId' as never, 42_431 as never)
|
|
24
|
+
const principal = c.req.header('x-principal')
|
|
25
|
+
if (principal) c.set('principal' as never, { id: principal, type: 'api_key' } as never)
|
|
26
|
+
await next()
|
|
27
|
+
})
|
|
28
|
+
app.get('/', (c) => {
|
|
29
|
+
return c.text(Earn.vaultCacheKey(c as never, Earn.schema.getEarnVault.Query))
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const [first, second, public_, unscoped] = await Promise.all([
|
|
33
|
+
app.request('/?include=zones', { headers: { 'x-principal': 'key_1' } }),
|
|
34
|
+
app.request('/?include=zones', { headers: { 'x-principal': 'key_2' } }),
|
|
35
|
+
app.request('/?include=zones'),
|
|
36
|
+
app.request('/', { headers: { 'x-principal': 'key_1' } }),
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
expect([
|
|
40
|
+
new URL(await first.text()).searchParams.get('principal'),
|
|
41
|
+
new URL(await second.text()).searchParams.get('principal'),
|
|
42
|
+
new URL(await public_.text()).searchParams.get('principal'),
|
|
43
|
+
new URL(await unscoped.text()).searchParams.get('principal'),
|
|
44
|
+
]).toStrictEqual(['api_key:key_1', 'api_key:key_2', null, null])
|
|
45
|
+
})
|
|
46
|
+
})
|
|
@@ -845,7 +845,37 @@ describe('GET /exchange/swaps', () => {
|
|
|
845
845
|
}, 60000)
|
|
846
846
|
})
|
|
847
847
|
|
|
848
|
-
describe('POST /exchange/quotes', () => {
|
|
848
|
+
describe('POST and QUERY /exchange/quotes', () => {
|
|
849
|
+
test('POST and QUERY accept the same body and return equivalent quote errors', async () => {
|
|
850
|
+
const client = TestApp.client()
|
|
851
|
+
const destinationToken = Schema.TokenAddress.parse(Addresses.pathUsd)
|
|
852
|
+
const request = {
|
|
853
|
+
json: {
|
|
854
|
+
account: Relay.accounts[1]!.address,
|
|
855
|
+
amount: (2n ** 128n).toString(),
|
|
856
|
+
destinationToken,
|
|
857
|
+
mode: 'exactSource' as const,
|
|
858
|
+
slippageBps: 50,
|
|
859
|
+
sourceToken: '0x20c0000000000000000000008f5425160ebe5525' as const,
|
|
860
|
+
},
|
|
861
|
+
query: {},
|
|
862
|
+
}
|
|
863
|
+
const [post, query] = await Promise.all([
|
|
864
|
+
client.v1.exchange.quotes.$post(request, TestApp.auth),
|
|
865
|
+
client.v1.exchange.quotes.$query(request, TestApp.auth),
|
|
866
|
+
])
|
|
867
|
+
|
|
868
|
+
expect([post.status, query.status]).toEqual([404, 404])
|
|
869
|
+
expect([post.headers.get('cache-control'), query.headers.get('cache-control')]).toEqual([
|
|
870
|
+
'no-store',
|
|
871
|
+
'no-store',
|
|
872
|
+
])
|
|
873
|
+
expect([await post.json(), await query.json()]).toMatchObject([
|
|
874
|
+
{ error: { code: 'quote_not_available' } },
|
|
875
|
+
{ error: { code: 'quote_not_available' } },
|
|
876
|
+
])
|
|
877
|
+
})
|
|
878
|
+
|
|
849
879
|
test('validates denominations without verification data', async () => {
|
|
850
880
|
const db = () =>
|
|
851
881
|
Db.postgres({ connectionString: 'postgresql://postgres:postgres@127.0.0.1:1/none' })
|
|
@@ -191,17 +191,17 @@ export namespace schema {
|
|
|
191
191
|
*/
|
|
192
192
|
export const PairToken = Schema.describe(
|
|
193
193
|
z.object({
|
|
194
|
-
address: Schema.
|
|
194
|
+
address: Schema.tokenAddress(Tokens.tokenExample.address).check(
|
|
195
195
|
z.describe(
|
|
196
196
|
'TIP-20 token contract address — the `0x`-prefixed 20-byte identifier for this token.',
|
|
197
197
|
),
|
|
198
|
-
z.meta({ examples: [
|
|
198
|
+
z.meta({ examples: [Tokens.tokenExample.address] }),
|
|
199
199
|
),
|
|
200
200
|
currency: z
|
|
201
201
|
.optional(z.string())
|
|
202
202
|
.check(
|
|
203
203
|
z.describe('Human-readable currency code for the token, when known.'),
|
|
204
|
-
z.meta({ examples: [
|
|
204
|
+
z.meta({ examples: [Tokens.tokenExample.currency] }),
|
|
205
205
|
),
|
|
206
206
|
decimals: z
|
|
207
207
|
.optional(z.number().check(z.int(), z.nonnegative()))
|
|
@@ -209,27 +209,25 @@ export namespace schema {
|
|
|
209
209
|
z.describe(
|
|
210
210
|
'Number of decimal places the token uses; stablecoins on Tempo typically use 6.',
|
|
211
211
|
),
|
|
212
|
-
z.meta({ examples: [
|
|
212
|
+
z.meta({ examples: [Tokens.tokenExample.decimals] }),
|
|
213
213
|
),
|
|
214
214
|
logoUri: z.optional(z.string()).check(
|
|
215
|
-
z.describe('URL for the token logo
|
|
215
|
+
z.describe('URL for the token logo image, when one is available.'),
|
|
216
216
|
z.meta({
|
|
217
|
-
examples: [
|
|
218
|
-
'https://api.tempo.xyz/data/4217/icons/0x20c0000000000000000000008f5425160ebe5525.svg',
|
|
219
|
-
],
|
|
217
|
+
examples: [Tokens.tokenExample.logoUri],
|
|
220
218
|
}),
|
|
221
219
|
),
|
|
222
220
|
name: z
|
|
223
221
|
.optional(z.string())
|
|
224
222
|
.check(
|
|
225
223
|
z.describe('Human-readable token name, such as `USD Coin`.'),
|
|
226
|
-
z.meta({ examples: [
|
|
224
|
+
z.meta({ examples: [Tokens.tokenExample.name] }),
|
|
227
225
|
),
|
|
228
226
|
symbol: z
|
|
229
227
|
.optional(z.string())
|
|
230
228
|
.check(
|
|
231
229
|
z.describe('Short token ticker symbol, such as `USDC`.'),
|
|
232
|
-
z.meta({ examples: [
|
|
230
|
+
z.meta({ examples: [Tokens.tokenExample.symbol] }),
|
|
233
231
|
),
|
|
234
232
|
verified: z
|
|
235
233
|
.optional(z.boolean())
|
|
@@ -1719,9 +1717,15 @@ export namespace schema {
|
|
|
1719
1717
|
export function exchanges(options: exchanges.Options = {}) {
|
|
1720
1718
|
const oracle = options.fx?.oracle ?? FxOracle.ecb()
|
|
1721
1719
|
return new Hono<App.Environment>()
|
|
1722
|
-
.
|
|
1720
|
+
.on(
|
|
1721
|
+
['POST', 'QUERY'],
|
|
1723
1722
|
'/v1/exchange/quotes',
|
|
1724
|
-
Auth.policy({
|
|
1723
|
+
Auth.policy({
|
|
1724
|
+
apiKey: { scopes: ['data:read'] },
|
|
1725
|
+
inheritOverridesFrom: 'POST',
|
|
1726
|
+
mpp: true,
|
|
1727
|
+
public: true,
|
|
1728
|
+
}),
|
|
1725
1729
|
OpenApi.validate('query', schema.createQuote.Query, {
|
|
1726
1730
|
code: 'query_invalid',
|
|
1727
1731
|
message: 'Invalid query parameters',
|
|
@@ -2411,7 +2415,7 @@ export function exchanges(options: exchanges.Options = {}) {
|
|
|
2411
2415
|
200,
|
|
2412
2416
|
)
|
|
2413
2417
|
} catch (cause) {
|
|
2414
|
-
return Response.upstream(c, cause)
|
|
2418
|
+
return Response.upstream(c, cause, { page: options.page })
|
|
2415
2419
|
}
|
|
2416
2420
|
},
|
|
2417
2421
|
)
|
|
@@ -2633,7 +2637,7 @@ export function exchanges(options: exchanges.Options = {}) {
|
|
|
2633
2637
|
200,
|
|
2634
2638
|
)
|
|
2635
2639
|
} catch (cause) {
|
|
2636
|
-
return Response.upstream(c, cause)
|
|
2640
|
+
return Response.upstream(c, cause, { page: options.page })
|
|
2637
2641
|
}
|
|
2638
2642
|
},
|
|
2639
2643
|
)
|
|
@@ -2831,7 +2835,7 @@ export function exchanges(options: exchanges.Options = {}) {
|
|
|
2831
2835
|
200,
|
|
2832
2836
|
)
|
|
2833
2837
|
} catch (cause) {
|
|
2834
|
-
return Response.upstream(c, cause)
|
|
2838
|
+
return Response.upstream(c, cause, { page: options.page })
|
|
2835
2839
|
}
|
|
2836
2840
|
},
|
|
2837
2841
|
)
|