tapimo 0.4.3 → 0.5.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 +7222 -6316
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +4 -0
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +18 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +24 -3
- package/dist/Scope.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +116 -116
- package/dist/apps/data/App.d.ts +2541 -2607
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +135 -44
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/FundingQuoteProviders.d.ts +36 -0
- package/dist/apps/data/FundingQuoteProviders.d.ts.map +1 -0
- package/dist/apps/data/FundingQuoteProviders.js +190 -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 +242 -242
- package/dist/apps/data/routes/addresses.d.ts +227 -227
- package/dist/apps/data/routes/balances.d.ts +12 -12
- 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 +125 -126
- 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 +55 -54
- 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/exchanges.d.ts +455 -455
- package/dist/apps/data/routes/fee-amm.d.ts +92 -92
- package/dist/apps/data/routes/funding.d.ts +91 -864
- package/dist/apps/data/routes/funding.d.ts.map +1 -1
- package/dist/apps/data/routes/funding.js +138 -450
- package/dist/apps/data/routes/funding.js.map +1 -1
- 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 +36 -36
- 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 +1843 -861
- 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 +121 -121
- 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 +2 -2
- 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/me.d.ts +13 -13
- package/dist/apps/management/routes/members.d.ts +77 -77
- package/dist/apps/management/routes/orgs.d.ts +96 -96
- package/dist/apps/management/routes/projects.d.ts +62 -62
- package/dist/apps/management/routes/scopes.d.ts +11 -11
- 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 +79 -79
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +3 -1
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +42 -4
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/cloudflare.d.ts +2 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +4 -0
- package/dist/cloudflare.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/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 +42 -23
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +169 -20
- 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/Errors.d.ts +6 -0
- package/dist/internal/Errors.d.ts.map +1 -0
- package/dist/internal/Errors.js +16 -0
- package/dist/internal/Errors.js.map +1 -0
- package/dist/internal/FundingQuotes.d.ts +644 -0
- package/dist/internal/FundingQuotes.d.ts.map +1 -0
- package/dist/internal/{FundingRoutes.js → FundingQuotes.js} +93 -289
- package/dist/internal/FundingQuotes.js.map +1 -0
- package/dist/internal/Store.d.ts +61 -16
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +72 -17
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Viem.d.ts +2 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +11 -2
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/index.d.ts +27 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +27 -0
- package/dist/internal/index.js.map +1 -0
- package/package.json +8 -3
- package/src/ApiKeys.test.ts +23 -0
- package/src/App.test-d.ts +2 -0
- package/src/App.test.ts +60 -4
- package/src/App.ts +6 -0
- package/src/Client.test-d.ts +16 -54
- package/src/Scope.test.ts +1 -0
- package/src/Scope.ts +30 -4
- package/src/apps/data/App.test.ts +354 -0
- package/src/apps/data/App.ts +159 -52
- package/src/apps/data/FundingQuoteProviders.test.ts +151 -0
- package/src/apps/data/FundingQuoteProviders.ts +251 -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 +149 -306
- package/src/apps/data/routes/funding.ts +154 -604
- package/src/apps/data/routes/indexer.test.ts +99 -3
- 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 +23 -2
- 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/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 +55 -14
- package/src/apps/mcp.ts +3 -1
- package/src/apps/relay/App.test.ts +324 -4
- package/src/apps/relay/App.ts +40 -4
- package/src/cloudflare.ts +5 -0
- package/src/db/Db.ts +65 -0
- package/src/db/Schema.ts +39 -0
- package/src/db/tables/inviteLinks.ts +187 -0
- package/src/db/tables/organizations.ts +2 -0
- package/src/handlers/relay.ts +16 -4
- package/src/internal/Auth.test.ts +528 -37
- package/src/internal/Auth.ts +246 -45
- package/src/internal/EdgeCache.test.ts +24 -3
- package/src/internal/EdgeCache.ts +18 -2
- package/src/internal/FundingQuotes.test.ts +174 -0
- package/src/internal/FundingQuotes.ts +735 -0
- package/src/internal/Log.test.ts +4 -4
- package/src/internal/Store.test-d.ts +15 -0
- package/src/internal/Store.test.ts +153 -2
- package/src/internal/Store.ts +157 -41
- package/src/internal/Viem.ts +14 -5
- package/src/internal/index.test.ts +34 -0
- package/src/internal/index.ts +26 -0
- package/dist/apps/data/FundingRouteProviders.d.ts +0 -143
- package/dist/apps/data/FundingRouteProviders.d.ts.map +0 -1
- package/dist/apps/data/FundingRouteProviders.js +0 -546
- package/dist/apps/data/FundingRouteProviders.js.map +0 -1
- package/dist/internal/FundingRoutes.d.ts +0 -1085
- 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 -485
- package/src/apps/data/FundingRouteProviders.ts +0 -744
- package/src/internal/FundingRoutes.test.ts +0 -239
- package/src/internal/FundingRoutes.ts +0 -1067
|
@@ -2,32 +2,31 @@ import { Hono } from 'hono';
|
|
|
2
2
|
import * as z from 'zod/mini';
|
|
3
3
|
import * as Auth from '../../../internal/Auth.js';
|
|
4
4
|
import * as Cache from '../../../internal/Cache.js';
|
|
5
|
-
import * as
|
|
5
|
+
import * as FundingQuotes from '../../../internal/FundingQuotes.js';
|
|
6
6
|
import * as OpenApi from '../../../internal/OpenApi.js';
|
|
7
7
|
import * as Response from '../../../internal/Response.js';
|
|
8
8
|
import * as Schema from '../../../internal/Schema.js';
|
|
9
|
-
|
|
10
|
-
/** Zod schemas owned by the funding routes resource. */
|
|
9
|
+
/** Zod schemas owned by funding quote resources. */
|
|
11
10
|
export var schema;
|
|
12
11
|
(function (schema) {
|
|
13
12
|
/** Source or destination chain reference. */
|
|
14
13
|
schema.Chain = Schema.describe(z.object({
|
|
15
14
|
addressFormat: z
|
|
16
|
-
.
|
|
15
|
+
.literal('evm')
|
|
17
16
|
.check(z.describe('Address family used by accounts and token identifiers on this chain.'), z.meta({ examples: ['evm'] })),
|
|
18
17
|
id: z
|
|
19
18
|
.string()
|
|
20
|
-
.check(z.describe('Stable
|
|
19
|
+
.check(z.describe('Stable CAIP-2 chain id, represented as a string instead of the numeric `chainId` used elsewhere.'), z.meta({ examples: ['eip155:8453'] })),
|
|
21
20
|
kind: z
|
|
22
|
-
.
|
|
21
|
+
.literal('evm')
|
|
23
22
|
.check(z.describe('Chain execution family used for provider routing.'), z.meta({ examples: ['evm'] })),
|
|
24
23
|
name: z
|
|
25
24
|
.string()
|
|
26
25
|
.check(z.describe('Human-readable chain name.'), z.meta({ examples: ['Base'] })),
|
|
27
26
|
providerIds: z
|
|
28
27
|
.optional(z.record(z.string(), z.string()))
|
|
29
|
-
.check(z.describe('Provider-specific chain ids Tempo uses when
|
|
30
|
-
}), 'A normalized chain reference for funding
|
|
28
|
+
.check(z.describe('Provider-specific chain ids Tempo uses when requesting quotes.'), z.meta({ examples: [{ relay: '8453' }] })),
|
|
29
|
+
}), 'A normalized chain reference for funding quotes.');
|
|
31
30
|
/** Source or destination token reference. */
|
|
32
31
|
schema.Token = Schema.describe(z.object({
|
|
33
32
|
address: z
|
|
@@ -53,179 +52,81 @@ export var schema;
|
|
|
53
52
|
})),
|
|
54
53
|
verified: z
|
|
55
54
|
.boolean()
|
|
56
|
-
.check(z.describe('Whether Tempo recognizes this token in its funding
|
|
57
|
-
}), 'A normalized token reference for funding
|
|
58
|
-
/** Source amount echoed by a funding
|
|
55
|
+
.check(z.describe('Whether Tempo recognizes this token in its funding quote inventory.'), z.meta({ examples: [true] })),
|
|
56
|
+
}), 'A normalized token reference for funding quotes.');
|
|
57
|
+
/** Source amount echoed by a funding quote response. */
|
|
59
58
|
schema.TokenAmount = Schema.describe(z.object({
|
|
60
59
|
amount: Schema.DecimalString.check(z.describe("The requested source amount in the token's smallest unit.")),
|
|
61
60
|
formatted: z
|
|
62
61
|
.string()
|
|
63
62
|
.check(z.describe('The same amount in human-readable decimal form, using the source token’s `decimals`.'), z.meta({ examples: ['1'] })),
|
|
64
|
-
usd: z
|
|
65
|
-
.nullable(z.string())
|
|
66
|
-
.check(z.describe('USD estimate for the requested source amount, when available.'), z.meta({ examples: ['1.00'] })),
|
|
67
63
|
}), 'The requested source amount in provider-safe base units and display form.');
|
|
68
|
-
/** Provider summary embedded in a
|
|
64
|
+
/** Provider summary embedded in a funding quote. */
|
|
69
65
|
schema.ProviderRef = Schema.describe(z.object({
|
|
70
|
-
id: z
|
|
66
|
+
id: z
|
|
67
|
+
.literal('relay')
|
|
68
|
+
.check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
|
|
71
69
|
kind: z
|
|
72
70
|
.string()
|
|
73
|
-
.check(z.describe('Provider category, such as
|
|
71
|
+
.check(z.describe('Provider category, such as a solver network or aggregator.'), z.meta({ examples: ['solverNetwork'] })),
|
|
74
72
|
name: z
|
|
75
73
|
.string()
|
|
76
|
-
.check(z.describe('Human-readable provider name.'), z.meta({ examples: ['
|
|
74
|
+
.check(z.describe('Human-readable provider name.'), z.meta({ examples: ['Relay'] })),
|
|
77
75
|
requiresApiKey: z
|
|
78
76
|
.boolean()
|
|
79
|
-
.check(z.describe('Whether Tempo needs provider credentials to query or use this provider.'), z.meta({ examples: [
|
|
80
|
-
}), 'Provider metadata embedded in a
|
|
81
|
-
/**
|
|
77
|
+
.check(z.describe('Whether Tempo needs provider credentials to query or use this provider.'), z.meta({ examples: [false] })),
|
|
78
|
+
}), 'Provider metadata embedded in a funding quote.');
|
|
79
|
+
/** Quote quality signals exposed directly instead of implied by list order. */
|
|
82
80
|
schema.Quality = Schema.describe(z.object({
|
|
83
|
-
availableVolumeUsd: z
|
|
84
|
-
.nullable(z.string())
|
|
85
|
-
.check(z.describe('Available USD capacity, when available.'), z.meta({ examples: ['1114274.43'] })),
|
|
86
81
|
estimatedSeconds: z
|
|
87
|
-
.
|
|
82
|
+
.optional(z.number().check(z.int(), z.nonnegative()))
|
|
88
83
|
.check(z.describe('Estimated settlement time in seconds, when known.'), z.meta({ examples: [2] })),
|
|
89
|
-
feeBps: z
|
|
90
|
-
.nullable(z.number().check(z.int(), z.nonnegative()))
|
|
91
|
-
.check(z.describe('Estimated fee in basis points, when known.'), z.meta({ examples: [109] })),
|
|
92
|
-
historicalVolumeUsd24h: z
|
|
93
|
-
.nullable(z.string())
|
|
94
|
-
.check(z.describe('24h routed volume in USD, when available.'), z.meta({ examples: ['250000.00'] })),
|
|
95
|
-
instantVolumeUsd: z
|
|
96
|
-
.nullable(z.string())
|
|
97
|
-
.check(z.describe('Instant USD capacity, when available.'), z.meta({ examples: ['12453.94'] })),
|
|
98
84
|
liquiditySource: z
|
|
99
85
|
.string()
|
|
100
|
-
.check(z.describe('
|
|
101
|
-
score: z
|
|
102
|
-
.nullable(z.number().check(z.int(), z.gte(0), z.lte(100)))
|
|
103
|
-
.check(z.describe('Explainable route score from 0 to 100, when enough signals are available.'), z.meta({ examples: [91] })),
|
|
86
|
+
.check(z.describe('Provider source for the live quote quality signal.'), z.meta({ examples: ['providerQuote'] })),
|
|
104
87
|
sourceDetail: z
|
|
105
|
-
.
|
|
88
|
+
.optional(z.string())
|
|
106
89
|
.check(z.describe('Provider-specific source or endpoint detail for the quality signal.'), z.meta({ examples: ['providerEndpoint'] })),
|
|
107
90
|
tier: z
|
|
108
|
-
.enum(['liquid', 'thin'
|
|
109
|
-
.check(z.describe('Machine-readable
|
|
110
|
-
}), 'Machine-readable liquidity, fee, and source signals for a
|
|
111
|
-
/** Provider-derived
|
|
112
|
-
schema.
|
|
113
|
-
expiresAt: z
|
|
114
|
-
.nullable(z.iso.datetime())
|
|
115
|
-
.check(z.describe('Provider quote expiry timestamp.'), z.meta({ examples: ['2026-01-01T00:00:30Z'] })),
|
|
91
|
+
.enum(['liquid', 'thin'])
|
|
92
|
+
.check(z.describe('Machine-readable quality tier for a successful quote.'), z.meta({ examples: ['liquid'] })),
|
|
93
|
+
}), 'Machine-readable liquidity, fee, and source signals for a successful quote.');
|
|
94
|
+
/** Provider-derived output, limits, and freshness data. */
|
|
95
|
+
schema.QuoteDetails = Schema.describe(z.object({
|
|
116
96
|
inputAmount: Schema.DecimalString.check(z.describe('Source amount sent to the provider in base units.'), z.meta({ examples: ['1000000'] })),
|
|
117
|
-
limits: z
|
|
118
|
-
.nullable(z.object({
|
|
119
|
-
instantSourceAmount: z
|
|
120
|
-
.nullable(Schema.DecimalString)
|
|
121
|
-
.check(z.describe('Provider-reported instant source amount capacity.'), z.meta({ examples: ['12453940000'] })),
|
|
122
|
-
maxSourceAmount: z
|
|
123
|
-
.nullable(Schema.DecimalString)
|
|
124
|
-
.check(z.describe('Provider-reported maximum source amount.'), z.meta({ examples: ['1114274433200'] })),
|
|
125
|
-
minSourceAmount: z
|
|
126
|
-
.nullable(Schema.DecimalString)
|
|
127
|
-
.check(z.describe('Provider-reported minimum source amount.'), z.meta({ examples: ['500063'] })),
|
|
128
|
-
}))
|
|
129
|
-
.check(z.describe('Provider limits expressed in source base units.')),
|
|
130
97
|
minimumOutputAmount: z
|
|
131
|
-
.
|
|
98
|
+
.optional(Schema.DecimalString)
|
|
132
99
|
.check(z.describe('Slippage-adjusted minimum destination amount in base units.'), z.meta({ examples: ['988000'] })),
|
|
133
100
|
outputAmount: z
|
|
134
|
-
.
|
|
101
|
+
.string()
|
|
102
|
+
.check(z.regex(/^\d+$/))
|
|
135
103
|
.check(z.describe('Expected destination amount in base units.'), z.meta({ examples: ['989102'] })),
|
|
136
104
|
outputAmountFormatted: z
|
|
137
|
-
.
|
|
105
|
+
.string()
|
|
138
106
|
.check(z.describe('Expected destination amount rendered with destination token decimals.'), z.meta({ examples: ['0.989102'] })),
|
|
139
107
|
sampledAt: z.iso
|
|
140
108
|
.datetime()
|
|
141
|
-
.check(z.describe('Timestamp for the live quote
|
|
142
|
-
}), 'Provider-derived
|
|
143
|
-
/**
|
|
144
|
-
schema.QuoteFeeToken = Schema.describe(z.object({
|
|
145
|
-
address: z
|
|
146
|
-
.string()
|
|
147
|
-
.check(z.describe('Contract address of the fee token.'), z.meta({ examples: ['0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'] })),
|
|
148
|
-
chainId: z
|
|
149
|
-
.string()
|
|
150
|
-
.check(z.describe('CAIP-2 chain id of the fee token.'), z.meta({ examples: ['eip155:8453'] })), // prettier-ignore
|
|
151
|
-
decimals: z
|
|
152
|
-
.number()
|
|
153
|
-
.check(z.int(), z.nonnegative(), z.describe('Number of decimal places used by the fee token.'), z.meta({ examples: [6] })),
|
|
154
|
-
symbol: z
|
|
155
|
-
.string()
|
|
156
|
-
.check(z.describe('Ticker symbol of the fee token.'), z.meta({ examples: ['USDC'] })),
|
|
157
|
-
}), 'Token in which a normalized quote fee is denominated.');
|
|
158
|
-
/** Normalized fee summary for an explicit funding quote. */
|
|
159
|
-
schema.QuoteFee = Schema.describe(z.object({
|
|
160
|
-
amount: Schema.DecimalString.check(z.describe("Fee amount in the fee token's smallest unit."), z.meta({ examples: ['1200'] })),
|
|
161
|
-
amountUsd: z
|
|
162
|
-
.nullable(z.string().check(z.regex(/^\d+(\.\d+)?$/)))
|
|
163
|
-
.check(z.describe('Provider-estimated USD value of the fee.'), z.meta({ examples: ['0.0012'] })),
|
|
164
|
-
bps: z
|
|
165
|
-
.nullable(z.number().check(z.int(), z.nonnegative()))
|
|
166
|
-
.check(z.describe('Fee as basis points of the quoted input.'), z.meta({ examples: [12] })),
|
|
167
|
-
token: schema.QuoteFeeToken,
|
|
168
|
-
}), 'Provider-neutral fee amount and denomination.');
|
|
169
|
-
/** Explicit depositor-specific quote for one curated funding route. */
|
|
109
|
+
.check(z.describe('Timestamp for the live quote probe.'), z.meta({ examples: ['2026-01-01T00:00:00Z'] })),
|
|
110
|
+
}), 'Provider-derived output, limits, and freshness data for a funding quote.');
|
|
111
|
+
/** Successful live funding quote. */
|
|
170
112
|
schema.FundingQuote = Schema.describe(z.object({
|
|
171
|
-
destinationChain: schema.Chain.check(z.describe('Destination chain for the quoted route.')),
|
|
172
|
-
destinationToken: schema.Token.check(z.describe('Token received on the destination chain.')),
|
|
173
|
-
estimatedSeconds: z
|
|
174
|
-
.nullable(z.number().check(z.int(), z.nonnegative()))
|
|
175
|
-
.check(z.describe('Estimated settlement time in seconds.'), z.meta({ examples: [2] })),
|
|
176
|
-
expiresAt: z.iso
|
|
177
|
-
.datetime()
|
|
178
|
-
.check(z.describe('Timestamp after which the quote must not be used.'), z.meta({ examples: ['2026-01-01T00:01:00Z'] })),
|
|
179
|
-
fees: z
|
|
180
|
-
.object({
|
|
181
|
-
total: schema.QuoteFee.check(z.describe('Current estimated total fee.')),
|
|
182
|
-
totalMax: schema.QuoteFee.check(z.describe('Maximum total fee allowed by the quote.')),
|
|
183
|
-
})
|
|
184
|
-
.check(z.describe('Current and maximum provider fee summaries.')),
|
|
185
|
-
inputAmount: Schema.DecimalString.check(z.describe('Exact source amount quoted in base units.'), z.meta({ examples: ['1000000'] })),
|
|
186
|
-
minimumOutputAmount: Schema.DecimalString.check(z.describe('Slippage-adjusted minimum destination amount in base units.'), z.meta({ examples: ['988000'] })),
|
|
187
|
-
outputAmount: Schema.DecimalString.check(z.describe('Expected destination amount in base units.'), z.meta({ examples: ['990000'] })),
|
|
188
|
-
outputAmountFormatted: z
|
|
189
|
-
.string()
|
|
190
|
-
.check(z.describe('Expected destination amount rendered with token decimals.'), z.meta({ examples: ['0.99'] })),
|
|
191
|
-
provider: schema.ProviderRef.check(z.describe('Provider that produced the quote.')),
|
|
192
|
-
routeId: z
|
|
193
|
-
.string()
|
|
194
|
-
.check(z.describe('Stable id of the curated route that was quoted.'), z.meta({ examples: ['base-usdc-tempo-usdce-across'] })),
|
|
195
|
-
sampledAt: z.iso
|
|
196
|
-
.datetime()
|
|
197
|
-
.check(z.describe('Timestamp when Tempo sampled the provider quote.'), z.meta({ examples: ['2026-01-01T00:00:00Z'] })),
|
|
198
|
-
sourceChain: schema.Chain.check(z.describe('Source chain for the quoted route.')),
|
|
199
|
-
sourceToken: schema.Token.check(z.describe('Token spent on the source chain.')),
|
|
200
|
-
}), 'Normalized quote information without provider execution payloads.');
|
|
201
|
-
/** Static or live funding route candidate. */
|
|
202
|
-
schema.RouteCandidate = Schema.describe(z.object({
|
|
203
113
|
destinationChain: schema.Chain.check(z.describe('Destination chain, always Tempo mainnet in V1.')),
|
|
204
|
-
destinationToken: schema.Token.check(z.describe('Tempo token expected from this
|
|
205
|
-
errorCode: z
|
|
206
|
-
.nullable(z.string())
|
|
207
|
-
.check(z.describe('Stable route error code, when status is `error`.'), z.meta({ examples: ['provider_timeout'] })),
|
|
114
|
+
destinationToken: schema.Token.check(z.describe('Tempo token expected from this quote.')),
|
|
208
115
|
id: z
|
|
209
116
|
.string()
|
|
210
|
-
.check(z.describe('Stable deterministic
|
|
117
|
+
.check(z.describe('Stable deterministic funding quote id.'), z.meta({ examples: ['base-usdc-tempo-usdce-relay'] })),
|
|
211
118
|
provider: schema.ProviderRef,
|
|
212
119
|
quality: schema.Quality,
|
|
213
|
-
quote:
|
|
214
|
-
.nullable(schema.RouteQuote)
|
|
215
|
-
.check(z.describe('Provider-derived quote data, when a live route probe succeeds.')),
|
|
120
|
+
quote: schema.QuoteDetails,
|
|
216
121
|
sourceAmount: schema.TokenAmount,
|
|
217
122
|
sourceChain: schema.Chain.check(z.describe('Chain where the caller currently holds funds.')),
|
|
218
123
|
sourceToken: schema.Token.check(z.describe('Token the caller currently holds.')),
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
.check(z.describe('Provider-specific route status for the requested amount.'), z.meta({ examples: ['unknown'] })),
|
|
222
|
-
}), 'One provider-specific funding route candidate.');
|
|
223
|
-
/** Generic provider catalog entry. */
|
|
124
|
+
}), 'One successful provider-specific funding quote.');
|
|
125
|
+
/** Funding quote provider catalog entry. */
|
|
224
126
|
schema.Provider = Schema.describe(z.object({
|
|
225
|
-
|
|
226
|
-
.
|
|
227
|
-
.check(z.describe('
|
|
228
|
-
id: z.string().check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
|
|
127
|
+
id: z
|
|
128
|
+
.literal('relay')
|
|
129
|
+
.check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
|
|
229
130
|
kind: z
|
|
230
131
|
.string()
|
|
231
132
|
.check(z.describe('Provider category.'), z.meta({ examples: ['solverNetwork'] })),
|
|
@@ -236,87 +137,44 @@ export var schema;
|
|
|
236
137
|
.boolean()
|
|
237
138
|
.check(z.describe('Whether Tempo needs provider credentials to query or use this provider.'), z.meta({ examples: [false] })),
|
|
238
139
|
status: z
|
|
239
|
-
.enum(['configured', '
|
|
240
|
-
.check(z.describe('`
|
|
241
|
-
}), 'One
|
|
140
|
+
.enum(['configured', 'unconfigured'])
|
|
141
|
+
.check(z.describe('`configured` means live quotes are enabled for this deployment. `unconfigured` means the provider is supported but unavailable here.'), z.meta({ examples: ['configured', 'unconfigured'] })),
|
|
142
|
+
}), 'One funding quote provider.');
|
|
242
143
|
/** Chain inventory entry returned by the funding chains endpoint. */
|
|
243
144
|
schema.ChainInventory = Schema.describe(z.extend(schema.Chain, {
|
|
244
145
|
tokens: z.array(schema.Token).check(z.describe('Stablecoins known on this source chain.')),
|
|
245
146
|
}), 'One source chain and its known stablecoin inventory.');
|
|
246
|
-
/** Schemas for the
|
|
247
|
-
let
|
|
248
|
-
(function (
|
|
249
|
-
/** Query parameters for funding
|
|
250
|
-
|
|
147
|
+
/** Schemas for the quoteFunding operation. */
|
|
148
|
+
let quoteFunding;
|
|
149
|
+
(function (quoteFunding) {
|
|
150
|
+
/** Query parameters for live funding quotes. */
|
|
151
|
+
quoteFunding.Query = z
|
|
251
152
|
.strictObject({
|
|
252
153
|
destinationToken: z
|
|
253
154
|
.optional(z.string())
|
|
254
155
|
.check(z.describe('Tempo destination token symbol, address, or token key. Defaults to USDC.e.'), z.meta({ examples: ['USDC.e'] })),
|
|
255
|
-
include: z
|
|
256
|
-
.optional(z.string())
|
|
257
|
-
.check(z.describe('Comma-separated response expansions. V1 accepts `quotes`.'), z.meta({ examples: ['quotes'] })),
|
|
258
|
-
limit: Schema.Limit,
|
|
259
156
|
provider: z
|
|
260
|
-
.optional(z.
|
|
261
|
-
.check(z.describe('Only
|
|
157
|
+
.optional(z.literal('relay'))
|
|
158
|
+
.check(z.describe('Only request a quote from this provider. The supported id is `relay`; omit it to query every configured provider.'), z.meta({ examples: ['relay'] })),
|
|
262
159
|
sourceAmount: z
|
|
263
160
|
.string()
|
|
264
|
-
.check(z.
|
|
161
|
+
.check(z.regex(/^(?=.*[1-9])\d+(\.\d+)?$/), z.describe('Positive source token amount. Base units by default, so 1 USDC is `1000000`.'), z.meta({ examples: ['1000000'] })),
|
|
265
162
|
sourceAmountUnits: z
|
|
266
163
|
._default(z.enum(['baseUnits', 'decimal']), 'baseUnits')
|
|
267
164
|
.check(z.describe('Whether `sourceAmount` is base units or a human-readable decimal.'), z.meta({ examples: ['baseUnits', 'decimal'] })),
|
|
268
165
|
sourceChain: z
|
|
269
166
|
.string()
|
|
270
|
-
.check(z.minLength(1), z.describe('Source chain alias or CAIP-2 id, such as `base
|
|
271
|
-
sourceToken: z.string().check(z.minLength(1), z.describe('Source token symbol, contract address, mint, or Tempo token key. Symbol lookup is scoped to `sourceChain`; EVM identifiers are case-insensitive, while Solana and Tron identifiers must match exactly. An unknown token returns an empty list, not an error.'), z.meta({
|
|
272
|
-
examples: [
|
|
273
|
-
'USDC',
|
|
274
|
-
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
275
|
-
'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
|
276
|
-
],
|
|
277
|
-
})),
|
|
278
|
-
})
|
|
279
|
-
.check(z.describe('Query parameters for discovering funding routes into Tempo.'));
|
|
280
|
-
/** Non-paginated list of funding route candidates. */
|
|
281
|
-
listFundingRoutes.Response = Schema.describe(z.object({
|
|
282
|
-
data: z
|
|
283
|
-
.array(schema.RouteCandidate)
|
|
284
|
-
.check(z.describe('Funding route candidates matching the request.')),
|
|
285
|
-
}), 'A non-paginated list of funding route candidates.');
|
|
286
|
-
})(listFundingRoutes = schema.listFundingRoutes || (schema.listFundingRoutes = {}));
|
|
287
|
-
/** Schemas for the quoteFundingRoute operation. */
|
|
288
|
-
let quoteFundingRoute;
|
|
289
|
-
(function (quoteFundingRoute) {
|
|
290
|
-
/** JSON body for an explicit funding route quote. */
|
|
291
|
-
quoteFundingRoute.Body = z
|
|
292
|
-
.strictObject({
|
|
293
|
-
depositor: Schema.Address.check(z.describe('Address that would submit the funding transaction.')),
|
|
294
|
-
destinationToken: z
|
|
295
|
-
.optional(z.string())
|
|
296
|
-
.check(z.describe('Tempo destination token symbol, address, or token key.'), z.meta({ examples: ['USDC.e'] })),
|
|
297
|
-
provider: z
|
|
298
|
-
.literal('across')
|
|
299
|
-
.check(z.describe('Provider id selected from funding route discovery.'), z.meta({ examples: ['across'] })),
|
|
300
|
-
recipient: z
|
|
301
|
-
.optional(Schema.Address)
|
|
302
|
-
.check(z.describe('Optional destination recipient; defaults to the depositor.')),
|
|
303
|
-
sourceAmount: z
|
|
304
|
-
.string()
|
|
305
|
-
.check(z.minLength(1), z.describe('Exact source amount to quote.'), z.meta({ examples: ['1000000'] })),
|
|
306
|
-
sourceAmountUnits: z
|
|
307
|
-
._default(z.enum(['baseUnits', 'decimal']), 'baseUnits')
|
|
308
|
-
.check(z.describe('Whether `sourceAmount` uses base units or decimal notation.'), z.meta({ examples: ['baseUnits'] })),
|
|
309
|
-
sourceChain: z
|
|
310
|
-
.string()
|
|
311
|
-
.check(z.minLength(1), z.describe('Source chain alias or CAIP-2 id.'), z.meta({ examples: ['base'] })),
|
|
167
|
+
.check(z.minLength(1), z.describe('Source chain alias or CAIP-2 id, such as `base` or `eip155:8453`.'), z.meta({ examples: ['base', 'eip155:8453'] })),
|
|
312
168
|
sourceToken: z
|
|
313
169
|
.string()
|
|
314
|
-
.check(z.minLength(1), z.describe('Source token symbol, address,
|
|
170
|
+
.check(z.minLength(1), z.describe('Source token symbol, contract address, or Tempo token key. Symbol and address lookup is scoped to `sourceChain` and case-insensitive. An unknown token returns an empty list.'), z.meta({ examples: ['USDC', '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'] })),
|
|
315
171
|
})
|
|
316
|
-
.check(z.describe('
|
|
317
|
-
/**
|
|
318
|
-
|
|
319
|
-
|
|
172
|
+
.check(z.describe('Query parameters for live funding quotes into Tempo.'));
|
|
173
|
+
/** Non-paginated list of successful funding quotes. */
|
|
174
|
+
quoteFunding.Response = Schema.describe(z.object({
|
|
175
|
+
data: z.array(schema.FundingQuote).check(z.describe('Successful live funding quotes.')),
|
|
176
|
+
}), 'A non-paginated list of successful live funding quotes.');
|
|
177
|
+
})(quoteFunding = schema.quoteFunding || (schema.quoteFunding = {}));
|
|
320
178
|
/** Schemas for the listFundingChains operation. */
|
|
321
179
|
let listFundingChains;
|
|
322
180
|
(function (listFundingChains) {
|
|
@@ -324,148 +182,83 @@ export var schema;
|
|
|
324
182
|
listFundingChains.Response = Schema.describe(z.object({
|
|
325
183
|
data: z
|
|
326
184
|
.array(schema.ChainInventory)
|
|
327
|
-
.check(z.describe('Source chains and stablecoins
|
|
185
|
+
.check(z.describe('Source chains and stablecoins supported by funding quotes.')),
|
|
328
186
|
}), 'A non-paginated list of source chains and stablecoin inventory.');
|
|
329
187
|
})(listFundingChains = schema.listFundingChains || (schema.listFundingChains = {}));
|
|
330
188
|
/** Schemas for the listProviders operation. */
|
|
331
189
|
let listProviders;
|
|
332
190
|
(function (listProviders) {
|
|
333
|
-
/**
|
|
334
|
-
listProviders.Query = z
|
|
335
|
-
.strictObject({
|
|
336
|
-
capability: z
|
|
337
|
-
.optional(z.enum(['fundingRoutes']))
|
|
338
|
-
.check(z.describe('Optional provider capability filter.'), z.meta({ examples: ['fundingRoutes'] })),
|
|
339
|
-
})
|
|
340
|
-
.check(z.describe('Query parameters for listing providers.'));
|
|
341
|
-
/** Non-paginated generic provider catalog. */
|
|
191
|
+
/** Non-paginated funding quote provider catalog. */
|
|
342
192
|
listProviders.Response = Schema.describe(z.object({
|
|
343
|
-
data: z.array(schema.Provider).check(z.describe("Providers in Tempo's
|
|
344
|
-
}), 'A non-paginated list of providers.');
|
|
193
|
+
data: z.array(schema.Provider).check(z.describe("Providers in Tempo's funding quote catalog.")),
|
|
194
|
+
}), 'A non-paginated list of funding quote providers.');
|
|
345
195
|
})(listProviders = schema.listProviders || (schema.listProviders = {}));
|
|
346
196
|
})(schema || (schema = {}));
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
description: '`GET /v1/funding/routes?sourceChain=tron&sourceToken=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t&sourceAmount=1000000&provider=bridge`',
|
|
379
|
-
summary: 'Tron USDT',
|
|
380
|
-
value: {
|
|
381
|
-
data: FundingRoutes.listStaticRoutes({
|
|
382
|
-
limit: 10,
|
|
383
|
-
provider: 'bridge',
|
|
384
|
-
sourceAmount: '1000000',
|
|
385
|
-
sourceAmountUnits: 'baseUnits',
|
|
386
|
-
sourceChain: 'tron',
|
|
387
|
-
sourceToken: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
|
388
|
-
}),
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
};
|
|
197
|
+
const fundingQuoteResponseExample = (() => {
|
|
198
|
+
const [candidate] = FundingQuotes.listQuoteCandidates({
|
|
199
|
+
provider: 'relay',
|
|
200
|
+
sourceAmount: '1000000',
|
|
201
|
+
sourceAmountUnits: 'baseUnits',
|
|
202
|
+
sourceChain: 'base',
|
|
203
|
+
sourceToken: 'USDC',
|
|
204
|
+
});
|
|
205
|
+
if (!candidate)
|
|
206
|
+
throw new Error('Missing Relay funding quote example candidate');
|
|
207
|
+
return {
|
|
208
|
+
data: [
|
|
209
|
+
{
|
|
210
|
+
...candidate,
|
|
211
|
+
quality: {
|
|
212
|
+
estimatedSeconds: 1,
|
|
213
|
+
liquiditySource: 'providerQuote',
|
|
214
|
+
sourceDetail: 'relay:quote-v2',
|
|
215
|
+
tier: 'liquid',
|
|
216
|
+
},
|
|
217
|
+
quote: {
|
|
218
|
+
inputAmount: '1000000',
|
|
219
|
+
minimumOutputAmount: '939242',
|
|
220
|
+
outputAmount: '979295',
|
|
221
|
+
outputAmountFormatted: '0.979295',
|
|
222
|
+
sampledAt: '2026-01-01T00:00:00.000Z',
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
})();
|
|
392
228
|
const fundingChainsResponseExample = {
|
|
393
|
-
data:
|
|
229
|
+
data: FundingQuotes.listChains(),
|
|
394
230
|
};
|
|
395
231
|
const providersResponseExample = {
|
|
396
|
-
data:
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
limit: 1,
|
|
401
|
-
provider: 'across',
|
|
402
|
-
sourceAmount: '1000000',
|
|
403
|
-
sourceAmountUnits: 'baseUnits',
|
|
404
|
-
sourceChain: 'base',
|
|
405
|
-
sourceToken: 'USDC',
|
|
406
|
-
});
|
|
407
|
-
const fundingQuoteResponseExample = {
|
|
408
|
-
destinationChain: fundingQuoteRouteExample.destinationChain,
|
|
409
|
-
destinationToken: fundingQuoteRouteExample.destinationToken,
|
|
410
|
-
estimatedSeconds: 2,
|
|
411
|
-
expiresAt: '2026-01-01T00:01:00Z',
|
|
412
|
-
fees: {
|
|
413
|
-
total: {
|
|
414
|
-
amount: '1200',
|
|
415
|
-
amountUsd: '0.0012',
|
|
416
|
-
bps: 12,
|
|
417
|
-
token: {
|
|
418
|
-
address: fundingQuoteRouteExample.sourceToken.address,
|
|
419
|
-
chainId: fundingQuoteRouteExample.sourceChain.id,
|
|
420
|
-
decimals: fundingQuoteRouteExample.sourceToken.decimals,
|
|
421
|
-
symbol: fundingQuoteRouteExample.sourceToken.symbol,
|
|
422
|
-
},
|
|
423
|
-
},
|
|
424
|
-
totalMax: {
|
|
425
|
-
amount: '1800',
|
|
426
|
-
amountUsd: '0.0018',
|
|
427
|
-
bps: 18,
|
|
428
|
-
token: {
|
|
429
|
-
address: fundingQuoteRouteExample.sourceToken.address,
|
|
430
|
-
chainId: fundingQuoteRouteExample.sourceChain.id,
|
|
431
|
-
decimals: fundingQuoteRouteExample.sourceToken.decimals,
|
|
432
|
-
symbol: fundingQuoteRouteExample.sourceToken.symbol,
|
|
433
|
-
},
|
|
434
|
-
},
|
|
435
|
-
},
|
|
436
|
-
inputAmount: '1000000',
|
|
437
|
-
minimumOutputAmount: '988000',
|
|
438
|
-
outputAmount: '990000',
|
|
439
|
-
outputAmountFormatted: '0.99',
|
|
440
|
-
provider: fundingQuoteRouteExample.provider,
|
|
441
|
-
routeId: fundingQuoteRouteExample.id,
|
|
442
|
-
sampledAt: '2026-01-01T00:00:00Z',
|
|
443
|
-
sourceChain: fundingQuoteRouteExample.sourceChain,
|
|
444
|
-
sourceToken: fundingQuoteRouteExample.sourceToken,
|
|
232
|
+
data: FundingQuotes.listProviders().map((provider) => ({
|
|
233
|
+
...provider,
|
|
234
|
+
status: 'configured',
|
|
235
|
+
})),
|
|
445
236
|
};
|
|
446
|
-
/** Mounts funding
|
|
237
|
+
/** Mounts live funding quotes and their supporting inventory endpoints. */
|
|
447
238
|
export function funding(options = {}) {
|
|
448
239
|
return new Hono()
|
|
449
|
-
.get('/v1/funding/
|
|
240
|
+
.get('/v1/funding/quotes', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.validate('query', schema.quoteFunding.Query, {
|
|
450
241
|
code: 'query_invalid',
|
|
451
242
|
message: 'Invalid query parameters',
|
|
452
243
|
}), OpenApi.describeRoute({
|
|
453
|
-
description: '
|
|
454
|
-
operationId: '
|
|
244
|
+
description: 'Returns live quotes for funding Tempo with a stablecoin. Omit `provider` to query all configured providers. This endpoint does not execute a transfer.',
|
|
245
|
+
operationId: 'quoteFunding',
|
|
455
246
|
responses: OpenApi.responses({
|
|
456
|
-
errors: {
|
|
247
|
+
errors: {
|
|
248
|
+
400: { codes: ['query_invalid'] },
|
|
249
|
+
502: {
|
|
250
|
+
codes: ['upstream_error'],
|
|
251
|
+
description: 'Every matching quote provider failed unexpectedly.',
|
|
252
|
+
},
|
|
253
|
+
},
|
|
457
254
|
success: {
|
|
458
|
-
description: '
|
|
459
|
-
|
|
460
|
-
schema: schema.
|
|
255
|
+
description: 'Live funding quotes. An empty list means no provider returned a quote.',
|
|
256
|
+
example: fundingQuoteResponseExample,
|
|
257
|
+
schema: schema.quoteFunding.Response,
|
|
461
258
|
},
|
|
462
259
|
}),
|
|
463
|
-
summary: '
|
|
260
|
+
summary: 'Get funding quotes',
|
|
464
261
|
tags: ['Funding'],
|
|
465
|
-
}), Cache.response({
|
|
466
|
-
cacheControl: Cache.policies.noStore,
|
|
467
|
-
name: 'tempo-api:funding-routes:v1',
|
|
468
|
-
key: (c) => Cache.urlKey(c, schema.listFundingRoutes.Query),
|
|
469
262
|
}), async (c) => {
|
|
470
263
|
if (Auth.narrowAccess)
|
|
471
264
|
return Auth.paidAccessError(c);
|
|
@@ -476,15 +269,13 @@ export function funding(options = {}) {
|
|
|
476
269
|
});
|
|
477
270
|
const query = c.req.valid('query');
|
|
478
271
|
try {
|
|
479
|
-
|
|
480
|
-
return c.json(Response.validated(schema.
|
|
481
|
-
data: await
|
|
272
|
+
c.header('Cache-Control', 'no-store');
|
|
273
|
+
return c.json(Response.validated(schema.quoteFunding.Response, {
|
|
274
|
+
data: await FundingQuotes.listQuotes({
|
|
482
275
|
adapters: options.adapters,
|
|
483
276
|
adapterTimeoutMs: options.adapterTimeoutMs,
|
|
484
277
|
cache: { bypass: cacheBypass(c.req.raw) },
|
|
485
278
|
destinationToken: query.destinationToken,
|
|
486
|
-
include,
|
|
487
|
-
limit: query.limit,
|
|
488
279
|
provider: query.provider,
|
|
489
280
|
sourceAmount: query.sourceAmount,
|
|
490
281
|
sourceAmountUnits: query.sourceAmountUnits,
|
|
@@ -497,108 +288,21 @@ export function funding(options = {}) {
|
|
|
497
288
|
const message = requestErrorMessage(cause);
|
|
498
289
|
if (message)
|
|
499
290
|
return Response.error(c, { code: 'query_invalid', message, status: 400 });
|
|
500
|
-
|
|
501
|
-
}
|
|
502
|
-
})
|
|
503
|
-
.post('/v1/funding/routes/quote', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.validate('json', schema.quoteFundingRoute.Body, {
|
|
504
|
-
code: 'body_invalid',
|
|
505
|
-
message: 'Invalid quote parameters',
|
|
506
|
-
}), OpenApi.describeRoute({
|
|
507
|
-
description: 'Gets a depositor-specific exact-input quote for one curated funding route. The response excludes provider transaction calldata, approvals, and wallet balance details.',
|
|
508
|
-
operationId: 'quoteFundingRoute',
|
|
509
|
-
responses: OpenApi.responses({
|
|
510
|
-
errors: {
|
|
511
|
-
400: { codes: ['body_invalid'] },
|
|
512
|
-
404: { codes: ['route_not_found', 'quote_unavailable'] },
|
|
513
|
-
501: { codes: ['provider_unconfigured'] },
|
|
514
|
-
502: { codes: ['provider_error', 'provider_rate_limited', 'provider_timeout'] },
|
|
515
|
-
},
|
|
516
|
-
success: {
|
|
517
|
-
description: 'Normalized route quote without provider execution payloads.',
|
|
518
|
-
example: fundingQuoteResponseExample,
|
|
519
|
-
schema: schema.quoteFundingRoute.Response,
|
|
520
|
-
},
|
|
521
|
-
}),
|
|
522
|
-
summary: 'Quote funding route',
|
|
523
|
-
tags: ['Funding'],
|
|
524
|
-
}), async (c) => {
|
|
525
|
-
if (Auth.narrowAccess)
|
|
526
|
-
return Auth.paidAccessError(c);
|
|
527
|
-
if (OpenApi.narrowValidation)
|
|
528
|
-
return OpenApi.validationError(c, {
|
|
529
|
-
code: 'body_invalid',
|
|
530
|
-
message: 'Invalid quote parameters',
|
|
531
|
-
});
|
|
532
|
-
const body = c.req.valid('json');
|
|
533
|
-
try {
|
|
534
|
-
const quote = await FundingRoutes.quoteRoute({
|
|
535
|
-
depositor: body.depositor,
|
|
536
|
-
destinationToken: body.destinationToken,
|
|
537
|
-
provider: body.provider,
|
|
538
|
-
quote: options.acrossQuote,
|
|
539
|
-
quoteTimeoutMs: options.quoteTimeoutMs,
|
|
540
|
-
recipient: body.recipient,
|
|
541
|
-
sourceAmount: body.sourceAmount,
|
|
542
|
-
sourceAmountUnits: body.sourceAmountUnits,
|
|
543
|
-
sourceChain: body.sourceChain,
|
|
544
|
-
sourceToken: body.sourceToken,
|
|
545
|
-
});
|
|
546
|
-
c.header('Cache-Control', 'no-store');
|
|
547
|
-
return c.json(Response.validated(schema.quoteFundingRoute.Response, quote), 200);
|
|
548
|
-
}
|
|
549
|
-
catch (cause) {
|
|
550
|
-
const message = requestErrorMessage(cause);
|
|
551
|
-
if (message)
|
|
552
|
-
return Response.error(c, { code: 'body_invalid', message, status: 400 });
|
|
553
|
-
if (cause instanceof FundingRoutes.FundingRouteNotFoundError)
|
|
554
|
-
return Response.error(c, {
|
|
555
|
-
code: 'route_not_found',
|
|
556
|
-
message: 'No curated funding route matches the request.',
|
|
557
|
-
status: 404,
|
|
558
|
-
});
|
|
559
|
-
if (cause instanceof FundingRoutes.ProviderQuoteUnavailableError)
|
|
560
|
-
return Response.error(c, {
|
|
561
|
-
code: 'quote_unavailable',
|
|
562
|
-
message: 'The provider cannot quote this route.',
|
|
563
|
-
status: 404,
|
|
564
|
-
});
|
|
565
|
-
if (cause instanceof FundingRoutes.ProviderNotConfiguredError)
|
|
566
|
-
return Response.error(c, {
|
|
567
|
-
code: 'provider_unconfigured',
|
|
568
|
-
message: 'The provider quote integration is not configured.',
|
|
569
|
-
status: 501,
|
|
570
|
-
});
|
|
571
|
-
if (cause instanceof FundingRoutes.ProviderRateLimitError)
|
|
572
|
-
return Response.error(c, {
|
|
573
|
-
code: 'provider_rate_limited',
|
|
574
|
-
message: 'The provider temporarily rate-limited this quote.',
|
|
575
|
-
status: 502,
|
|
576
|
-
});
|
|
577
|
-
if (cause instanceof FundingRoutes.ProviderAdapterTimeoutError)
|
|
578
|
-
return Response.error(c, {
|
|
579
|
-
code: 'provider_timeout',
|
|
580
|
-
message: 'The provider quote timed out.',
|
|
581
|
-
status: 502,
|
|
582
|
-
});
|
|
583
|
-
if (cause instanceof Error) {
|
|
584
|
-
const providerFailure = FundingRouteProviders.acrossQuoteFailure({ cause });
|
|
585
|
-
if (providerFailure)
|
|
586
|
-
c.set('providerFailure', providerFailure);
|
|
291
|
+
if (cause instanceof FundingQuotes.ProviderQuoteError)
|
|
587
292
|
return Response.error(c, {
|
|
588
|
-
code: '
|
|
589
|
-
message: '
|
|
293
|
+
code: 'upstream_error',
|
|
294
|
+
message: 'Quote providers could not complete the request.',
|
|
590
295
|
status: 502,
|
|
591
296
|
});
|
|
592
|
-
}
|
|
593
297
|
throw cause;
|
|
594
298
|
}
|
|
595
299
|
})
|
|
596
300
|
.get('/v1/funding/chains', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.describeRoute({
|
|
597
|
-
description: 'Lists source chains and stablecoins
|
|
301
|
+
description: 'Lists the source chains and stablecoins you can use when requesting a funding quote.',
|
|
598
302
|
operationId: 'listFundingChains',
|
|
599
303
|
responses: OpenApi.responses({
|
|
600
304
|
success: {
|
|
601
|
-
description: '
|
|
305
|
+
description: 'Supported source chains and stablecoins.',
|
|
602
306
|
example: fundingChainsResponseExample,
|
|
603
307
|
schema: schema.listFundingChains.Response,
|
|
604
308
|
},
|
|
@@ -613,58 +317,42 @@ export function funding(options = {}) {
|
|
|
613
317
|
if (Auth.narrowAccess)
|
|
614
318
|
return Auth.paidAccessError(c);
|
|
615
319
|
return c.json(Response.validated(schema.listFundingChains.Response, {
|
|
616
|
-
data:
|
|
320
|
+
data: FundingQuotes.listChains(),
|
|
617
321
|
}), 200);
|
|
618
322
|
})
|
|
619
|
-
.get('/v1/providers', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}), OpenApi.describeRoute({
|
|
623
|
-
description: 'Lists provider metadata, capability flags, auth requirements, and integration status across provider domains. `inventoryOnly` providers can appear in static route candidates; `planned` providers are visible for roadmap transparency and may not return candidates.',
|
|
624
|
-
operationId: 'listProviders',
|
|
323
|
+
.get('/v1/funding/providers', Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }), OpenApi.describeRoute({
|
|
324
|
+
description: 'Lists funding quote providers and whether live quoting is configured for this deployment.',
|
|
325
|
+
operationId: 'listFundingProviders',
|
|
625
326
|
responses: OpenApi.responses({
|
|
626
|
-
errors: { 400: { codes: ['query_invalid'] } },
|
|
627
327
|
success: {
|
|
628
|
-
description: '
|
|
328
|
+
description: 'Funding quote providers supported by Tempo.',
|
|
629
329
|
example: providersResponseExample,
|
|
630
330
|
schema: schema.listProviders.Response,
|
|
631
331
|
},
|
|
632
332
|
}),
|
|
633
|
-
summary: 'List providers',
|
|
634
|
-
tags: ['
|
|
333
|
+
summary: 'List funding providers',
|
|
334
|
+
tags: ['Funding'],
|
|
635
335
|
}), Cache.response({
|
|
636
336
|
cacheControl: Cache.policies.stable,
|
|
637
|
-
name: 'tempo-api:providers:v1',
|
|
638
|
-
key: (c) =>
|
|
337
|
+
name: 'tempo-api:funding-providers:v1',
|
|
338
|
+
key: (c) => c.req.url,
|
|
639
339
|
}), (c) => {
|
|
640
340
|
if (Auth.narrowAccess)
|
|
641
341
|
return Auth.paidAccessError(c);
|
|
642
|
-
if (OpenApi.narrowValidation)
|
|
643
|
-
return OpenApi.validationError(c, {
|
|
644
|
-
code: 'query_invalid',
|
|
645
|
-
message: 'Invalid query parameters',
|
|
646
|
-
});
|
|
647
|
-
const query = c.req.valid('query');
|
|
648
342
|
return c.json(Response.validated(schema.listProviders.Response, {
|
|
649
|
-
data:
|
|
650
|
-
adapters: options.adapters,
|
|
651
|
-
capability: query.capability,
|
|
652
|
-
configuredProviders: options.acrossQuote ? ['across'] : [],
|
|
653
|
-
}),
|
|
343
|
+
data: FundingQuotes.listProviders({ adapters: options.adapters }),
|
|
654
344
|
}), 200);
|
|
655
345
|
});
|
|
656
346
|
}
|
|
657
347
|
// Maps caller-input errors to a specific 400 message; anything else rethrows.
|
|
658
348
|
function requestErrorMessage(cause) {
|
|
659
|
-
if (cause instanceof
|
|
349
|
+
if (cause instanceof FundingQuotes.InvalidAmountError)
|
|
660
350
|
return 'Invalid `sourceAmount`.';
|
|
661
|
-
if (cause instanceof
|
|
662
|
-
return 'Unsupported `include`.';
|
|
663
|
-
if (cause instanceof FundingRoutes.UnsupportedDestinationTokenError)
|
|
351
|
+
if (cause instanceof FundingQuotes.UnsupportedDestinationTokenError)
|
|
664
352
|
return 'Unsupported `destinationToken`.';
|
|
665
|
-
if (cause instanceof
|
|
353
|
+
if (cause instanceof FundingQuotes.UnsupportedProviderError)
|
|
666
354
|
return 'Unsupported `provider`.';
|
|
667
|
-
if (cause instanceof
|
|
355
|
+
if (cause instanceof FundingQuotes.UnsupportedSourceChainError)
|
|
668
356
|
return 'Unsupported `sourceChain`.';
|
|
669
357
|
return undefined;
|
|
670
358
|
}
|