tapimo 0.4.0 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ApiKey.d.ts +1 -9
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +2 -3
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +53 -27
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +32 -17
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +2451 -1533
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +23 -9
- package/dist/App.js.map +1 -1
- package/dist/Assets.d.ts +10 -0
- package/dist/Assets.d.ts.map +1 -1
- package/dist/Assets.js +4 -0
- package/dist/Assets.js.map +1 -1
- package/dist/Auth.d.ts +2 -1
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js +2 -1
- package/dist/Auth.js.map +1 -1
- package/dist/Scope.d.ts +40 -15
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +44 -13
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +560 -9
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +38 -6
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +10 -24
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +10 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +833 -0
- package/dist/admin/apps/organizations.d.ts.map +1 -0
- package/dist/admin/apps/organizations.js +733 -0
- package/dist/admin/apps/organizations.js.map +1 -0
- package/dist/admin/apps/scopes.d.ts +8 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +53 -13
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts +10 -0
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +8 -0
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +9 -0
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +14 -0
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +1354 -984
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +20 -3
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingRouteProviders.d.ts +94 -5
- package/dist/apps/data/FundingRouteProviders.d.ts.map +1 -1
- package/dist/apps/data/FundingRouteProviders.js +196 -5
- package/dist/apps/data/FundingRouteProviders.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +38 -38
- package/dist/apps/data/routes/addresses.d.ts +24 -24
- package/dist/apps/data/routes/balances.d.ts +45 -45
- package/dist/apps/data/routes/blocks.d.ts +39 -39
- package/dist/apps/data/routes/coingecko.d.ts +176 -176
- package/dist/apps/data/routes/exchanges.d.ts +453 -453
- package/dist/apps/data/routes/fee-amm.d.ts +101 -101
- package/dist/apps/data/routes/funding.d.ts +730 -138
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +234 -0
- package/dist/apps/data/routes/funding.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +5 -5
- package/dist/apps/data/routes/rpc.d.ts +31 -31
- package/dist/apps/data/routes/verified-tokens.d.ts +81 -81
- package/dist/apps/management/App.d.ts +1156 -615
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -2
- package/dist/apps/management/Billing.d.ts +3 -0
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +7 -2
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +106 -90
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +41 -30
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +278 -146
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +14 -14
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +93 -20
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +12 -15
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +13 -13
- package/dist/apps/management/routes/members.d.ts +89 -18
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +10 -10
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +130 -70
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +19 -19
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +137 -48
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +12 -13
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/scopes.d.ts +14 -28
- package/dist/apps/management/routes/scopes.d.ts.map +1 -1
- package/dist/apps/management/routes/scopes.js +6 -7
- package/dist/apps/management/routes/scopes.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts +63 -19
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +9 -10
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +35 -3
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/relay/App.d.ts +26 -4
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +17 -14
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/db/Db.d.ts +5 -3
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +52 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +13 -0
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +16 -1
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/adminAuditLogs.d.ts +27 -0
- package/dist/db/tables/adminAuditLogs.d.ts.map +1 -0
- package/dist/db/tables/adminAuditLogs.js +19 -0
- package/dist/db/tables/adminAuditLogs.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +1 -1
- package/dist/db/tables/invitations.d.ts.map +1 -1
- package/dist/db/tables/memberships.d.ts +32 -4
- package/dist/db/tables/memberships.d.ts.map +1 -1
- package/dist/db/tables/memberships.js +31 -0
- package/dist/db/tables/memberships.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +43 -1
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +103 -0
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/projects.d.ts +25 -0
- package/dist/db/tables/projects.d.ts.map +1 -1
- package/dist/db/tables/projects.js +22 -0
- package/dist/db/tables/projects.js.map +1 -1
- package/dist/db/tables/webhookDeliveries.d.ts +26 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
- package/dist/db/tables/webhookDeliveries.js +37 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -1
- package/dist/handlers/relay.d.ts +13 -10
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +46 -16
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +13 -18
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +78 -58
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Cursor.d.ts +1 -1
- package/dist/internal/Cursor.d.ts.map +1 -1
- package/dist/internal/Cursor.js +4 -0
- package/dist/internal/Cursor.js.map +1 -1
- package/dist/internal/EdgeCache.d.ts.map +1 -1
- package/dist/internal/EdgeCache.js +2 -0
- package/dist/internal/EdgeCache.js.map +1 -1
- package/dist/internal/FundingRoutes.d.ts +170 -0
- package/dist/internal/FundingRoutes.d.ts.map +1 -1
- package/dist/internal/FundingRoutes.js +68 -6
- package/dist/internal/FundingRoutes.js.map +1 -1
- package/dist/internal/Log.d.ts +16 -1
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +5 -3
- package/dist/internal/Log.js.map +1 -1
- package/package.json +2 -2
- package/src/ApiKey.ts +2 -3
- package/src/ApiKeys.ts +95 -17
- package/src/App.test.ts +44 -2
- package/src/App.ts +29 -9
- package/src/Assets.ts +8 -0
- package/src/Auth.test-d.ts +36 -0
- package/src/Auth.ts +20 -1
- package/src/Client.test-d.ts +64 -17
- package/src/Scope.test.ts +34 -0
- package/src/Scope.ts +53 -17
- package/src/admin/App.test.ts +33 -3
- package/src/admin/App.ts +49 -14
- package/src/admin/apps/api-keys.ts +10 -3
- package/src/admin/apps/organizations.test.ts +455 -0
- package/src/admin/apps/organizations.ts +953 -0
- package/src/admin/apps/scopes.test.ts +10 -0
- package/src/admin/ui/plugin.ts +1 -1
- package/src/admin/ui/src/components/MobileProfile.tsx +2 -0
- package/src/admin/ui/src/components/ThemeToggle.tsx +20 -0
- package/src/admin/ui/src/lib/api-keys.ts +36 -19
- package/src/admin/ui/src/lib/config.ts +2 -3
- package/src/admin/ui/src/lib/organizations.test.ts +89 -0
- package/src/admin/ui/src/lib/organizations.ts +262 -0
- package/src/admin/ui/src/lib/query-client.ts +3 -1
- package/src/admin/ui/src/lib/theme.ts +57 -0
- package/src/admin/ui/src/routeTree.gen.ts +47 -4
- package/src/admin/ui/src/routes/__root.tsx +18 -3
- package/src/admin/ui/src/routes/api-keys.tsx +52 -7
- package/src/admin/ui/src/routes/index.tsx +1 -1
- package/src/admin/ui/src/routes/organizations.tsx +158 -0
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +710 -0
- package/src/admin/ui/src/start.ts +6 -0
- package/src/admin/ui.generated.ts +63 -13
- package/src/analytics/Analytics.ts +25 -0
- package/src/analytics/tables/requestEvents.ts +33 -0
- package/src/apps/composition.test.ts +82 -2
- package/src/apps/data/App.ts +24 -3
- package/src/apps/data/FundingRouteProviders.test.ts +204 -0
- package/src/apps/data/FundingRouteProviders.ts +294 -9
- package/src/apps/data/routes/funding.test.ts +90 -23
- package/src/apps/data/routes/funding.ts +315 -0
- package/src/apps/data/routes/rpc.test.ts +33 -0
- package/src/apps/management/App.ts +2 -2
- package/src/apps/management/Billing.ts +10 -2
- package/src/apps/management/routes/api-keys.test.ts +137 -1
- package/src/apps/management/routes/api-keys.ts +63 -38
- package/src/apps/management/routes/billing.ts +14 -14
- package/src/apps/management/routes/invitations.test.ts +102 -1
- package/src/apps/management/routes/invitations.ts +13 -15
- package/src/apps/management/routes/members.ts +10 -10
- package/src/apps/management/routes/orgs.test.ts +78 -16
- package/src/apps/management/routes/orgs.ts +21 -20
- package/src/apps/management/routes/projects.ts +12 -13
- package/src/apps/management/routes/scopes.test.ts +16 -0
- package/src/apps/management/routes/scopes.ts +6 -7
- package/src/apps/management/routes/usage.ts +9 -14
- package/src/apps/mcp.test.ts +25 -1
- package/src/apps/mcp.ts +43 -3
- package/src/apps/relay/App.test.ts +23 -18
- package/src/apps/relay/App.ts +35 -14
- package/src/db/Db.ts +59 -3
- package/src/db/Schema.ts +20 -1
- package/src/db/tables/adminAuditLogs.ts +47 -0
- package/src/db/tables/invitations.ts +1 -1
- package/src/db/tables/memberships.ts +59 -3
- package/src/db/tables/organizations.ts +148 -1
- package/src/db/tables/projects.ts +47 -0
- package/src/db/tables/webhookDeliveries.ts +83 -0
- package/src/handlers/relay.test-d.ts +8 -0
- package/src/handlers/relay.test.ts +2 -2
- package/src/handlers/relay.ts +62 -22
- package/src/internal/Auth.test.ts +174 -7
- package/src/internal/Auth.ts +90 -62
- package/src/internal/Cursor.test.ts +10 -0
- package/src/internal/Cursor.ts +5 -1
- package/src/internal/EdgeCache.test.ts +11 -0
- package/src/internal/EdgeCache.ts +2 -0
- package/src/internal/FundingRoutes.test.ts +26 -0
- package/src/internal/FundingRoutes.ts +187 -18
- package/src/internal/Log.test.ts +41 -3
- package/src/internal/Log.ts +23 -4
|
@@ -307,7 +307,9 @@ export type ChainRef = ReturnType<typeof formatChain> | typeof destinationChain
|
|
|
307
307
|
export type TokenAmount = ReturnType<typeof resolveSourceAmount>
|
|
308
308
|
|
|
309
309
|
/** Normalized token reference passed to provider adapters. */
|
|
310
|
-
export type TokenRef =
|
|
310
|
+
export type TokenRef =
|
|
311
|
+
| ReturnType<typeof formatDestinationToken>
|
|
312
|
+
| ReturnType<typeof formatSourceToken>
|
|
311
313
|
|
|
312
314
|
/** A normalized funding route candidate returned by route discovery. */
|
|
313
315
|
export type RouteCandidate = ReturnType<typeof formatRouteCandidate>
|
|
@@ -411,6 +413,64 @@ export type QuoteProbeResult = {
|
|
|
411
413
|
}
|
|
412
414
|
}
|
|
413
415
|
|
|
416
|
+
/** Token reference attached to a normalized provider fee. */
|
|
417
|
+
export type ProviderQuoteFeeToken = {
|
|
418
|
+
/** Token contract address on its chain. */
|
|
419
|
+
address: string
|
|
420
|
+
/** CAIP-2 chain id for the fee token. */
|
|
421
|
+
chainId: string
|
|
422
|
+
/** Number of decimal places used by the fee token. */
|
|
423
|
+
decimals: number
|
|
424
|
+
/** Fee token ticker symbol. */
|
|
425
|
+
symbol: string
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/** Normalized fee amount returned by a provider quote. */
|
|
429
|
+
export type ProviderQuoteFee = {
|
|
430
|
+
/** Fee amount in the fee token's base units. */
|
|
431
|
+
amount: string
|
|
432
|
+
/** Provider-estimated USD value of the fee. */
|
|
433
|
+
amountUsd: string | null
|
|
434
|
+
/** Fee as basis points of the quoted input, when available. */
|
|
435
|
+
bps: number | null
|
|
436
|
+
/** Token in which the fee amount is denominated. */
|
|
437
|
+
token: ProviderQuoteFeeToken
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** Input passed to a provider for one explicit, depositor-specific quote. */
|
|
441
|
+
export type ProviderQuoteInput = {
|
|
442
|
+
/** Address that would submit the funding transaction. */
|
|
443
|
+
depositor: string
|
|
444
|
+
/** Optional destination recipient; providers default it to the depositor. */
|
|
445
|
+
recipient?: string | undefined
|
|
446
|
+
/** Curated route selected by the caller. */
|
|
447
|
+
route: RouteCandidate
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** Dynamic data returned by an explicit provider quote. */
|
|
451
|
+
export type ProviderQuoteResult = {
|
|
452
|
+
/** Estimated settlement time in seconds. */
|
|
453
|
+
estimatedSeconds: number | null
|
|
454
|
+
/** Provider quote expiry timestamp. */
|
|
455
|
+
expiresAt: string
|
|
456
|
+
/** Current and maximum fee summaries. */
|
|
457
|
+
fees: {
|
|
458
|
+
/** Current estimated total fee. */
|
|
459
|
+
total: ProviderQuoteFee
|
|
460
|
+
/** Maximum total fee allowed by the quote. */
|
|
461
|
+
totalMax: ProviderQuoteFee
|
|
462
|
+
}
|
|
463
|
+
/** Slippage-adjusted minimum destination amount in base units. */
|
|
464
|
+
minimumOutputAmount: string
|
|
465
|
+
/** Expected destination amount in base units. */
|
|
466
|
+
outputAmount: string
|
|
467
|
+
/** Timestamp when Tempo sampled the quote. */
|
|
468
|
+
sampledAt: string
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/** A normalized explicit funding quote returned to callers. */
|
|
472
|
+
export type FundingQuote = ReturnType<typeof formatFundingQuote>
|
|
473
|
+
|
|
414
474
|
/** Adapter used to enrich a static route candidate with live provider information. */
|
|
415
475
|
export type ProviderAdapter = {
|
|
416
476
|
/** Probes provider-backed quote information for one static candidate. */
|
|
@@ -420,6 +480,12 @@ export type ProviderAdapter = {
|
|
|
420
480
|
/** Provider adapter registry, keyed by provider id. Missing adapters leave routes static. */
|
|
421
481
|
export type ProviderAdapters = Partial<Record<ProviderId, ProviderAdapter>>
|
|
422
482
|
|
|
483
|
+
/** Gets a depositor-specific quote without exposing provider execution payloads. */
|
|
484
|
+
export type ProviderQuote = (
|
|
485
|
+
input: ProviderQuoteInput,
|
|
486
|
+
signal: AbortSignal,
|
|
487
|
+
) => Promise<ProviderQuoteResult>
|
|
488
|
+
|
|
423
489
|
/** Static provider support rows used until live quote adapters are configured. */
|
|
424
490
|
const inventory: readonly InventoryEntry[] = [
|
|
425
491
|
{ destinationToken: 'usdce', provider: 'across', sourceChains: ['ethereum', 'base', 'bnb'], sourceTokens: ['USDC'] }, // prettier-ignore
|
|
@@ -437,6 +503,7 @@ type InventoryEntry = {
|
|
|
437
503
|
}
|
|
438
504
|
|
|
439
505
|
const defaultAdapterTimeoutMs = 750
|
|
506
|
+
const defaultQuoteTimeoutMs = 5_000
|
|
440
507
|
const includes = ['quotes'] as const
|
|
441
508
|
|
|
442
509
|
/** Lists normalized chains and source tokens that can fund Tempo. */
|
|
@@ -455,7 +522,10 @@ export function listProviders(options: listProviders.Options = {}) {
|
|
|
455
522
|
)
|
|
456
523
|
.map((provider) => ({
|
|
457
524
|
...formatProvider(provider),
|
|
458
|
-
status:
|
|
525
|
+
status:
|
|
526
|
+
options.adapters?.[provider.id] || options.configuredProviders?.includes(provider.id)
|
|
527
|
+
? ('configured' as const)
|
|
528
|
+
: provider.status,
|
|
459
529
|
}))
|
|
460
530
|
}
|
|
461
531
|
|
|
@@ -464,6 +534,8 @@ export declare namespace listProviders {
|
|
|
464
534
|
type Options = {
|
|
465
535
|
/** Provider adapters configured for this deployment. */
|
|
466
536
|
adapters?: ProviderAdapters | undefined
|
|
537
|
+
/** Providers configured through capabilities outside discovery adapters. */
|
|
538
|
+
configuredProviders?: readonly ProviderId[] | undefined
|
|
467
539
|
/** Provider capability to require. */
|
|
468
540
|
capability?: Capability | undefined
|
|
469
541
|
}
|
|
@@ -472,7 +544,10 @@ export declare namespace listProviders {
|
|
|
472
544
|
/** Parses the comma-separated `include` query parameter. */
|
|
473
545
|
export function parseInclude(input: string | undefined) {
|
|
474
546
|
if (input === undefined || input.trim() === '') return []
|
|
475
|
-
const parsed = input
|
|
547
|
+
const parsed = input
|
|
548
|
+
.split(',')
|
|
549
|
+
.map((part) => part.trim())
|
|
550
|
+
.filter(Boolean)
|
|
476
551
|
for (const include of parsed)
|
|
477
552
|
if (!(includes as readonly string[]).includes(include)) throw new UnsupportedIncludeError()
|
|
478
553
|
return [...new Set(parsed)] as readonly Include[]
|
|
@@ -506,6 +581,55 @@ export async function listRoutes(options: listRoutes.Options) {
|
|
|
506
581
|
)
|
|
507
582
|
}
|
|
508
583
|
|
|
584
|
+
/** Gets a depositor-specific quote for one curated funding route. */
|
|
585
|
+
export async function quoteRoute(options: quoteRoute.Options): Promise<FundingQuote> {
|
|
586
|
+
const [route] = listStaticRoutes({
|
|
587
|
+
destinationToken: options.destinationToken,
|
|
588
|
+
limit: 1,
|
|
589
|
+
provider: options.provider,
|
|
590
|
+
sourceAmount: options.sourceAmount,
|
|
591
|
+
sourceAmountUnits: options.sourceAmountUnits,
|
|
592
|
+
sourceChain: options.sourceChain,
|
|
593
|
+
sourceToken: options.sourceToken,
|
|
594
|
+
})
|
|
595
|
+
if (!route) throw new FundingRouteNotFoundError()
|
|
596
|
+
|
|
597
|
+
const quote = options.quote
|
|
598
|
+
if (!quote) throw new ProviderNotConfiguredError()
|
|
599
|
+
|
|
600
|
+
return formatFundingQuote(
|
|
601
|
+
route,
|
|
602
|
+
await runWithTimeout(
|
|
603
|
+
(signal) =>
|
|
604
|
+
quote(
|
|
605
|
+
{
|
|
606
|
+
depositor: options.depositor,
|
|
607
|
+
...(options.recipient === undefined ? {} : { recipient: options.recipient }),
|
|
608
|
+
route,
|
|
609
|
+
},
|
|
610
|
+
signal,
|
|
611
|
+
),
|
|
612
|
+
options.quoteTimeoutMs ?? defaultQuoteTimeoutMs,
|
|
613
|
+
),
|
|
614
|
+
)
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
export declare namespace quoteRoute {
|
|
618
|
+
/** Options for resolving and quoting one curated funding route. */
|
|
619
|
+
type Options = Omit<listStaticRoutes.Options, 'limit' | 'provider'> & {
|
|
620
|
+
/** Address that would submit the funding transaction. */
|
|
621
|
+
depositor: string
|
|
622
|
+
/** Configured provider quote capability. */
|
|
623
|
+
quote?: ProviderQuote | undefined
|
|
624
|
+
/** Provider selected for the quote. */
|
|
625
|
+
provider: 'across'
|
|
626
|
+
/** Maximum time allowed for the live provider request. */
|
|
627
|
+
quoteTimeoutMs?: number | undefined
|
|
628
|
+
/** Optional destination recipient; defaults to the depositor. */
|
|
629
|
+
recipient?: string | undefined
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
509
633
|
/** Lists static funding route candidates for a normalized caller request. */
|
|
510
634
|
export function listStaticRoutes(options: listStaticRoutes.Options) {
|
|
511
635
|
const sourceChain = resolveSourceChain(options.sourceChain)
|
|
@@ -608,19 +732,22 @@ async function enrichRoute(
|
|
|
608
732
|
if (!adapter) return route
|
|
609
733
|
|
|
610
734
|
try {
|
|
611
|
-
const quote = await
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
735
|
+
const quote = await runWithTimeout(
|
|
736
|
+
(signal) =>
|
|
737
|
+
adapter.probeQuote(
|
|
738
|
+
{
|
|
739
|
+
cache: options.cache,
|
|
740
|
+
destinationChain: route.destinationChain,
|
|
741
|
+
destinationToken: route.destinationToken,
|
|
742
|
+
include: options.include,
|
|
743
|
+
request: options.request,
|
|
744
|
+
route,
|
|
745
|
+
sourceAmount: route.sourceAmount,
|
|
746
|
+
sourceChain: route.sourceChain,
|
|
747
|
+
sourceToken: route.sourceToken,
|
|
748
|
+
},
|
|
749
|
+
signal,
|
|
750
|
+
),
|
|
624
751
|
options.timeoutMs,
|
|
625
752
|
)
|
|
626
753
|
return {
|
|
@@ -754,6 +881,28 @@ function formatRouteQuote(route: RouteCandidate, quote: QuoteProbeResult) {
|
|
|
754
881
|
} as const
|
|
755
882
|
}
|
|
756
883
|
|
|
884
|
+
function formatFundingQuote(route: RouteCandidate, quote: ProviderQuoteResult) {
|
|
885
|
+
return {
|
|
886
|
+
destinationChain: route.destinationChain,
|
|
887
|
+
destinationToken: route.destinationToken,
|
|
888
|
+
estimatedSeconds: quote.estimatedSeconds,
|
|
889
|
+
expiresAt: quote.expiresAt,
|
|
890
|
+
fees: quote.fees,
|
|
891
|
+
inputAmount: route.sourceAmount.amount,
|
|
892
|
+
minimumOutputAmount: quote.minimumOutputAmount,
|
|
893
|
+
outputAmount: quote.outputAmount,
|
|
894
|
+
outputAmountFormatted: decimalFromBaseUnits(
|
|
895
|
+
quote.outputAmount,
|
|
896
|
+
route.destinationToken.decimals,
|
|
897
|
+
),
|
|
898
|
+
provider: route.provider,
|
|
899
|
+
routeId: route.id,
|
|
900
|
+
sampledAt: quote.sampledAt,
|
|
901
|
+
sourceChain: route.sourceChain,
|
|
902
|
+
sourceToken: route.sourceToken,
|
|
903
|
+
} as const
|
|
904
|
+
}
|
|
905
|
+
|
|
757
906
|
function markRouteError(route: RouteCandidate, errorCode: string) {
|
|
758
907
|
return {
|
|
759
908
|
...route,
|
|
@@ -770,11 +919,11 @@ function markRouteError(route: RouteCandidate, errorCode: string) {
|
|
|
770
919
|
}
|
|
771
920
|
}
|
|
772
921
|
|
|
773
|
-
function
|
|
922
|
+
function runWithTimeout<result>(fn: (signal: AbortSignal) => Promise<result>, timeoutMs: number) {
|
|
774
923
|
const controller = new AbortController()
|
|
775
924
|
const timeout = setTimeout(() => controller.abort(), timeoutMs)
|
|
776
925
|
return Promise.race([
|
|
777
|
-
|
|
926
|
+
fn(controller.signal),
|
|
778
927
|
new Promise<never>((_, reject) => {
|
|
779
928
|
if (controller.signal.aborted) {
|
|
780
929
|
reject(new ProviderAdapterTimeoutError())
|
|
@@ -877,11 +1026,31 @@ export class InvalidAmountError extends Error {
|
|
|
877
1026
|
override name = 'FundingRoutes.InvalidAmountError'
|
|
878
1027
|
}
|
|
879
1028
|
|
|
1029
|
+
/** Error thrown when no curated route matches an explicit quote request. */
|
|
1030
|
+
export class FundingRouteNotFoundError extends Error {
|
|
1031
|
+
override name = 'FundingRoutes.FundingRouteNotFoundError'
|
|
1032
|
+
}
|
|
1033
|
+
|
|
880
1034
|
/** Error thrown internally when a provider adapter exceeds its route quote timeout. */
|
|
881
1035
|
export class ProviderAdapterTimeoutError extends Error {
|
|
882
1036
|
override name = 'FundingRoutes.ProviderAdapterTimeoutError'
|
|
883
1037
|
}
|
|
884
1038
|
|
|
1039
|
+
/** Error thrown when a requested provider quote is temporarily unavailable. */
|
|
1040
|
+
export class ProviderQuoteUnavailableError extends Error {
|
|
1041
|
+
override name = 'FundingRoutes.ProviderQuoteUnavailableError'
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/** Error thrown when a provider rate-limits a quote request. */
|
|
1045
|
+
export class ProviderRateLimitError extends Error {
|
|
1046
|
+
override name = 'FundingRoutes.ProviderRateLimitError'
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/** Error thrown when a route provider lacks explicit quote capability. */
|
|
1050
|
+
export class ProviderNotConfiguredError extends Error {
|
|
1051
|
+
override name = 'FundingRoutes.ProviderNotConfiguredError'
|
|
1052
|
+
}
|
|
1053
|
+
|
|
885
1054
|
/** Error thrown when the caller filters to an unknown provider. */
|
|
886
1055
|
export class UnsupportedProviderError extends Error {
|
|
887
1056
|
override name = 'FundingRoutes.UnsupportedProviderError'
|
package/src/internal/Log.test.ts
CHANGED
|
@@ -65,8 +65,7 @@ describe('middleware', () => {
|
|
|
65
65
|
})
|
|
66
66
|
api.get('/secure', (c) => c.json({ ok: true }, 200))
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
await api.request(`/secure?apiKey=${token}`)
|
|
68
|
+
await api.request('/secure?key=opaque-secret&chainId=mainnet')
|
|
70
69
|
|
|
71
70
|
expect(stable(entries[0]!)).toMatchInlineSnapshot(`
|
|
72
71
|
{
|
|
@@ -80,7 +79,7 @@ describe('middleware', () => {
|
|
|
80
79
|
"orgId": "org_1",
|
|
81
80
|
"type": "api_key",
|
|
82
81
|
},
|
|
83
|
-
"query": "
|
|
82
|
+
"query": "chainId=mainnet",
|
|
84
83
|
"route": "/secure",
|
|
85
84
|
"status": 200,
|
|
86
85
|
}
|
|
@@ -139,6 +138,45 @@ describe('middleware', () => {
|
|
|
139
138
|
`)
|
|
140
139
|
})
|
|
141
140
|
|
|
141
|
+
test('includes redacted provider failure details', async () => {
|
|
142
|
+
const entries: Log.Entry[] = []
|
|
143
|
+
const api = app({ emit: (entry) => void entries.push(entry) })
|
|
144
|
+
api.get('/provider', (c) => {
|
|
145
|
+
c.set('providerFailure', {
|
|
146
|
+
code: 'UNAUTHORIZED',
|
|
147
|
+
failure: 'http',
|
|
148
|
+
id: 'across',
|
|
149
|
+
operation: 'swap/approval',
|
|
150
|
+
status: 401,
|
|
151
|
+
})
|
|
152
|
+
return Response.error(c, {
|
|
153
|
+
code: 'provider_error',
|
|
154
|
+
message: 'Provider request failed',
|
|
155
|
+
status: 502,
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
await api.request('/provider')
|
|
160
|
+
|
|
161
|
+
expect(stable(entries[0]!)).toMatchInlineSnapshot(`
|
|
162
|
+
{
|
|
163
|
+
"errorCode": "provider_error",
|
|
164
|
+
"level": "error",
|
|
165
|
+
"method": "GET",
|
|
166
|
+
"path": "/provider",
|
|
167
|
+
"provider": {
|
|
168
|
+
"code": "UNAUTHORIZED",
|
|
169
|
+
"failure": "http",
|
|
170
|
+
"id": "across",
|
|
171
|
+
"operation": "swap/approval",
|
|
172
|
+
"status": 401,
|
|
173
|
+
},
|
|
174
|
+
"route": "/provider",
|
|
175
|
+
"status": 502,
|
|
176
|
+
}
|
|
177
|
+
`)
|
|
178
|
+
})
|
|
179
|
+
|
|
142
180
|
test('logs thrown errors at error level', async () => {
|
|
143
181
|
const entries: Log.Entry[] = []
|
|
144
182
|
const api = app({ emit: (entry) => void entries.push(entry) })
|
package/src/internal/Log.ts
CHANGED
|
@@ -10,6 +10,8 @@ import type * as Timing from './Timing.js'
|
|
|
10
10
|
export type Variables = {
|
|
11
11
|
/** Stable error code recorded by `Response.error` for the request log entry. */
|
|
12
12
|
errorCode?: string | undefined
|
|
13
|
+
/** Redacted provider failure details recorded by an upstream adapter. */
|
|
14
|
+
providerFailure?: Entry['provider'] | undefined
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
/** Hono environment shape used by the request logger. */
|
|
@@ -55,12 +57,27 @@ export type Entry = {
|
|
|
55
57
|
id: string
|
|
56
58
|
/** Owning organization id for API-key callers. */
|
|
57
59
|
orgId?: string | undefined
|
|
58
|
-
/**
|
|
60
|
+
/** Attributed project id for API-key callers. */
|
|
59
61
|
projectId?: string | undefined
|
|
60
62
|
/** Principal kind. */
|
|
61
63
|
type: 'api_key' | 'public' | 'session' | 'super_admin'
|
|
62
64
|
}
|
|
63
65
|
| undefined
|
|
66
|
+
/** Redacted upstream provider failure details, when an adapter request fails. */
|
|
67
|
+
provider?:
|
|
68
|
+
| {
|
|
69
|
+
/** Stable provider error code, when one is safe to retain. */
|
|
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
|
|
64
81
|
/** Raw query string (no leading `?`) with API-key tokens redacted, when present. */
|
|
65
82
|
query?: string | undefined
|
|
66
83
|
/** Rate limit state from the `RateLimit-*` response headers, when enforced. */
|
|
@@ -110,12 +127,15 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
110
127
|
const duration = performance.now() - start
|
|
111
128
|
|
|
112
129
|
const url = new URL(c.req.url)
|
|
130
|
+
url.searchParams.delete('key')
|
|
131
|
+
const query = ApiKey.redact(url.search.slice(1))
|
|
113
132
|
const status = c.res.status
|
|
114
133
|
// Hono cannot resolve variable types through the generic `environment`,
|
|
115
134
|
// so shared-variable reads are cast from the environment contract above
|
|
116
135
|
// (the same pattern EdgeCache uses for its cross-layer reads).
|
|
117
136
|
const principal = c.get('principal' as never) as Auth.Principal | undefined
|
|
118
137
|
const errorCode = c.get('errorCode' as never) as string | undefined
|
|
138
|
+
const provider = c.get('providerFailure' as never) as Entry['provider']
|
|
119
139
|
|
|
120
140
|
// The `request` total metric duplicates `duration` (measured here, one
|
|
121
141
|
// layer further out), so only operation timings are kept.
|
|
@@ -165,9 +185,8 @@ export function middleware<environment extends Environment = Environment>(
|
|
|
165
185
|
type: principal.type,
|
|
166
186
|
},
|
|
167
187
|
}),
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...(url.search.length > 1 ? { query: ApiKey.redact(url.search.slice(1)) } : {}),
|
|
188
|
+
...(provider === undefined ? {} : { provider }),
|
|
189
|
+
...(query ? { query } : {}),
|
|
171
190
|
...(rateLimit === undefined ? {} : { rateLimit }),
|
|
172
191
|
requestId: c.get('requestId' as never) as string,
|
|
173
192
|
route: c.req.routePath,
|