tapimo 0.11.0 → 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 +2296 -1010
- 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/admin/App.d.ts +53 -4
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +4 -4
- package/dist/admin/apps/earn-vaults.d.ts +114 -0
- 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.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 +9 -9
- 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 +1699 -749
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +56 -7
- 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 +2367 -4
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +368 -87
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +471 -340
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +28 -28
- 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 +4 -4
- package/dist/apps/data/routes/blocks.js +1 -1
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/earn.d.ts +131 -6
- 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 +825 -119
- 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.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/indexer.d.ts +34 -34
- package/dist/apps/data/routes/receipts.d.ts +230 -230
- 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.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 +14 -0
- 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.js +1 -1
- package/dist/apps/data/routes/transactions.js.map +1 -1
- 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/webhooks.d.ts +4 -4
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +2 -2
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +30 -30
- 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 +16 -16
- 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 +13 -13
- 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/management/App.d.ts +627 -293
- 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 +114 -54
- 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 +33 -33
- 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 +86 -41
- 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 +93 -72
- 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 +90 -28
- 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 +78 -78
- 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 +147 -130
- package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/management/routes/webhooks.js +80 -35
- 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 +40 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +23 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +19 -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 +14 -20
- package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
- package/dist/db/tables/webhookQueueEvents.js +68 -47
- package/dist/db/tables/webhookQueueEvents.js.map +1 -1
- package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
- package/dist/db/tables/webhookSubscriptions.js +29 -5
- 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/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 +5 -7
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +6 -7
- 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/Webhooks.d.ts +29 -12
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +37 -20
- 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/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/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/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 +4 -2
- package/src/Assets.test.ts +18 -0
- package/src/Assets.ts +22 -0
- package/src/Client.test-d.ts +265 -16
- 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 +56 -8
- 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 +328 -1
- package/src/apps/data/routes/activities.ts +498 -93
- 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.ts +6 -2
- 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 +234 -0
- package/src/apps/management/routes/webhooks.ts +191 -78
- package/src/apps/mpp/internal/Adapter.ts +13 -1
- package/src/db/Db.test.ts +41 -0
- package/src/db/Db.ts +62 -0
- package/src/db/Schema.ts +28 -3
- package/src/db/tables/earnVaults.test.ts +22 -0
- package/src/db/tables/earnVaults.ts +11 -1
- package/src/db/tables/webhookDeliveries.ts +13 -0
- package/src/db/tables/webhookQueueCompletions.ts +55 -0
- package/src/db/tables/webhookQueueEvents.ts +95 -61
- package/src/db/tables/webhookSubscriptions.ts +45 -6
- 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/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 +16 -0
- package/src/internal/Schema.ts +7 -7
- 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/Webhooks.test.ts +122 -8
- package/src/internal/Webhooks.ts +59 -29
- package/src/internal/funding/Deposit.ts +71 -64
- package/src/internal/funding/DepositAddress.ts +50 -43
- package/src/internal/funding/Provider.ts +164 -142
- package/src/internal/funding/providers/index.test.ts +185 -0
- package/src/internal/funding/providers/stargate.ts +184 -0
- package/src/providers/index.test.ts +1 -0
- package/src/providers/index.ts +9 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZoneId } from 'ox/tempo'
|
|
1
2
|
import {
|
|
2
3
|
ContractFunctionExecutionError,
|
|
3
4
|
ContractFunctionRevertedError,
|
|
@@ -161,6 +162,28 @@ export namespace schema {
|
|
|
161
162
|
})
|
|
162
163
|
.check(z.describe('Onchain identity of an Earn vault.'))
|
|
163
164
|
|
|
165
|
+
/** Schema for one curated Earn route through a private Zone. */
|
|
166
|
+
export const ZoneRoute = z
|
|
167
|
+
.strictObject({
|
|
168
|
+
chainId: Schema.ChainId.check(
|
|
169
|
+
z.describe('Private Zone chain id.'),
|
|
170
|
+
z.meta({ examples: [1424310001] }),
|
|
171
|
+
),
|
|
172
|
+
deploymentBlock: z
|
|
173
|
+
.number()
|
|
174
|
+
.check(
|
|
175
|
+
z.int(),
|
|
176
|
+
z.nonnegative(),
|
|
177
|
+
z.describe('Parent-chain block that deployed the Earn router.'),
|
|
178
|
+
z.meta({ examples: [31039238] }),
|
|
179
|
+
),
|
|
180
|
+
earnRouter: Schema.Address.check(
|
|
181
|
+
z.describe('Parent-chain router for this Zone and Earn vault.'),
|
|
182
|
+
z.meta({ examples: ['0x9144086a79dea966d8bf1b52125ebed8919fc45c'] }),
|
|
183
|
+
),
|
|
184
|
+
})
|
|
185
|
+
.check(z.describe('Curated Earn route through one private Zone.'))
|
|
186
|
+
|
|
164
187
|
/** Schema for live state resolved from one Earn vault. */
|
|
165
188
|
export const Discovery = z
|
|
166
189
|
.strictObject({
|
|
@@ -228,12 +251,48 @@ export type Discovery = z.output<typeof schema.Discovery>
|
|
|
228
251
|
/** Onchain identity of an Earn vault. */
|
|
229
252
|
export type ResolveInput = z.output<typeof schema.ResolveInput>
|
|
230
253
|
|
|
254
|
+
/** Curated Earn route through one private Zone. */
|
|
255
|
+
export type ZoneRoute = z.output<typeof schema.ZoneRoute>
|
|
256
|
+
|
|
257
|
+
/** Curated Zone route with immutable router bindings resolved onchain. */
|
|
258
|
+
export type ResolvedZoneRoute = ZoneRoute & {
|
|
259
|
+
/** Tokens accepted by private deposits. */
|
|
260
|
+
inputTokens: readonly Address[]
|
|
261
|
+
/** Configured private Zone name. */
|
|
262
|
+
name: string
|
|
263
|
+
/** Tokens returned by private redemptions. */
|
|
264
|
+
outputTokens: readonly Address[]
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Adds capabilities proven by a verified private Zone route. */
|
|
268
|
+
export function addZoneRouteCapabilities(
|
|
269
|
+
capabilities: NonNullable<Discovery['capabilities']>,
|
|
270
|
+
): NonNullable<Discovery['capabilities']> {
|
|
271
|
+
return { ...capabilities, privateRouting: true, routerSwaps: true }
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Derives a Zone ID from any supported Zone chain-ID scheme. */
|
|
275
|
+
export function deriveZoneId(chainId: number): number {
|
|
276
|
+
for (const sourceId of [4_217, 42_431] satisfies readonly ZoneId.SourceId[]) {
|
|
277
|
+
const zoneId = ZoneId.fromChainId(chainId, sourceId)
|
|
278
|
+
if (zoneId >= 0 && ZoneId.toChainId(zoneId, sourceId) === chainId) return zoneId
|
|
279
|
+
}
|
|
280
|
+
throw new InvalidRegistryError(`Chain ${chainId} does not use a supported Zone chain-ID scheme.`)
|
|
281
|
+
}
|
|
282
|
+
|
|
231
283
|
/** Stable code describing an onchain verification issue. */
|
|
232
284
|
export type VerificationIssueCode =
|
|
233
285
|
| 'chain-mismatch'
|
|
234
286
|
| 'engine-asset-mismatch'
|
|
235
287
|
| 'policy-unsupported'
|
|
236
288
|
| 'read-failed'
|
|
289
|
+
| 'zone-deployment-block-mismatch'
|
|
290
|
+
| 'zone-flow-unsupported'
|
|
291
|
+
| 'zone-id-mismatch'
|
|
292
|
+
| 'zone-router-invalid'
|
|
293
|
+
| 'zone-share-mismatch'
|
|
294
|
+
| 'zone-vault-asset-mismatch'
|
|
295
|
+
| 'zone-vault-mismatch'
|
|
237
296
|
|
|
238
297
|
/** One onchain verification issue. */
|
|
239
298
|
export type VerificationIssue = {
|
|
@@ -303,6 +362,16 @@ type RouterCapabilities = {
|
|
|
303
362
|
redeem: boolean
|
|
304
363
|
}
|
|
305
364
|
|
|
365
|
+
type ZoneRouteBindings = {
|
|
366
|
+
allowedZoneId: number
|
|
367
|
+
deposit: boolean
|
|
368
|
+
earnShare: Address
|
|
369
|
+
earnVault: Address
|
|
370
|
+
privateAsset: Address
|
|
371
|
+
redeem: boolean
|
|
372
|
+
vaultAsset: Address
|
|
373
|
+
}
|
|
374
|
+
|
|
306
375
|
type TokenMetadata = Omit<Discovery['assetToken'], 'address'>
|
|
307
376
|
|
|
308
377
|
const engineBindingsAbi = parseAbi(['function vault() view returns (address)'])
|
|
@@ -363,6 +432,139 @@ export declare namespace resolve {
|
|
|
363
432
|
}
|
|
364
433
|
}
|
|
365
434
|
|
|
435
|
+
/** Resolves and verifies every curated Zone route for one Earn vault. */
|
|
436
|
+
export async function resolveZoneRoutes(
|
|
437
|
+
options: resolveZoneRoutes.Options,
|
|
438
|
+
): Promise<ResolvedZoneRoute[]> {
|
|
439
|
+
const result = z.array(schema.ZoneRoute).safeParse(options.routes)
|
|
440
|
+
if (!result.success) throw invalid(result.error)
|
|
441
|
+
|
|
442
|
+
const chainIds = new Set<number>()
|
|
443
|
+
const routers = new Set<string>()
|
|
444
|
+
for (const route of result.data) {
|
|
445
|
+
if (chainIds.has(route.chainId))
|
|
446
|
+
throw new InvalidRegistryError(`Zone ${route.chainId} is configured more than once.`)
|
|
447
|
+
if (routers.has(route.earnRouter))
|
|
448
|
+
throw new InvalidRegistryError(
|
|
449
|
+
`Earn router ${route.earnRouter} is configured more than once.`,
|
|
450
|
+
)
|
|
451
|
+
chainIds.add(route.chainId)
|
|
452
|
+
routers.add(route.earnRouter)
|
|
453
|
+
}
|
|
454
|
+
if (result.data.length === 0) return []
|
|
455
|
+
|
|
456
|
+
const client = options.getClient(options.discovery.chainId)
|
|
457
|
+
return Promise.all(
|
|
458
|
+
result.data.map(async (route) => {
|
|
459
|
+
const zone = options.zones.find((candidate) => candidate.id === route.chainId)
|
|
460
|
+
if (!zone) throw new InvalidRegistryError(`Zone ${route.chainId} is not configured.`)
|
|
461
|
+
if (zone.sourceId !== options.discovery.chainId)
|
|
462
|
+
throw new InvalidRegistryError(
|
|
463
|
+
`Zone ${route.chainId} does not belong to chain ${options.discovery.chainId}.`,
|
|
464
|
+
)
|
|
465
|
+
const expectedZoneId = deriveZoneId(route.chainId)
|
|
466
|
+
|
|
467
|
+
const [code, previousCode] = await Promise.all([
|
|
468
|
+
client.getCode({
|
|
469
|
+
address: route.earnRouter,
|
|
470
|
+
blockNumber: BigInt(route.deploymentBlock),
|
|
471
|
+
}),
|
|
472
|
+
route.deploymentBlock === 0
|
|
473
|
+
? undefined
|
|
474
|
+
: client.getCode({
|
|
475
|
+
address: route.earnRouter,
|
|
476
|
+
blockNumber: BigInt(route.deploymentBlock - 1),
|
|
477
|
+
}),
|
|
478
|
+
])
|
|
479
|
+
if (!code || code === '0x' || (previousCode !== undefined && previousCode !== '0x'))
|
|
480
|
+
throw mismatch({
|
|
481
|
+
discovery: options.discovery,
|
|
482
|
+
issues: [
|
|
483
|
+
{
|
|
484
|
+
actual: String(route.deploymentBlock),
|
|
485
|
+
code: 'zone-deployment-block-mismatch',
|
|
486
|
+
message: 'Earn router deployment block does not match its code boundary.',
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
const bindings = await readZoneRouteBindings(client, { earnRouter: route.earnRouter }).catch(
|
|
492
|
+
(error) => {
|
|
493
|
+
if (!isMissingOptionalFunctionError(error)) throw error
|
|
494
|
+
throw mismatch({
|
|
495
|
+
discovery: options.discovery,
|
|
496
|
+
issues: [
|
|
497
|
+
{
|
|
498
|
+
actual: route.earnRouter,
|
|
499
|
+
code: 'zone-router-invalid',
|
|
500
|
+
message: 'Earn router does not expose the required immutable bindings.',
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
})
|
|
504
|
+
},
|
|
505
|
+
)
|
|
506
|
+
const issues: VerificationIssue[] = []
|
|
507
|
+
if (bindings.allowedZoneId !== expectedZoneId)
|
|
508
|
+
issues.push({
|
|
509
|
+
actual: bindings.allowedZoneId.toString(),
|
|
510
|
+
code: 'zone-id-mismatch',
|
|
511
|
+
expected: String(expectedZoneId),
|
|
512
|
+
message: 'Earn router is configured for a different Zone.',
|
|
513
|
+
})
|
|
514
|
+
compareAddress(
|
|
515
|
+
issues,
|
|
516
|
+
'zone-vault-mismatch',
|
|
517
|
+
'Earn router is configured for a different Earn vault.',
|
|
518
|
+
options.discovery.vaultAddress,
|
|
519
|
+
bindings.earnVault,
|
|
520
|
+
)
|
|
521
|
+
compareAddress(
|
|
522
|
+
issues,
|
|
523
|
+
'zone-vault-asset-mismatch',
|
|
524
|
+
'Earn router vault asset does not match the Earn vault.',
|
|
525
|
+
options.discovery.assetToken.address,
|
|
526
|
+
bindings.vaultAsset,
|
|
527
|
+
)
|
|
528
|
+
compareAddress(
|
|
529
|
+
issues,
|
|
530
|
+
'zone-share-mismatch',
|
|
531
|
+
'Earn router share token does not match the Earn vault.',
|
|
532
|
+
options.discovery.shareToken.address,
|
|
533
|
+
bindings.earnShare,
|
|
534
|
+
)
|
|
535
|
+
if (!bindings.deposit || !bindings.redeem)
|
|
536
|
+
issues.push({
|
|
537
|
+
actual: `deposit=${bindings.deposit},redeem=${bindings.redeem}`,
|
|
538
|
+
code: 'zone-flow-unsupported',
|
|
539
|
+
expected: 'deposit=true,redeem=true',
|
|
540
|
+
message: 'Earn router must support private deposits and redemptions.',
|
|
541
|
+
})
|
|
542
|
+
if (issues.length > 0) throw mismatch({ discovery: options.discovery, issues })
|
|
543
|
+
|
|
544
|
+
return {
|
|
545
|
+
...route,
|
|
546
|
+
inputTokens: [bindings.privateAsset],
|
|
547
|
+
name: zone.name,
|
|
548
|
+
outputTokens: [bindings.privateAsset],
|
|
549
|
+
}
|
|
550
|
+
}),
|
|
551
|
+
)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
export declare namespace resolveZoneRoutes {
|
|
555
|
+
/** Inputs for resolving and verifying curated Zone routes. */
|
|
556
|
+
type Options = {
|
|
557
|
+
/** Live state of the Earn vault bound by every router. */
|
|
558
|
+
discovery: Discovery
|
|
559
|
+
/** Resolves the parent-chain client used to read each router. */
|
|
560
|
+
getClient: Viem.GetClient
|
|
561
|
+
/** Curated Zone routes to verify. */
|
|
562
|
+
routes: unknown
|
|
563
|
+
/** Private Zones configured by the API. */
|
|
564
|
+
zones: readonly Chain[]
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
366
568
|
/** Infers the supported engine type from its capability fingerprint. */
|
|
367
569
|
export function classifyEngineType(
|
|
368
570
|
options: classifyEngineType.Options,
|
|
@@ -729,6 +931,60 @@ declare namespace readEngineBindings {
|
|
|
729
931
|
}
|
|
730
932
|
}
|
|
731
933
|
|
|
934
|
+
async function readZoneRouteBindings(
|
|
935
|
+
client: Client,
|
|
936
|
+
options: readZoneRouteBindings.Options,
|
|
937
|
+
): Promise<ZoneRouteBindings> {
|
|
938
|
+
const [allowedZoneId, earnShare, earnVault, privateAsset, vaultAsset, deposit, redeem] =
|
|
939
|
+
await Promise.all([
|
|
940
|
+
client.readContract({
|
|
941
|
+
abi: Abis.earnRouter,
|
|
942
|
+
address: options.earnRouter,
|
|
943
|
+
functionName: 'allowedZoneId',
|
|
944
|
+
}),
|
|
945
|
+
client.readContract({
|
|
946
|
+
abi: Abis.earnRouter,
|
|
947
|
+
address: options.earnRouter,
|
|
948
|
+
functionName: 'earnShare',
|
|
949
|
+
}),
|
|
950
|
+
client.readContract({
|
|
951
|
+
abi: Abis.earnRouter,
|
|
952
|
+
address: options.earnRouter,
|
|
953
|
+
functionName: 'earnVault',
|
|
954
|
+
}),
|
|
955
|
+
client.readContract({
|
|
956
|
+
abi: Abis.earnRouter,
|
|
957
|
+
address: options.earnRouter,
|
|
958
|
+
functionName: 'privateAsset',
|
|
959
|
+
}),
|
|
960
|
+
client.readContract({
|
|
961
|
+
abi: Abis.earnRouter,
|
|
962
|
+
address: options.earnRouter,
|
|
963
|
+
functionName: 'vaultAsset',
|
|
964
|
+
}),
|
|
965
|
+
client.readContract({
|
|
966
|
+
abi: Abis.earnRouter,
|
|
967
|
+
address: options.earnRouter,
|
|
968
|
+
args: [0],
|
|
969
|
+
functionName: 'supportsFlow',
|
|
970
|
+
}),
|
|
971
|
+
client.readContract({
|
|
972
|
+
abi: Abis.earnRouter,
|
|
973
|
+
address: options.earnRouter,
|
|
974
|
+
args: [1],
|
|
975
|
+
functionName: 'supportsFlow',
|
|
976
|
+
}),
|
|
977
|
+
])
|
|
978
|
+
return { allowedZoneId, deposit, earnShare, earnVault, privateAsset, redeem, vaultAsset }
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
declare namespace readZoneRouteBindings {
|
|
982
|
+
type Options = {
|
|
983
|
+
/** Parent-chain Earn router to inspect. */
|
|
984
|
+
earnRouter: Address
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
732
988
|
async function readRouterCapabilities(
|
|
733
989
|
client: Client,
|
|
734
990
|
options: readRouterCapabilities.Options,
|
|
@@ -840,6 +1096,27 @@ function compareAddress(
|
|
|
840
1096
|
if (!isAddressEqual(actual, expected)) issues.push({ actual, code, expected, message })
|
|
841
1097
|
}
|
|
842
1098
|
|
|
1099
|
+
function mismatch(options: mismatch.Options): VerificationError {
|
|
1100
|
+
return new VerificationError({
|
|
1101
|
+
issues: options.issues,
|
|
1102
|
+
snapshot: {
|
|
1103
|
+
assetToken: options.discovery.assetToken,
|
|
1104
|
+
isSynced: options.discovery.state.isAccountingAligned,
|
|
1105
|
+
shareToken: options.discovery.shareToken,
|
|
1106
|
+
},
|
|
1107
|
+
status: 'mismatch',
|
|
1108
|
+
})
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
declare namespace mismatch {
|
|
1112
|
+
type Options = {
|
|
1113
|
+
/** Live vault state captured with the mismatch. */
|
|
1114
|
+
discovery: Discovery
|
|
1115
|
+
/** Verification issues that rejected the deployment. */
|
|
1116
|
+
issues: readonly VerificationIssue[]
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
|
|
843
1120
|
function unavailable(): VerificationUnavailable {
|
|
844
1121
|
return {
|
|
845
1122
|
issues: [
|
package/src/internal/OpenApi.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { Context, Env, MiddlewareHandler, ValidationTargets } from 'hono'
|
|
2
2
|
import type { HasRequiredKeys } from 'hono/utils/types'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
describeRoute as core_describeRoute,
|
|
5
|
+
type DescribeRouteOptions,
|
|
6
|
+
resolver,
|
|
7
|
+
type ResponsesWithResolver,
|
|
8
|
+
uniqueSymbol,
|
|
9
|
+
validator,
|
|
10
|
+
} from 'hono-openapi'
|
|
4
11
|
import * as z from 'zod/mini'
|
|
5
12
|
import * as Response from './Response.js'
|
|
6
13
|
import * as Schema from './Schema.js'
|
|
@@ -41,7 +48,6 @@ const schemaOptions = { options: { override: recoverExamples, unrepresentable: '
|
|
|
41
48
|
// re-exports because `uniqueSymbol` is a `unique symbol` whose identity is
|
|
42
49
|
// lost when copied through a `const` declaration.
|
|
43
50
|
export {
|
|
44
|
-
describeRoute,
|
|
45
51
|
type HandlerUniqueProperty,
|
|
46
52
|
resolver,
|
|
47
53
|
type ResponsesWithResolver,
|
|
@@ -49,12 +55,53 @@ export {
|
|
|
49
55
|
validator,
|
|
50
56
|
} from 'hono-openapi'
|
|
51
57
|
|
|
58
|
+
function cloneResponseContainers(spec: DescribeRouteOptions): DescribeRouteOptions {
|
|
59
|
+
if (!spec.responses) return spec
|
|
60
|
+
return {
|
|
61
|
+
...spec,
|
|
62
|
+
responses: Object.fromEntries(
|
|
63
|
+
Object.entries(spec.responses).map(([status, response]) => [
|
|
64
|
+
status,
|
|
65
|
+
!response || !('content' in response)
|
|
66
|
+
? response
|
|
67
|
+
: {
|
|
68
|
+
...response,
|
|
69
|
+
content: Object.fromEntries(
|
|
70
|
+
Object.entries(response.content ?? {}).map(([mediaType, media]) => [
|
|
71
|
+
mediaType,
|
|
72
|
+
{ ...media },
|
|
73
|
+
]),
|
|
74
|
+
),
|
|
75
|
+
},
|
|
76
|
+
]),
|
|
77
|
+
),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Describes a route without allowing spec generation to mutate reusable response definitions. */
|
|
82
|
+
export function describeRoute(spec: DescribeRouteOptions): MiddlewareHandler {
|
|
83
|
+
const handler = core_describeRoute(spec)
|
|
84
|
+
Object.defineProperty(handler, uniqueSymbol, {
|
|
85
|
+
get: () => ({ spec: cloneResponseContainers(spec) }),
|
|
86
|
+
})
|
|
87
|
+
return handler
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Emits a named OpenAPI component and uses its `$ref` wherever the schema appears. */
|
|
91
|
+
export function component<const schema extends z.ZodMiniType>(
|
|
92
|
+
schema: schema,
|
|
93
|
+
name: string,
|
|
94
|
+
): schema {
|
|
95
|
+
const cloned = schema.clone()
|
|
96
|
+
z.globalRegistry.add(cloned, { ...z.globalRegistry.get(schema), ref: name })
|
|
97
|
+
return cloned as schema
|
|
98
|
+
}
|
|
99
|
+
|
|
52
100
|
/**
|
|
53
101
|
* Standard machine-readable `error.code` values per status, shared API-wide.
|
|
54
102
|
* The reference enumerates `error.code` to these so generated clients narrow it
|
|
55
|
-
* to a literal union instead of an open `string`.
|
|
56
|
-
*
|
|
57
|
-
* via the `codes` override in {@link responses.Options}.
|
|
103
|
+
* to a literal union instead of an open `string`. The values here are shared
|
|
104
|
+
* defaults; operation-specific codes are supplied through {@link responses.Options}.
|
|
58
105
|
*/
|
|
59
106
|
export const errorCodes = {
|
|
60
107
|
400: [
|
|
@@ -80,7 +127,7 @@ export const errorCodes = {
|
|
|
80
127
|
'api_key_malformed',
|
|
81
128
|
],
|
|
82
129
|
401: ['api_key_missing', 'api_key_invalid', 'unauthorized'],
|
|
83
|
-
403: ['api_key_forbidden', 'api_key_ip_forbidden', '
|
|
130
|
+
403: ['api_key_forbidden', 'api_key_ip_forbidden', 'forbidden'],
|
|
84
131
|
404: [
|
|
85
132
|
'not_found',
|
|
86
133
|
'token_not_found',
|
|
@@ -164,11 +211,78 @@ export const rateLimitHeaders = {
|
|
|
164
211
|
/** Representative `requestId` used in error-body examples. */
|
|
165
212
|
const exampleRequestId = '0a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9'
|
|
166
213
|
|
|
167
|
-
|
|
168
|
-
|
|
214
|
+
const standardErrorNames = {
|
|
215
|
+
400: 'InvalidRequestError',
|
|
216
|
+
401: 'AuthenticationError',
|
|
217
|
+
403: 'ForbiddenError',
|
|
218
|
+
404: 'ResourceNotFoundError',
|
|
219
|
+
429: 'RateLimitError',
|
|
220
|
+
500: 'InternalError',
|
|
221
|
+
501: 'NotImplementedError',
|
|
222
|
+
502: 'UpstreamError',
|
|
223
|
+
} as const satisfies Record<keyof typeof errorCodes, string>
|
|
224
|
+
|
|
225
|
+
const reservedErrorNames = new Set<string>(Object.values(standardErrorNames))
|
|
226
|
+
const errorSchemas = new Map<string, z.ZodMiniType>()
|
|
227
|
+
|
|
228
|
+
function errorName(status: number, codes: readonly string[]) {
|
|
229
|
+
const standard = errorCodes[status as keyof typeof errorCodes]
|
|
230
|
+
if (
|
|
231
|
+
standard &&
|
|
232
|
+
standard.length === codes.length &&
|
|
233
|
+
[...standard].sort().every((code, index) => code === codes[index])
|
|
234
|
+
)
|
|
235
|
+
return standardErrorNames[status as keyof typeof standardErrorNames]
|
|
236
|
+
const name = `${codes
|
|
237
|
+
.map((code) =>
|
|
238
|
+
code
|
|
239
|
+
.split('_')
|
|
240
|
+
.map((part) => `${part[0]?.toUpperCase()}${part.slice(1)}`)
|
|
241
|
+
.join(''),
|
|
242
|
+
)
|
|
243
|
+
.join('Or')}Error`
|
|
244
|
+
if (reservedErrorNames.has(name)) return `${name.slice(0, -'Error'.length)}${status}Error`
|
|
245
|
+
return name
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function errorSchema(status: number, codes: readonly [string, ...string[]] | undefined) {
|
|
249
|
+
const defaults = errorCodes[status as keyof typeof errorCodes]
|
|
250
|
+
if (!codes && !defaults) {
|
|
251
|
+
const cached = errorSchemas.get('*')
|
|
252
|
+
if (cached) return cached
|
|
253
|
+
const schema = component(Schema.errorResponse(), 'ErrorResponse')
|
|
254
|
+
errorSchemas.set('*', schema)
|
|
255
|
+
return schema
|
|
256
|
+
}
|
|
257
|
+
const normalized = [...(codes ?? defaults ?? [])].sort() as [string, ...string[]]
|
|
258
|
+
const key = normalized.join('\0')
|
|
259
|
+
const cached = errorSchemas.get(key)
|
|
260
|
+
if (cached) return cached
|
|
261
|
+
const schema = component(Schema.errorResponse(normalized), errorName(status, normalized))
|
|
262
|
+
errorSchemas.set(key, schema)
|
|
263
|
+
return schema
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function mergeErrorCodes(
|
|
267
|
+
status: number,
|
|
268
|
+
codes: readonly string[] | undefined,
|
|
269
|
+
): readonly [string, ...string[]] | undefined {
|
|
270
|
+
if (!codes) return errorCodes[status as keyof typeof errorCodes]
|
|
271
|
+
if (status !== 400 && status !== 403)
|
|
272
|
+
return codes.length ? (codes as [string, ...string[]]) : undefined
|
|
273
|
+
const baseline = status === 400 ? (['api_key_malformed'] as const) : errorCodes[403]
|
|
274
|
+
return [...new Set([...baseline, ...codes])] as [string, ...string[]]
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Builds the `application/json` content for a standard error response: the named enumerated-code envelope plus an example body. */
|
|
278
|
+
function errorContent(
|
|
279
|
+
status: number,
|
|
280
|
+
codes: readonly [string, ...string[]] | undefined,
|
|
281
|
+
message: string,
|
|
282
|
+
) {
|
|
169
283
|
return {
|
|
170
284
|
'application/json': {
|
|
171
|
-
schema: resolver(
|
|
285
|
+
schema: resolver(errorSchema(status, codes), schemaOptions),
|
|
172
286
|
example: { error: { code: codes?.[0] ?? 'error', message }, requestId: exampleRequestId },
|
|
173
287
|
},
|
|
174
288
|
}
|
|
@@ -186,32 +300,30 @@ export const paymentChallenge = {
|
|
|
186
300
|
headers: { 'WWW-Authenticate': headerRef('WwwAuthenticate') },
|
|
187
301
|
} as const
|
|
188
302
|
|
|
189
|
-
|
|
190
|
-
const rateLimitedResponse = {
|
|
191
|
-
content: errorContent(errorCodes[429], 'Rate limit exceeded.'),
|
|
192
|
-
description:
|
|
193
|
-
'Rate limit exceeded. On endpoints that accept MPP, over-quota unpaid requests return `402 Payment Required` instead.',
|
|
194
|
-
headers: { ...rateLimitHeaders },
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** Shared `500` internal-error response, registered as `components.responses.InternalError`. */
|
|
198
|
-
const serverErrorResponse = {
|
|
199
|
-
content: errorContent(errorCodes[500], 'Internal server error.'),
|
|
200
|
-
description: 'Internal server error.',
|
|
201
|
-
}
|
|
303
|
+
type ResponseComponentName = 'InternalError' | 'PaymentRequired' | 'RateLimited'
|
|
202
304
|
|
|
203
305
|
/**
|
|
204
306
|
* Reusable responses registered under `components.responses` (see `App.create`)
|
|
205
307
|
* and `$ref`-erenced from operations, so the uniform `402`/`429`/`500` responses
|
|
206
308
|
* are defined once instead of inlined on every operation.
|
|
207
309
|
*/
|
|
208
|
-
export
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
310
|
+
export function responseComponents(): ResponsesWithResolver {
|
|
311
|
+
return {
|
|
312
|
+
InternalError: {
|
|
313
|
+
content: errorContent(500, errorCodes[500], 'Internal server error.'),
|
|
314
|
+
description: 'Internal server error.',
|
|
315
|
+
},
|
|
316
|
+
PaymentRequired: paymentChallenge,
|
|
317
|
+
RateLimited: {
|
|
318
|
+
content: errorContent(429, errorCodes[429], 'Rate limit exceeded.'),
|
|
319
|
+
description:
|
|
320
|
+
'Rate limit exceeded. On endpoints that accept MPP, over-quota unpaid requests return `402 Payment Required` instead.',
|
|
321
|
+
headers: { ...rateLimitHeaders },
|
|
322
|
+
},
|
|
323
|
+
}
|
|
212
324
|
}
|
|
213
325
|
|
|
214
|
-
const responseRef = (name:
|
|
326
|
+
const responseRef = (name: ResponseComponentName) => ({
|
|
215
327
|
$ref: `#/components/responses/${name}`,
|
|
216
328
|
})
|
|
217
329
|
|
|
@@ -232,22 +344,22 @@ export function standardError(
|
|
|
232
344
|
): ResponsesWithResolver[string] {
|
|
233
345
|
if (status === 429) return responseRef('RateLimited')
|
|
234
346
|
if (status === 500) return responseRef('InternalError')
|
|
235
|
-
return { content: errorContent(
|
|
347
|
+
return { content: errorContent(status, mergeErrorCodes(status, codes), description), description }
|
|
236
348
|
}
|
|
237
349
|
|
|
238
350
|
/**
|
|
239
351
|
* Builds an OpenAPI `responses` map with the API's standard error responses
|
|
240
352
|
* pre-filled, plus the success response (with rate-limit headers):
|
|
241
353
|
*
|
|
242
|
-
* - `400` invalid request, `401` missing/invalid key, `
|
|
243
|
-
* `500` internal error, and `502` upstream failure on every operation;
|
|
244
|
-
* - `
|
|
354
|
+
* - `400` invalid request, `401` missing/invalid key, `403` forbidden, `429`
|
|
355
|
+
* rate limited, `500` internal error, and `502` upstream failure on every operation;
|
|
356
|
+
* - `404`/`409`/`412`/`413`/`415` only when an `errors` entry is set.
|
|
245
357
|
*
|
|
246
|
-
* `error.code` is enumerated per status from {@link errorCodes}
|
|
247
|
-
*
|
|
248
|
-
* `429
|
|
249
|
-
*
|
|
250
|
-
*
|
|
358
|
+
* `error.code` is enumerated per status from {@link errorCodes}. Operation-level
|
|
359
|
+
* 400/403 codes merge with shared auth codes; other overrides replace defaults.
|
|
360
|
+
* The default `429` and `500` `$ref` shared {@link responseComponents}; an exact
|
|
361
|
+
* operation-level `429` override is emitted inline with the standard headers.
|
|
362
|
+
* `402` is injected per operation from the route's MPP policy in `App.ts`.
|
|
251
363
|
*/
|
|
252
364
|
export function responses<schema extends z.ZodMiniType>(
|
|
253
365
|
options: responses.Options<schema>,
|
|
@@ -257,10 +369,11 @@ export function responses<schema extends z.ZodMiniType>(
|
|
|
257
369
|
const override = errors?.[status as 400]
|
|
258
370
|
const description =
|
|
259
371
|
typeof override === 'string' ? override : (override?.description ?? fallback)
|
|
260
|
-
const codes =
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
372
|
+
const codes = mergeErrorCodes(status, typeof override === 'object' ? override.codes : undefined)
|
|
373
|
+
return {
|
|
374
|
+
content: errorContent(status, codes, description),
|
|
375
|
+
description,
|
|
376
|
+
}
|
|
264
377
|
}
|
|
265
378
|
return {
|
|
266
379
|
200: {
|
|
@@ -279,13 +392,15 @@ export function responses<schema extends z.ZodMiniType>(
|
|
|
279
392
|
},
|
|
280
393
|
400: error(400, 'Invalid request.'),
|
|
281
394
|
401: error(401, 'Missing or invalid API key.'),
|
|
282
|
-
|
|
395
|
+
403: error(403, 'Forbidden.'),
|
|
283
396
|
...(errors?.[404] && { 404: error(404, 'Not found.') }),
|
|
284
397
|
...(errors?.[409] && { 409: error(409, 'Conflict.') }),
|
|
285
398
|
...(errors?.[412] && { 412: error(412, 'Precondition failed.') }),
|
|
286
399
|
...(errors?.[413] && { 413: error(413, 'Payload too large.') }),
|
|
287
400
|
...(errors?.[415] && { 415: error(415, 'Unsupported media type.') }),
|
|
288
|
-
429:
|
|
401
|
+
429: errors?.[429]
|
|
402
|
+
? { ...error(429, 'Rate limit exceeded.'), headers: { ...rateLimitHeaders } }
|
|
403
|
+
: responseRef('RateLimited'),
|
|
289
404
|
500: responseRef('InternalError'),
|
|
290
405
|
...(errors?.[501] && { 501: error(501, 'Not implemented.') }),
|
|
291
406
|
502: error(502, 'Upstream data failure.'),
|
|
@@ -295,23 +410,22 @@ export function responses<schema extends z.ZodMiniType>(
|
|
|
295
410
|
export declare namespace responses {
|
|
296
411
|
/**
|
|
297
412
|
* Override for a standard error response: a description string, or an object
|
|
298
|
-
* adding
|
|
413
|
+
* adding operation codes. Codes replace defaults except shared 400/403 auth codes.
|
|
299
414
|
*/
|
|
300
415
|
type ErrorOverride =
|
|
301
416
|
| string
|
|
302
417
|
| {
|
|
303
418
|
/** Human-readable description of the error response. */
|
|
304
419
|
description?: string | undefined
|
|
305
|
-
/**
|
|
306
|
-
codes?: readonly
|
|
420
|
+
/** Operation-specific `error.code` values for this status. */
|
|
421
|
+
codes?: readonly string[] | undefined
|
|
307
422
|
}
|
|
308
423
|
|
|
309
424
|
/** Options for building a standard OpenAPI responses map. */
|
|
310
425
|
type Options<schema> = {
|
|
311
426
|
/**
|
|
312
|
-
* Optional overrides for standard error responses
|
|
313
|
-
* `
|
|
314
|
-
* includes that status in the map.
|
|
427
|
+
* Optional overrides for standard error responses. Setting
|
|
428
|
+
* `404`/`409`/`412`/`413`/`415` includes that status in the map.
|
|
315
429
|
*/
|
|
316
430
|
errors?:
|
|
317
431
|
| {
|
|
@@ -319,7 +433,7 @@ export declare namespace responses {
|
|
|
319
433
|
400?: ErrorOverride | undefined
|
|
320
434
|
/** Override for the 401 response. */
|
|
321
435
|
401?: ErrorOverride | undefined
|
|
322
|
-
/**
|
|
436
|
+
/** Add operation-specific 403 codes or override its description. */
|
|
323
437
|
403?: ErrorOverride | undefined
|
|
324
438
|
/** Override for the 404 response. Setting this includes 404 in the map. */
|
|
325
439
|
404?: ErrorOverride | undefined
|
|
@@ -331,6 +445,8 @@ export declare namespace responses {
|
|
|
331
445
|
413?: ErrorOverride | undefined
|
|
332
446
|
/** Override for the 415 response. Setting this includes 415 in the map. */
|
|
333
447
|
415?: ErrorOverride | undefined
|
|
448
|
+
/** Override the shared 429 response with operation-specific rate-limit codes. */
|
|
449
|
+
429?: ErrorOverride | undefined
|
|
334
450
|
/** Override for the 501 response. Setting this includes 501 in the map. */
|
|
335
451
|
501?: ErrorOverride | undefined
|
|
336
452
|
/** Override for the 502 response. */
|