tapimo 0.4.4 → 0.5.1
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 +4701 -3416
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +24 -2
- package/dist/App.js.map +1 -1
- package/dist/Assets.js +3 -3
- package/dist/Assets.js.map +1 -1
- package/dist/Scope.d.ts +18 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +23 -3
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +1 -1
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +5 -10
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/App.d.ts +6 -34
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +3 -3
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +4 -1
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +6 -34
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/scopes.js +2 -2
- package/dist/admin/apps/scopes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +57 -57
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +33 -33
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/apps/data/App.d.ts +4574 -4277
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +155 -77
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts +109 -0
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -0
- package/dist/apps/data/FundingQuoteProviders.js +464 -0
- package/dist/apps/data/FundingQuoteProviders.js.map +1 -0
- package/dist/apps/data/index.d.ts +1 -1
- package/dist/apps/data/index.js +1 -1
- package/dist/apps/data/routes/activities.d.ts +26 -26
- package/dist/apps/data/routes/addresses.d.ts +38 -38
- package/dist/apps/data/routes/balances.d.ts +45 -45
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +67 -149
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +2 -3
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +3 -5
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +177 -176
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
- package/dist/apps/data/routes/coingecko.js +3 -8
- package/dist/apps/data/routes/coingecko.js.map +1 -1
- package/dist/apps/data/routes/funding.d.ts +131 -228
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +152 -219
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +34 -34
- package/dist/apps/data/routes/indexer.d.ts.map +1 -1
- package/dist/apps/data/routes/indexer.js +9 -2
- package/dist/apps/data/routes/indexer.js.map +1 -1
- package/dist/apps/data/routes/receipts.d.ts +228 -228
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +86 -16
- 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/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +340 -0
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +13 -1
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/index.js +1 -1
- package/dist/apps/management/App.d.ts +1833 -851
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +4 -0
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +41 -41
- package/dist/apps/management/routes/api-keys.js +2 -2
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +48 -48
- package/dist/apps/management/routes/invitations.d.ts +132 -132
- package/dist/apps/management/routes/invite-links.d.ts +1100 -0
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -0
- package/dist/apps/management/routes/invite-links.js +411 -0
- package/dist/apps/management/routes/invite-links.js.map +1 -0
- package/dist/apps/management/routes/members.d.ts +41 -41
- package/dist/apps/management/routes/orgs.d.ts +92 -92
- package/dist/apps/management/routes/projects.d.ts +9 -9
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +2 -2
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +24 -24
- package/dist/apps/mcp.js +2 -2
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/relay/App.d.ts +2 -2
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +44 -6
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/db/Db.d.ts +3 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +57 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +31 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +31 -0
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/inviteLinks.d.ts +42 -0
- package/dist/db/tables/inviteLinks.d.ts.map +1 -0
- package/dist/db/tables/inviteLinks.js +148 -0
- package/dist/db/tables/inviteLinks.js.map +1 -0
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +2 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +6 -2
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +13 -3
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +9 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +138 -10
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts +3 -1
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +17 -2
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/{FundingRoutes.d.ts → FundingQuotes.d.ts} +240 -369
- package/dist/internal/FundingQuotes.d.ts.map +1 -0
- package/dist/internal/{FundingRoutes.js → FundingQuotes.js} +144 -183
- package/dist/internal/FundingQuotes.js.map +1 -0
- package/dist/internal/Log.d.ts +18 -12
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +2 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/Tidx.d.ts +9 -3
- package/dist/internal/Tidx.d.ts.map +1 -1
- package/dist/internal/Tidx.js +13 -7
- package/dist/internal/Tidx.js.map +1 -1
- package/dist/internal/Viem.d.ts +17 -2
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +30 -3
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +1 -1
- package/package.json +2 -2
- package/src/ApiKeys.test.ts +25 -0
- package/src/App.test-d.ts +2 -0
- package/src/App.test.ts +13 -2
- package/src/App.ts +37 -5
- package/src/Assets.ts +3 -3
- package/src/Client.test-d.ts +21 -11
- package/src/Scope.test.ts +1 -0
- package/src/Scope.ts +32 -4
- package/src/Webhooks.ts +5 -10
- package/src/admin/apps/api-keys.test.ts +27 -0
- package/src/admin/apps/api-keys.ts +8 -1
- package/src/admin/apps/scopes.test.ts +7 -2
- package/src/admin/apps/scopes.ts +2 -2
- package/src/admin/ui/src/components/Dialog.tsx +8 -2
- package/src/admin/ui/src/lib/scopes.test.ts +19 -0
- package/src/admin/ui/src/lib/scopes.ts +12 -0
- package/src/admin/ui/src/routes/api-keys.tsx +128 -27
- package/src/admin/ui.generated.ts +33 -33
- package/src/apps/composition.test.ts +77 -0
- package/src/apps/data/App.test.ts +354 -0
- package/src/apps/data/App.ts +178 -91
- package/src/apps/data/FundingQuoteProviders.test.ts +577 -0
- package/src/apps/data/FundingQuoteProviders.ts +633 -0
- package/src/apps/data/index.ts +1 -1
- package/src/apps/data/routes/balances.test.ts +64 -18
- package/src/apps/data/routes/balances.ts +76 -177
- package/src/apps/data/routes/blocks.ts +3 -5
- package/src/apps/data/routes/coingecko.ts +3 -8
- package/src/apps/data/routes/funding.test.ts +304 -192
- package/src/apps/data/routes/funding.ts +166 -286
- package/src/apps/data/routes/indexer.test.ts +173 -15
- package/src/apps/data/routes/indexer.ts +8 -2
- package/src/apps/data/routes/rpc.test.ts +219 -0
- package/src/apps/data/routes/rpc.ts +92 -17
- package/src/apps/data/routes/webhooks.test.ts +21 -0
- package/src/apps/data/routes/webhooks.ts +13 -1
- package/src/apps/index.ts +1 -1
- package/src/apps/management/App.ts +4 -0
- package/src/apps/management/Billing.test.ts +2 -2
- package/src/apps/management/routes/api-keys.test.ts +47 -3
- package/src/apps/management/routes/api-keys.ts +2 -2
- package/src/apps/management/routes/invite-links.test.ts +385 -0
- package/src/apps/management/routes/invite-links.ts +570 -0
- package/src/apps/management/routes/scopes.test.ts +3 -2
- package/src/apps/management/routes/scopes.ts +4 -2
- package/src/apps/mcp.test.ts +18 -0
- package/src/apps/mcp.ts +2 -2
- package/src/apps/relay/App.test.ts +328 -7
- package/src/apps/relay/App.ts +42 -6
- package/src/apps/relay/Sponsorships.test.ts +2 -2
- package/src/db/Db.test.ts +5 -5
- package/src/db/Db.ts +65 -0
- package/src/db/Schema.ts +39 -0
- package/src/db/tables/billingSettings.test.ts +2 -2
- package/src/db/tables/inviteLinks.ts +187 -0
- package/src/db/tables/organizations.test.ts +2 -2
- package/src/db/tables/organizations.ts +2 -0
- package/src/db/tables/sponsoredTransactions.test.ts +19 -2
- package/src/db/tables/sponsoredTransactions.ts +21 -14
- package/src/db/tables/stripeCustomers.test.ts +2 -2
- package/src/handlers/relay.ts +16 -4
- package/src/internal/Auth.test.ts +132 -22
- package/src/internal/Auth.ts +181 -14
- package/src/internal/EdgeCache.test.ts +24 -3
- package/src/internal/EdgeCache.ts +18 -2
- package/src/internal/FundingQuotes.test.ts +268 -0
- package/src/internal/{FundingRoutes.ts → FundingQuotes.ts} +216 -277
- package/src/internal/Log.ts +21 -14
- package/src/internal/Tidx.test.ts +48 -0
- package/src/internal/Tidx.ts +21 -7
- package/src/internal/Viem.test.ts +46 -0
- package/src/internal/Viem.ts +48 -6
- package/src/internal/index.test.ts +1 -1
- package/src/internal/index.ts +1 -1
- package/dist/apps/data/FundingRouteProviders.d.ts +0 -36
- package/dist/apps/data/FundingRouteProviders.d.ts.map +0 -1
- package/dist/apps/data/FundingRouteProviders.js +0 -245
- package/dist/apps/data/FundingRouteProviders.js.map +0 -1
- package/dist/internal/FundingRoutes.d.ts.map +0 -1
- package/dist/internal/FundingRoutes.js.map +0 -1
- package/src/apps/data/FundingRouteProviders.test.ts +0 -225
- package/src/apps/data/FundingRouteProviders.ts +0 -312
- package/src/internal/FundingRoutes.test.ts +0 -213
package/src/internal/Log.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type Variables = {
|
|
|
12
12
|
errorCode?: string | undefined
|
|
13
13
|
/** Redacted provider failure details recorded by an upstream adapter. */
|
|
14
14
|
providerFailure?: Entry['provider'] | undefined
|
|
15
|
+
/** Redacted provider failures when multiple upstream adapters fail. */
|
|
16
|
+
providerFailures?: Entry['providerFailures'] | undefined
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/** Hono environment shape used by the request logger. */
|
|
@@ -28,6 +30,20 @@ export type Environment = {
|
|
|
28
30
|
/** Log level, derived from the response status. */
|
|
29
31
|
export type Level = 'error' | 'info' | 'warn'
|
|
30
32
|
|
|
33
|
+
/** Redacted upstream provider failure details. */
|
|
34
|
+
export type ProviderFailure = {
|
|
35
|
+
/** Stable provider error code, when one is safe to retain. */
|
|
36
|
+
code?: string | undefined
|
|
37
|
+
/** Failure boundary that rejected the provider request. */
|
|
38
|
+
failure: 'http' | 'network' | 'payload' | 'timeout' | 'unknown'
|
|
39
|
+
/** Provider identifier. */
|
|
40
|
+
id: string
|
|
41
|
+
/** Provider operation identifier. */
|
|
42
|
+
operation: string
|
|
43
|
+
/** Upstream HTTP status, when a response was received. */
|
|
44
|
+
status?: number | undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
/** One canonical request log entry. */
|
|
32
48
|
export type Entry = {
|
|
33
49
|
/** `'hit'` when the edge response cache served the request without reaching the origin handlers. */
|
|
@@ -64,20 +80,9 @@ export type Entry = {
|
|
|
64
80
|
}
|
|
65
81
|
| undefined
|
|
66
82
|
/** Redacted upstream provider failure details, when an adapter request fails. */
|
|
67
|
-
provider?:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
code?: string | undefined
|
|
71
|
-
/** Failure boundary that rejected the provider request. */
|
|
72
|
-
failure: 'http' | 'network' | 'payload' | 'unknown'
|
|
73
|
-
/** Provider identifier. */
|
|
74
|
-
id: string
|
|
75
|
-
/** Provider operation identifier. */
|
|
76
|
-
operation: string
|
|
77
|
-
/** Upstream HTTP status, when a response was received. */
|
|
78
|
-
status?: number | undefined
|
|
79
|
-
}
|
|
80
|
-
| undefined
|
|
83
|
+
provider?: ProviderFailure | undefined
|
|
84
|
+
/** Redacted failures for every provider when multiple adapters fail. */
|
|
85
|
+
providerFailures?: readonly ProviderFailure[] | undefined
|
|
81
86
|
/** Raw query string (no leading `?`) with API-key tokens redacted, when present. */
|
|
82
87
|
query?: string | undefined
|
|
83
88
|
/** Rate limit state from the `RateLimit-*` response headers, when enforced. */
|
|
@@ -136,6 +141,7 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
136
141
|
const principal = c.get('principal' as never) as Auth.Principal | undefined
|
|
137
142
|
const errorCode = c.get('errorCode' as never) as string | undefined
|
|
138
143
|
const provider = c.get('providerFailure' as never) as Entry['provider']
|
|
144
|
+
const providerFailures = c.get('providerFailures' as never) as Entry['providerFailures']
|
|
139
145
|
|
|
140
146
|
// The `request` total metric duplicates `duration` (measured here, one
|
|
141
147
|
// layer further out), so only operation timings are kept.
|
|
@@ -186,6 +192,7 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
186
192
|
},
|
|
187
193
|
}),
|
|
188
194
|
...(provider === undefined ? {} : { provider }),
|
|
195
|
+
...(providerFailures === undefined ? {} : { providerFailures }),
|
|
189
196
|
...(query ? { query } : {}),
|
|
190
197
|
...(rateLimit === undefined ? {} : { rateLimit }),
|
|
191
198
|
requestId: c.get('requestId' as never) as string,
|
|
@@ -203,6 +203,21 @@ describe('resolve', () => {
|
|
|
203
203
|
`)
|
|
204
204
|
})
|
|
205
205
|
|
|
206
|
+
test('resolves Bearer auth', () => {
|
|
207
|
+
expect(
|
|
208
|
+
Tidx.resolve(
|
|
209
|
+
{ baseUrl: 'https://internal.indexer', bearerAuth: 'zone-secret' },
|
|
210
|
+
{ chainId: 4217, principal: apiKeyPrincipal },
|
|
211
|
+
),
|
|
212
|
+
).toMatchInlineSnapshot(`
|
|
213
|
+
{
|
|
214
|
+
"baseUrl": "https://internal.indexer",
|
|
215
|
+
"basicAuth": undefined,
|
|
216
|
+
"bearerAuth": "zone-secret",
|
|
217
|
+
}
|
|
218
|
+
`)
|
|
219
|
+
})
|
|
220
|
+
|
|
206
221
|
test('the resolver form routes anonymous callers to a separate upstream', () => {
|
|
207
222
|
const tidx = ({ principal }: Viem.resolve.Context) =>
|
|
208
223
|
principal?.type === 'public'
|
|
@@ -243,6 +258,28 @@ describe('resolve', () => {
|
|
|
243
258
|
})
|
|
244
259
|
})
|
|
245
260
|
|
|
261
|
+
describe('getClient', () => {
|
|
262
|
+
test('sends Bearer auth', async () => {
|
|
263
|
+
const fetch = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
|
264
|
+
new Response(JSON.stringify({ columns: [], ok: true, row_count: 0, rows: [] }), {
|
|
265
|
+
headers: { 'content-type': 'application/json' },
|
|
266
|
+
}),
|
|
267
|
+
)
|
|
268
|
+
try {
|
|
269
|
+
const client = Tidx.getClient({
|
|
270
|
+
chainId: 4217,
|
|
271
|
+
tidx: { baseUrl: 'https://internal.indexer', bearerAuth: 'zone-secret' },
|
|
272
|
+
})
|
|
273
|
+
await client.fetch({ query: 'select 1' })
|
|
274
|
+
|
|
275
|
+
const upstream = fetch.mock.calls[0]![0] as Request
|
|
276
|
+
expect(upstream.headers.get('authorization')).toBe('Bearer zone-secret')
|
|
277
|
+
} finally {
|
|
278
|
+
fetch.mockRestore()
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
})
|
|
282
|
+
|
|
246
283
|
describe('createGetClient', () => {
|
|
247
284
|
test('memoizes one client per resolved upstream', () => {
|
|
248
285
|
const getTidx = Tidx.createGetClient({
|
|
@@ -267,6 +304,17 @@ describe('createGetClient', () => {
|
|
|
267
304
|
expect(getTidx(4217, null)).toBe(getTidx(4217, publicPrincipal))
|
|
268
305
|
})
|
|
269
306
|
|
|
307
|
+
test('does not share clients across Bearer credentials', () => {
|
|
308
|
+
const getTidx = Tidx.createGetClient({
|
|
309
|
+
tidx: ({ principal }) => ({
|
|
310
|
+
baseUrl: 'https://internal.indexer',
|
|
311
|
+
bearerAuth: principal?.type === 'public' ? 'public-secret' : 'private-secret',
|
|
312
|
+
}),
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
expect(getTidx(4217, publicPrincipal)).not.toBe(getTidx(4217, apiKeyPrincipal))
|
|
316
|
+
})
|
|
317
|
+
|
|
270
318
|
test('consults the resolver on every call but builds one client per upstream', () => {
|
|
271
319
|
const seen: (string | undefined)[] = []
|
|
272
320
|
const getTidx = Tidx.createGetClient({
|
package/src/internal/Tidx.ts
CHANGED
|
@@ -29,8 +29,8 @@ export type UrlResolver = (chainId: Viem.ChainId) => string | undefined
|
|
|
29
29
|
* receives a {@link Viem.resolve.Context} (`chainId` plus the request
|
|
30
30
|
* `principal`), so callers can route traffic per caller — e.g. send anonymous
|
|
31
31
|
* (`principal.type === 'public'`) traffic to a separate, no-auth indexer. A
|
|
32
|
-
* missing `baseUrl` falls back to the built-in public host map ({@link url});
|
|
33
|
-
* missing
|
|
32
|
+
* missing `baseUrl` falls back to the built-in public host map ({@link url});
|
|
33
|
+
* missing auth fields send no Authorization header.
|
|
34
34
|
*/
|
|
35
35
|
export function resolve(
|
|
36
36
|
tidx: getClient.Tidx | undefined,
|
|
@@ -42,6 +42,7 @@ export function resolve(
|
|
|
42
42
|
(typeof config?.baseUrl === 'function' ? config.baseUrl(context.chainId) : config?.baseUrl) ??
|
|
43
43
|
url[context.chainId],
|
|
44
44
|
basicAuth: config?.basicAuth,
|
|
45
|
+
...(config?.bearerAuth ? { bearerAuth: config.bearerAuth } : {}),
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -56,13 +57,22 @@ export declare namespace resolve {
|
|
|
56
57
|
baseUrl: string | undefined
|
|
57
58
|
/** Basic auth credentials, or undefined to send no Basic auth. */
|
|
58
59
|
basicAuth?: string | undefined
|
|
60
|
+
/** Bearer auth credential, or undefined to send no Bearer auth. */
|
|
61
|
+
bearerAuth?: string | undefined
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
export function getClient(options: getClient.Options): Client {
|
|
63
66
|
const { chainId = Viem.defaultChainId, principal = null, tidx } = options
|
|
64
|
-
const { baseUrl, basicAuth } = resolve(tidx, { chainId, principal })
|
|
65
|
-
return withTransientRetry(
|
|
67
|
+
const { baseUrl, basicAuth, bearerAuth } = resolve(tidx, { chainId, principal })
|
|
68
|
+
return withTransientRetry(
|
|
69
|
+
Tidx.create({
|
|
70
|
+
baseUrl,
|
|
71
|
+
basicAuth,
|
|
72
|
+
bearerAuth,
|
|
73
|
+
chainId,
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
66
76
|
}
|
|
67
77
|
|
|
68
78
|
/**
|
|
@@ -72,7 +82,7 @@ export function getClient(options: getClient.Options): Client {
|
|
|
72
82
|
* output (`baseUrl` + `basicAuth` + `chainId`), not the principal, so a resolver
|
|
73
83
|
* `tidx` may branch on any principal field while client cardinality stays
|
|
74
84
|
* bounded by the number of distinct upstreams — callers that resolve to the same
|
|
75
|
-
* upstream share a client. Shared by `
|
|
85
|
+
* upstream share a client. Shared by `data()` (per-request reads) and
|
|
76
86
|
* `Webhooks.createPoller` (the scheduled poller) so the resolver logic lives in
|
|
77
87
|
* one place.
|
|
78
88
|
*/
|
|
@@ -83,8 +93,8 @@ export function createGetClient(options: createGetClient.Options = {}): GetClien
|
|
|
83
93
|
return (chainId = defaultChainId, principal = null) => {
|
|
84
94
|
// Resolve to derive the cache key; `getClient` re-resolves to build the
|
|
85
95
|
// client on a miss. `resolve` is pure and cheap, so the extra call is free.
|
|
86
|
-
const { baseUrl, basicAuth } = resolve(tidx, { chainId, principal })
|
|
87
|
-
const cacheKey = `${baseUrl}|${basicAuth ?? ''}|${chainId}`
|
|
96
|
+
const { baseUrl, basicAuth, bearerAuth } = resolve(tidx, { chainId, principal })
|
|
97
|
+
const cacheKey = `${baseUrl}|${basicAuth ?? ''}|${bearerAuth ?? ''}|${chainId}`
|
|
88
98
|
const existing = clients.get(cacheKey)
|
|
89
99
|
if (existing) return existing
|
|
90
100
|
|
|
@@ -218,12 +228,16 @@ export declare namespace getClient {
|
|
|
218
228
|
baseUrl?: UrlResolver | string | undefined
|
|
219
229
|
/** Basic auth credentials for TIDX requests. */
|
|
220
230
|
basicAuth?: string | undefined
|
|
231
|
+
/** Bearer auth credential for TIDX requests. */
|
|
232
|
+
bearerAuth?: string | undefined
|
|
221
233
|
}
|
|
222
234
|
| ((context: Viem.resolve.Context) => {
|
|
223
235
|
/** TIDX base URL to use; falls back to the built-in public host when omitted. */
|
|
224
236
|
baseUrl?: string | undefined
|
|
225
237
|
/** Basic auth credentials for TIDX requests, or undefined for none. */
|
|
226
238
|
basicAuth?: string | undefined
|
|
239
|
+
/** Bearer auth credential for TIDX requests, or undefined for none. */
|
|
240
|
+
bearerAuth?: string | undefined
|
|
227
241
|
})
|
|
228
242
|
}
|
|
229
243
|
|
|
@@ -113,3 +113,49 @@ describe('resolve', () => {
|
|
|
113
113
|
`)
|
|
114
114
|
})
|
|
115
115
|
})
|
|
116
|
+
|
|
117
|
+
describe('createGetClient', () => {
|
|
118
|
+
test('memoizes one client per resolved upstream', () => {
|
|
119
|
+
const getClient = Viem.createGetClient({
|
|
120
|
+
rpc: ({ principal }) =>
|
|
121
|
+
principal?.type === 'public'
|
|
122
|
+
? { url: 'https://rpc.tempo.xyz' }
|
|
123
|
+
: { basicAuth: 'user:pass', url: 'https://internal.rpc' },
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
expect(getClient(4217, apiKeyPrincipal)).toBe(getClient(4217, apiKeyPrincipal))
|
|
127
|
+
expect(getClient(4217, publicPrincipal)).toBe(getClient(4217, publicPrincipal))
|
|
128
|
+
expect(getClient(4217, publicPrincipal)).not.toBe(getClient(4217, apiKeyPrincipal))
|
|
129
|
+
expect(getClient(4217, apiKeyPrincipal)).not.toBe(getClient(42431, apiKeyPrincipal))
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('shares a client across principals when they resolve identically', () => {
|
|
133
|
+
const getClient = Viem.createGetClient()
|
|
134
|
+
|
|
135
|
+
expect(getClient(4217, publicPrincipal)).toBe(getClient(4217, apiKeyPrincipal))
|
|
136
|
+
expect(getClient(4217, null)).toBe(getClient(4217, publicPrincipal))
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('consults the resolver on cache hits', () => {
|
|
140
|
+
const seen: (string | undefined)[] = []
|
|
141
|
+
const getClient = Viem.createGetClient({
|
|
142
|
+
rpc: ({ principal }) => {
|
|
143
|
+
seen.push(principal?.type)
|
|
144
|
+
return { url: 'https://internal.rpc' }
|
|
145
|
+
},
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
const first = getClient(4217, apiKeyPrincipal)
|
|
149
|
+
const second = getClient(4217, apiKeyPrincipal)
|
|
150
|
+
getClient(4217, publicPrincipal)
|
|
151
|
+
|
|
152
|
+
expect(seen).toMatchInlineSnapshot(`
|
|
153
|
+
[
|
|
154
|
+
"api_key",
|
|
155
|
+
"api_key",
|
|
156
|
+
"public",
|
|
157
|
+
]
|
|
158
|
+
`)
|
|
159
|
+
expect(first).toBe(second)
|
|
160
|
+
})
|
|
161
|
+
})
|
package/src/internal/Viem.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZoneRpcAuthentication } from 'ox/tempo'
|
|
1
2
|
import { createClient, http, publicActions } from 'viem'
|
|
2
3
|
import type { Client as core_Client, HttpTransport, PublicActions } from 'viem'
|
|
3
4
|
import { tempoActions } from 'viem/tempo'
|
|
@@ -57,7 +58,7 @@ export type UrlResolver = (chainId: ChainId) => string | undefined
|
|
|
57
58
|
* webhook poller). A missing `url` falls back to the built-in public host map
|
|
58
59
|
* ({@link url}); a missing `basicAuth` means no Basic auth is sent.
|
|
59
60
|
*
|
|
60
|
-
* Memoization is keyed on the resolved output (see
|
|
61
|
+
* Memoization is keyed on the resolved output (see {@link createGetClient} and
|
|
61
62
|
* {@link Tidx.createGetClient}), not the context, so a resolver may branch on
|
|
62
63
|
* any principal field without unbounded client cardinality: callers that
|
|
63
64
|
* resolve to the same upstream share a client. Pass the result to
|
|
@@ -103,8 +104,17 @@ export declare namespace resolve {
|
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
export function getClient(options: getClient.Options): getClient.ReturnType {
|
|
106
|
-
const { chainId = defaultChainId, principal = null, rpc } = options
|
|
107
|
+
const { chainId = defaultChainId, principal = null, rpc, zoneToken } = options
|
|
107
108
|
const { basicAuth, url: rpcUrl } = resolve(rpc, { chainId, principal })
|
|
109
|
+
const fetchOptions =
|
|
110
|
+
basicAuth || zoneToken
|
|
111
|
+
? {
|
|
112
|
+
headers: {
|
|
113
|
+
...(basicAuth ? { Authorization: `Basic ${btoa(basicAuth)}` } : {}),
|
|
114
|
+
...(zoneToken ? { [ZoneRpcAuthentication.headerName]: zoneToken } : {}),
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
: undefined
|
|
108
118
|
|
|
109
119
|
return createClient({
|
|
110
120
|
// Auto-batch `eth_call`s within the same macrotask into a single
|
|
@@ -114,15 +124,45 @@ export function getClient(options: getClient.Options): getClient.ReturnType {
|
|
|
114
124
|
// configure a deployed multicall3, can still serve the aggregated call.
|
|
115
125
|
batch: { multicall: { deployless: true } },
|
|
116
126
|
chain: { ...tempoMainnet, id: chainId },
|
|
117
|
-
transport: http(
|
|
118
|
-
rpcUrl,
|
|
119
|
-
basicAuth ? { fetchOptions: { headers: { Authorization: `Basic ${btoa(basicAuth)}` } } } : {},
|
|
120
|
-
),
|
|
127
|
+
transport: http(rpcUrl, fetchOptions ? { fetchOptions } : {}),
|
|
121
128
|
})
|
|
122
129
|
.extend(publicActions)
|
|
123
130
|
.extend(tempoActions())
|
|
124
131
|
}
|
|
125
132
|
|
|
133
|
+
/** Builds a memoized Tempo client resolver. */
|
|
134
|
+
export function createGetClient(options: createGetClient.Options = {}): createGetClient.ReturnType {
|
|
135
|
+
const { defaultChainId: defaultChainId_option = defaultChainId, rpc } = options
|
|
136
|
+
const clients = new Map<string, getClient.ReturnType>()
|
|
137
|
+
|
|
138
|
+
return (chainId = defaultChainId_option, principal = null) => {
|
|
139
|
+
const { basicAuth, url } = resolve(rpc, { chainId, principal })
|
|
140
|
+
const cacheKey = JSON.stringify([url, basicAuth, chainId])
|
|
141
|
+
const existing = clients.get(cacheKey)
|
|
142
|
+
if (existing) return existing
|
|
143
|
+
|
|
144
|
+
const client = getClient({
|
|
145
|
+
chainId,
|
|
146
|
+
rpc: { basicAuth, url: () => url },
|
|
147
|
+
})
|
|
148
|
+
clients.set(cacheKey, client)
|
|
149
|
+
return client
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export declare namespace createGetClient {
|
|
154
|
+
/** Options for building a memoized Tempo client resolver. */
|
|
155
|
+
type Options = {
|
|
156
|
+
/** Tempo chain id used when a caller omits one. */
|
|
157
|
+
defaultChainId?: ChainId | undefined
|
|
158
|
+
/** Tempo RPC options applied to every constructed client. */
|
|
159
|
+
rpc?: getClient.Rpc | undefined
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Memoized Tempo client resolver. */
|
|
163
|
+
type ReturnType = (chainId?: ChainId, principal?: Auth.Principal | null) => getClient.ReturnType
|
|
164
|
+
}
|
|
165
|
+
|
|
126
166
|
export declare namespace getClient {
|
|
127
167
|
/** Tempo viem client with public and Tempo action helpers. */
|
|
128
168
|
type ReturnType = core_Client<
|
|
@@ -142,6 +182,8 @@ export declare namespace getClient {
|
|
|
142
182
|
principal?: Auth.Principal | null | undefined
|
|
143
183
|
/** Tempo RPC options. */
|
|
144
184
|
rpc?: Rpc | undefined
|
|
185
|
+
/** Zone authorization token forwarded to the RPC node. */
|
|
186
|
+
zoneToken?: string | undefined
|
|
145
187
|
}
|
|
146
188
|
|
|
147
189
|
/**
|
package/src/internal/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export * as Cursor from './Cursor.js'
|
|
|
4
4
|
export * as EdgeCache from './EdgeCache.js'
|
|
5
5
|
export * as Errors from './Errors.js'
|
|
6
6
|
export * as Fees from './Fees.js'
|
|
7
|
-
export * as
|
|
7
|
+
export * as FundingQuotes from './FundingQuotes.js'
|
|
8
8
|
export * as Id from './Id.js'
|
|
9
9
|
export * as Log from './Log.js'
|
|
10
10
|
export * as MetricSink from './MetricSink.js'
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import * as FundingRoutes from '../../internal/FundingRoutes.js';
|
|
2
|
-
type Fetch = typeof globalThis.fetch;
|
|
3
|
-
/** Creates the live funding route adapters configured for this deployment. */
|
|
4
|
-
export declare function createAdapters(options?: createAdapters.Options): {
|
|
5
|
-
relay: FundingRoutes.ProviderAdapter;
|
|
6
|
-
} | {
|
|
7
|
-
relay?: never;
|
|
8
|
-
};
|
|
9
|
-
export declare namespace createAdapters {
|
|
10
|
-
/** Provider adapter factory options. Omit a provider to keep its routes static. */
|
|
11
|
-
type Options = {
|
|
12
|
-
/** Relay quote adapter options. */
|
|
13
|
-
relay?: relay.Options | false | undefined;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
/** Creates a Relay quote adapter backed by `/chains/liquidity` and `/quote/v2`. */
|
|
17
|
-
export declare function relay(options: relay.Options): FundingRoutes.ProviderAdapter;
|
|
18
|
-
export declare namespace relay {
|
|
19
|
-
/** Relay quote adapter options. */
|
|
20
|
-
type Options = {
|
|
21
|
-
/** Probe wallet address required by Relay's quote API. */
|
|
22
|
-
userAddress: string;
|
|
23
|
-
/** Optional recipient override; defaults to `userAddress`. */
|
|
24
|
-
recipientAddress?: string | undefined;
|
|
25
|
-
/** Optional Relay API key for higher rate limits. */
|
|
26
|
-
apiKey?: string | undefined;
|
|
27
|
-
/** Override for tests or Relay testnet environments. */
|
|
28
|
-
baseUrl?: string | undefined;
|
|
29
|
-
/** Fetch implementation override for tests. */
|
|
30
|
-
fetch?: Fetch | undefined;
|
|
31
|
-
/** Clock override for deterministic tests. */
|
|
32
|
-
now?: (() => Date) | undefined;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
export {};
|
|
36
|
-
//# sourceMappingURL=FundingRouteProviders.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FundingRouteProviders.d.ts","sourceRoot":"","sources":["../../../src/apps/data/FundingRouteProviders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,iCAAiC,CAAA;AAEhE,KAAK,KAAK,GAAG,OAAO,UAAU,CAAC,KAAK,CAAA;AAMpC,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,OAAO,GAAE,cAAc,CAAC,OAAY;;;;EAIlE;AAED,MAAM,CAAC,OAAO,WAAW,cAAc,CAAC;IACtC,mFAAmF;IACnF,KAAK,OAAO,GAAG;QACb,mCAAmC;QACnC,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,GAAG,SAAS,CAAA;KAC1C,CAAA;CACF;AAED,mFAAmF;AACnF,wBAAgB,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,aAAa,CAAC,eAAe,CAkD3E;AAED,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC;IAC7B,mCAAmC;IACnC,KAAK,OAAO,GAAG;QACb,0DAA0D;QAC1D,WAAW,EAAE,MAAM,CAAA;QACnB,8DAA8D;QAC9D,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACrC,qDAAqD;QACrD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC3B,wDAAwD;QACxD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC5B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;QACzB,8CAA8C;QAC9C,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAA;KAC/B,CAAA;CACF"}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import * as FundingRoutes from '../../internal/FundingRoutes.js';
|
|
2
|
-
const defaultFetch = (input, init) => globalThis.fetch(input, init);
|
|
3
|
-
const defaultRelayBaseUrl = 'https://api.relay.link';
|
|
4
|
-
/** Creates the live funding route adapters configured for this deployment. */
|
|
5
|
-
export function createAdapters(options = {}) {
|
|
6
|
-
return (options.relay ? { relay: relay(options.relay) } : {});
|
|
7
|
-
}
|
|
8
|
-
/** Creates a Relay quote adapter backed by `/chains/liquidity` and `/quote/v2`. */
|
|
9
|
-
export function relay(options) {
|
|
10
|
-
const baseUrl = normalizeBaseUrl(options.baseUrl ?? defaultRelayBaseUrl);
|
|
11
|
-
const fetcher = options.fetch ?? defaultFetch;
|
|
12
|
-
const now = options.now ?? (() => new Date());
|
|
13
|
-
return {
|
|
14
|
-
async probeQuote({ route }, signal) {
|
|
15
|
-
const originChainId = providerChainId(route.sourceChain, 'relay');
|
|
16
|
-
const destinationChainId = eip155ChainId(route.destinationChain);
|
|
17
|
-
const headers = relayHeaders(options.apiKey);
|
|
18
|
-
try {
|
|
19
|
-
const quote = await requestJson(new URL(`${baseUrl}/quote/v2`), {
|
|
20
|
-
body: {
|
|
21
|
-
amount: route.sourceAmount.amount,
|
|
22
|
-
destinationChainId: Number(destinationChainId),
|
|
23
|
-
destinationCurrency: route.destinationToken.address,
|
|
24
|
-
originChainId: Number(originChainId),
|
|
25
|
-
originCurrency: route.sourceToken.address,
|
|
26
|
-
recipient: options.recipientAddress ?? options.userAddress,
|
|
27
|
-
tradeType: 'EXACT_INPUT',
|
|
28
|
-
user: options.userAddress,
|
|
29
|
-
},
|
|
30
|
-
fetcher,
|
|
31
|
-
headers,
|
|
32
|
-
method: 'POST',
|
|
33
|
-
signal,
|
|
34
|
-
});
|
|
35
|
-
const liquidityUrl = new URL(`${baseUrl}/chains/liquidity`);
|
|
36
|
-
liquidityUrl.searchParams.set('chainId', destinationChainId);
|
|
37
|
-
const liquidity = await requestJson(liquidityUrl, { fetcher, headers, signal }).catch(() => undefined);
|
|
38
|
-
return formatRelayResult(route, quote, liquidity, now());
|
|
39
|
-
}
|
|
40
|
-
catch (cause) {
|
|
41
|
-
const unavailable = providerUnavailable(cause, [
|
|
42
|
-
'NO_QUOTES',
|
|
43
|
-
'NO_ROUTE',
|
|
44
|
-
'UNSUPPORTED_ROUTE',
|
|
45
|
-
]);
|
|
46
|
-
if (!unavailable)
|
|
47
|
-
throw cause;
|
|
48
|
-
return unavailableResult({
|
|
49
|
-
detail: 'relay:quote-v2',
|
|
50
|
-
message: unavailable,
|
|
51
|
-
now: now(),
|
|
52
|
-
source: 'providerQuote',
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function formatRelayResult(route, quote, liquidity, now) {
|
|
59
|
-
const details = record(record(quote)['details']);
|
|
60
|
-
const currencyOut = record(details['currencyOut']);
|
|
61
|
-
const outputAmount = decimalString(currencyOut['amount']);
|
|
62
|
-
const liquidityRow = relayLiquidity(liquidity, route);
|
|
63
|
-
const destinationLiquidity = decimalString(liquidityRow?.['balance']);
|
|
64
|
-
const availableVolumeUsd = decimalString(liquidityRow?.['amountUsd']) ?? null;
|
|
65
|
-
const liquidityStatus = relayLiquidityStatus({ destinationLiquidity, outputAmount });
|
|
66
|
-
return {
|
|
67
|
-
limits: null,
|
|
68
|
-
minimumOutputAmount: decimalString(currencyOut['minimumAmount']),
|
|
69
|
-
outputAmount,
|
|
70
|
-
outputAmountFormatted: outputAmount
|
|
71
|
-
? decimalFromBaseUnits(outputAmount, route.destinationToken.decimals)
|
|
72
|
-
: null,
|
|
73
|
-
quality: {
|
|
74
|
-
availableVolumeUsd: availableVolumeUsd,
|
|
75
|
-
estimatedSeconds: nonnegativeInteger(details['timeEstimate']),
|
|
76
|
-
feeBps: null,
|
|
77
|
-
historicalVolumeUsd24h: null,
|
|
78
|
-
instantVolumeUsd: availableVolumeUsd,
|
|
79
|
-
liquiditySource: 'providerQuote',
|
|
80
|
-
score: scoreFor(liquidityStatus.tier),
|
|
81
|
-
sourceDetail: 'relay:quote-v2',
|
|
82
|
-
tier: liquidityStatus.tier,
|
|
83
|
-
},
|
|
84
|
-
sampledAt: now.toISOString(),
|
|
85
|
-
status: liquidityStatus.status,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function relayLiquidityStatus(options) {
|
|
89
|
-
if (!options.outputAmount)
|
|
90
|
-
return { status: 'unknown', tier: 'unknown' };
|
|
91
|
-
if (!options.destinationLiquidity)
|
|
92
|
-
return { status: 'unknown', tier: 'unknown' };
|
|
93
|
-
if (compareIntegerStrings(options.destinationLiquidity, options.outputAmount) < 0)
|
|
94
|
-
return { status: 'thin', tier: 'thin' };
|
|
95
|
-
return { status: 'available', tier: 'liquid' };
|
|
96
|
-
}
|
|
97
|
-
function unavailableResult(options) {
|
|
98
|
-
return {
|
|
99
|
-
quality: {
|
|
100
|
-
availableVolumeUsd: null,
|
|
101
|
-
estimatedSeconds: null,
|
|
102
|
-
feeBps: null,
|
|
103
|
-
historicalVolumeUsd24h: null,
|
|
104
|
-
instantVolumeUsd: null,
|
|
105
|
-
liquiditySource: options.source,
|
|
106
|
-
score: 0,
|
|
107
|
-
sourceDetail: `${options.detail}:${options.message}`,
|
|
108
|
-
tier: 'unavailable',
|
|
109
|
-
},
|
|
110
|
-
sampledAt: options.now.toISOString(),
|
|
111
|
-
status: 'unavailable',
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
function relayLiquidity(input, route) {
|
|
115
|
-
const response = record(input);
|
|
116
|
-
const rows = Array.isArray(response['liquidity']) ? response['liquidity'] : [];
|
|
117
|
-
const destinationChainId = eip155ChainId(route.destinationChain);
|
|
118
|
-
return rows.map(record).find((row) => {
|
|
119
|
-
const rowChainId = integerString(row['chainId']);
|
|
120
|
-
const rowAddress = typeof row['address'] === 'string' ? row['address'].toLowerCase() : undefined;
|
|
121
|
-
return (rowChainId === destinationChainId &&
|
|
122
|
-
rowAddress === route.destinationToken.address.toLowerCase());
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
async function requestJson(url, options) {
|
|
126
|
-
const headers = { accept: 'application/json', ...options.headers };
|
|
127
|
-
const init = {
|
|
128
|
-
headers: options.body === undefined ? headers : { ...headers, 'content-type': 'application/json' },
|
|
129
|
-
method: options.method ?? 'GET',
|
|
130
|
-
signal: options.signal,
|
|
131
|
-
};
|
|
132
|
-
if (options.body !== undefined)
|
|
133
|
-
init.body = JSON.stringify(options.body);
|
|
134
|
-
const response = await options.fetcher(url, init);
|
|
135
|
-
const text = await response.text();
|
|
136
|
-
const body = parseJson(text);
|
|
137
|
-
if (!response.ok)
|
|
138
|
-
throw new ProviderResponseError(response.status, body);
|
|
139
|
-
return body;
|
|
140
|
-
}
|
|
141
|
-
function relayHeaders(apiKey) {
|
|
142
|
-
return apiKey ? { 'x-api-key': apiKey } : undefined;
|
|
143
|
-
}
|
|
144
|
-
function providerUnavailable(cause, codes) {
|
|
145
|
-
if (!(cause instanceof ProviderResponseError) || cause.status < 400 || cause.status >= 500)
|
|
146
|
-
return undefined;
|
|
147
|
-
const code = providerErrorCode(cause.body);
|
|
148
|
-
if (code && codes.includes(code))
|
|
149
|
-
return code;
|
|
150
|
-
return undefined;
|
|
151
|
-
}
|
|
152
|
-
function providerErrorCode(input) {
|
|
153
|
-
const body = record(input);
|
|
154
|
-
const code = stringValue(body['code']) ?? stringValue(body['errorCode']);
|
|
155
|
-
return code && /^[A-Za-z0-9_.:-]{1,64}$/.test(code) ? code : undefined;
|
|
156
|
-
}
|
|
157
|
-
class ProviderResponseError extends Error {
|
|
158
|
-
status;
|
|
159
|
-
body;
|
|
160
|
-
name = 'FundingRouteProviders.ProviderResponseError';
|
|
161
|
-
constructor(status, body) {
|
|
162
|
-
super(`Provider request failed with status ${status}`);
|
|
163
|
-
this.status = status;
|
|
164
|
-
this.body = body;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
function providerChainId(routeChain, provider) {
|
|
168
|
-
const providerIds = routeChain.providerIds;
|
|
169
|
-
const id = providerIds?.[provider];
|
|
170
|
-
if (id && /^\d+$/.test(id))
|
|
171
|
-
return id;
|
|
172
|
-
return eip155ChainId(routeChain);
|
|
173
|
-
}
|
|
174
|
-
function eip155ChainId(chain) {
|
|
175
|
-
if (chain.kind !== 'evm')
|
|
176
|
-
throw new UnsupportedProviderRouteError();
|
|
177
|
-
const match = /^eip155:(\d+)$/.exec(chain.id);
|
|
178
|
-
if (!match?.[1])
|
|
179
|
-
throw new UnsupportedProviderRouteError();
|
|
180
|
-
return match[1];
|
|
181
|
-
}
|
|
182
|
-
class UnsupportedProviderRouteError extends Error {
|
|
183
|
-
name = 'FundingRouteProviders.UnsupportedProviderRouteError';
|
|
184
|
-
}
|
|
185
|
-
function normalizeBaseUrl(input) {
|
|
186
|
-
return input.replace(/\/+$/, '');
|
|
187
|
-
}
|
|
188
|
-
function parseJson(input) {
|
|
189
|
-
if (!input)
|
|
190
|
-
return null;
|
|
191
|
-
try {
|
|
192
|
-
return JSON.parse(input);
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
return input;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
function record(input) {
|
|
199
|
-
return input && typeof input === 'object' && !Array.isArray(input)
|
|
200
|
-
? input
|
|
201
|
-
: {};
|
|
202
|
-
}
|
|
203
|
-
function stringValue(input) {
|
|
204
|
-
return typeof input === 'string' && input.length > 0 ? input : undefined;
|
|
205
|
-
}
|
|
206
|
-
function decimalString(input) {
|
|
207
|
-
if (typeof input === 'string' && /^\d+(\.\d+)?$/.test(input))
|
|
208
|
-
return input;
|
|
209
|
-
if (typeof input === 'number' && Number.isFinite(input) && input >= 0)
|
|
210
|
-
return String(input);
|
|
211
|
-
return undefined;
|
|
212
|
-
}
|
|
213
|
-
function integerString(input) {
|
|
214
|
-
if (typeof input === 'string' && /^\d+$/.test(input))
|
|
215
|
-
return input;
|
|
216
|
-
if (typeof input === 'number' && Number.isSafeInteger(input) && input >= 0)
|
|
217
|
-
return String(input);
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
function nonnegativeInteger(input) {
|
|
221
|
-
if (typeof input === 'number' && Number.isSafeInteger(input) && input >= 0)
|
|
222
|
-
return input;
|
|
223
|
-
if (typeof input === 'string' && /^\d+$/.test(input))
|
|
224
|
-
return Number(input);
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
function decimalFromBaseUnits(baseUnits, decimals) {
|
|
228
|
-
const padded = baseUnits.padStart(decimals + 1, '0');
|
|
229
|
-
const whole = decimals === 0 ? padded : padded.slice(0, -decimals);
|
|
230
|
-
const fraction = decimals === 0 ? '' : padded.slice(-decimals).replace(/0+$/, '');
|
|
231
|
-
return fraction ? `${whole}.${fraction}` : whole;
|
|
232
|
-
}
|
|
233
|
-
function compareIntegerStrings(left, right) {
|
|
234
|
-
return BigInt(left) === BigInt(right) ? 0 : BigInt(left) > BigInt(right) ? 1 : -1;
|
|
235
|
-
}
|
|
236
|
-
function scoreFor(tier) {
|
|
237
|
-
if (tier === 'liquid')
|
|
238
|
-
return 90;
|
|
239
|
-
if (tier === 'thin')
|
|
240
|
-
return 65;
|
|
241
|
-
if (tier === 'unavailable')
|
|
242
|
-
return 0;
|
|
243
|
-
return null;
|
|
244
|
-
}
|
|
245
|
-
//# sourceMappingURL=FundingRouteProviders.js.map
|