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
|
@@ -4,19 +4,18 @@ import * as z from 'zod/mini'
|
|
|
4
4
|
import type * as App from '../../../App.js'
|
|
5
5
|
import * as Auth from '../../../internal/Auth.js'
|
|
6
6
|
import * as Cache from '../../../internal/Cache.js'
|
|
7
|
-
import * as
|
|
7
|
+
import * as FundingQuotes from '../../../internal/FundingQuotes.js'
|
|
8
8
|
import * as OpenApi from '../../../internal/OpenApi.js'
|
|
9
9
|
import * as Response from '../../../internal/Response.js'
|
|
10
10
|
import * as Schema from '../../../internal/Schema.js'
|
|
11
|
-
import * as FundingRouteProviders from '../FundingRouteProviders.js'
|
|
12
11
|
|
|
13
|
-
/** Zod schemas owned by
|
|
12
|
+
/** Zod schemas owned by funding quote resources. */
|
|
14
13
|
export namespace schema {
|
|
15
14
|
/** Source or destination chain reference. */
|
|
16
15
|
export const Chain = Schema.describe(
|
|
17
16
|
z.object({
|
|
18
17
|
addressFormat: z
|
|
19
|
-
.
|
|
18
|
+
.literal('evm')
|
|
20
19
|
.check(
|
|
21
20
|
z.describe('Address family used by accounts and token identifiers on this chain.'),
|
|
22
21
|
z.meta({ examples: ['evm'] }),
|
|
@@ -25,12 +24,12 @@ export namespace schema {
|
|
|
25
24
|
.string()
|
|
26
25
|
.check(
|
|
27
26
|
z.describe(
|
|
28
|
-
'Stable
|
|
27
|
+
'Stable CAIP-2 chain id, represented as a string instead of the numeric `chainId` used elsewhere.',
|
|
29
28
|
),
|
|
30
29
|
z.meta({ examples: ['eip155:8453'] }),
|
|
31
30
|
),
|
|
32
31
|
kind: z
|
|
33
|
-
.
|
|
32
|
+
.literal('evm')
|
|
34
33
|
.check(
|
|
35
34
|
z.describe('Chain execution family used for provider routing.'),
|
|
36
35
|
z.meta({ examples: ['evm'] }),
|
|
@@ -41,11 +40,11 @@ export namespace schema {
|
|
|
41
40
|
providerIds: z
|
|
42
41
|
.optional(z.record(z.string(), z.string()))
|
|
43
42
|
.check(
|
|
44
|
-
z.describe('Provider-specific chain ids Tempo uses when
|
|
45
|
-
z.meta({ examples: [{
|
|
43
|
+
z.describe('Provider-specific chain ids Tempo uses when requesting quotes.'),
|
|
44
|
+
z.meta({ examples: [{ relay: '8453' }] }),
|
|
46
45
|
),
|
|
47
46
|
}),
|
|
48
|
-
'A normalized chain reference for funding
|
|
47
|
+
'A normalized chain reference for funding quotes.',
|
|
49
48
|
)
|
|
50
49
|
|
|
51
50
|
/** Source or destination token reference. */
|
|
@@ -89,14 +88,14 @@ export namespace schema {
|
|
|
89
88
|
verified: z
|
|
90
89
|
.boolean()
|
|
91
90
|
.check(
|
|
92
|
-
z.describe('Whether Tempo recognizes this token in its funding
|
|
91
|
+
z.describe('Whether Tempo recognizes this token in its funding quote inventory.'),
|
|
93
92
|
z.meta({ examples: [true] }),
|
|
94
93
|
),
|
|
95
94
|
}),
|
|
96
|
-
'A normalized token reference for funding
|
|
95
|
+
'A normalized token reference for funding quotes.',
|
|
97
96
|
)
|
|
98
97
|
|
|
99
|
-
/** Source amount echoed by a funding
|
|
98
|
+
/** Source amount echoed by a funding quote response. */
|
|
100
99
|
export const TokenAmount = Schema.describe(
|
|
101
100
|
z.object({
|
|
102
101
|
amount: Schema.DecimalString.check(
|
|
@@ -110,151 +109,88 @@ export namespace schema {
|
|
|
110
109
|
),
|
|
111
110
|
z.meta({ examples: ['1'] }),
|
|
112
111
|
),
|
|
113
|
-
usd: z
|
|
114
|
-
.nullable(z.string())
|
|
115
|
-
.check(
|
|
116
|
-
z.describe('USD estimate for the requested source amount, when available.'),
|
|
117
|
-
z.meta({ examples: ['1.00'] }),
|
|
118
|
-
),
|
|
119
112
|
}),
|
|
120
113
|
'The requested source amount in provider-safe base units and display form.',
|
|
121
114
|
)
|
|
122
115
|
|
|
123
|
-
/** Provider summary embedded in a
|
|
116
|
+
/** Provider summary embedded in a funding quote. */
|
|
124
117
|
export const ProviderRef = Schema.describe(
|
|
125
118
|
z.object({
|
|
126
|
-
id: z
|
|
119
|
+
id: z
|
|
120
|
+
.literal('relay')
|
|
121
|
+
.check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
|
|
127
122
|
kind: z
|
|
128
123
|
.string()
|
|
129
124
|
.check(
|
|
130
|
-
z.describe('Provider category, such as
|
|
131
|
-
z.meta({ examples: ['
|
|
125
|
+
z.describe('Provider category, such as a solver network or aggregator.'),
|
|
126
|
+
z.meta({ examples: ['solverNetwork'] }),
|
|
132
127
|
),
|
|
133
128
|
name: z
|
|
134
129
|
.string()
|
|
135
|
-
.check(z.describe('Human-readable provider name.'), z.meta({ examples: ['
|
|
130
|
+
.check(z.describe('Human-readable provider name.'), z.meta({ examples: ['Relay'] })),
|
|
136
131
|
requiresApiKey: z
|
|
137
132
|
.boolean()
|
|
138
133
|
.check(
|
|
139
134
|
z.describe('Whether Tempo needs provider credentials to query or use this provider.'),
|
|
140
|
-
z.meta({ examples: [
|
|
135
|
+
z.meta({ examples: [false] }),
|
|
141
136
|
),
|
|
142
137
|
}),
|
|
143
|
-
'Provider metadata embedded in a
|
|
138
|
+
'Provider metadata embedded in a funding quote.',
|
|
144
139
|
)
|
|
145
140
|
|
|
146
|
-
/**
|
|
141
|
+
/** Quote quality signals exposed directly instead of implied by list order. */
|
|
147
142
|
export const Quality = Schema.describe(
|
|
148
143
|
z.object({
|
|
149
|
-
availableVolumeUsd: z
|
|
150
|
-
.nullable(z.string())
|
|
151
|
-
.check(
|
|
152
|
-
z.describe('Available USD capacity, when available.'),
|
|
153
|
-
z.meta({ examples: ['1114274.43'] }),
|
|
154
|
-
),
|
|
155
144
|
estimatedSeconds: z
|
|
156
|
-
.
|
|
145
|
+
.optional(z.number().check(z.int(), z.nonnegative()))
|
|
157
146
|
.check(
|
|
158
147
|
z.describe('Estimated settlement time in seconds, when known.'),
|
|
159
148
|
z.meta({ examples: [2] }),
|
|
160
149
|
),
|
|
161
|
-
feeBps: z
|
|
162
|
-
.nullable(z.number().check(z.int(), z.nonnegative()))
|
|
163
|
-
.check(
|
|
164
|
-
z.describe('Estimated fee in basis points, when known.'),
|
|
165
|
-
z.meta({ examples: [109] }),
|
|
166
|
-
),
|
|
167
|
-
historicalVolumeUsd24h: z
|
|
168
|
-
.nullable(z.string())
|
|
169
|
-
.check(
|
|
170
|
-
z.describe('24h routed volume in USD, when available.'),
|
|
171
|
-
z.meta({ examples: ['250000.00'] }),
|
|
172
|
-
),
|
|
173
|
-
instantVolumeUsd: z
|
|
174
|
-
.nullable(z.string())
|
|
175
|
-
.check(
|
|
176
|
-
z.describe('Instant USD capacity, when available.'),
|
|
177
|
-
z.meta({ examples: ['12453.94'] }),
|
|
178
|
-
),
|
|
179
150
|
liquiditySource: z
|
|
180
151
|
.string()
|
|
181
152
|
.check(
|
|
182
|
-
z.describe('
|
|
183
|
-
z.meta({ examples: ['
|
|
184
|
-
),
|
|
185
|
-
score: z
|
|
186
|
-
.nullable(z.number().check(z.int(), z.gte(0), z.lte(100)))
|
|
187
|
-
.check(
|
|
188
|
-
z.describe('Explainable route score from 0 to 100, when enough signals are available.'),
|
|
189
|
-
z.meta({ examples: [91] }),
|
|
153
|
+
z.describe('Provider source for the live quote quality signal.'),
|
|
154
|
+
z.meta({ examples: ['providerQuote'] }),
|
|
190
155
|
),
|
|
191
156
|
sourceDetail: z
|
|
192
|
-
.
|
|
157
|
+
.optional(z.string())
|
|
193
158
|
.check(
|
|
194
159
|
z.describe('Provider-specific source or endpoint detail for the quality signal.'),
|
|
195
160
|
z.meta({ examples: ['providerEndpoint'] }),
|
|
196
161
|
),
|
|
197
162
|
tier: z
|
|
198
|
-
.enum(['liquid', 'thin'
|
|
163
|
+
.enum(['liquid', 'thin'])
|
|
199
164
|
.check(
|
|
200
|
-
z.describe('Machine-readable
|
|
201
|
-
z.meta({ examples: ['
|
|
165
|
+
z.describe('Machine-readable quality tier for a successful quote.'),
|
|
166
|
+
z.meta({ examples: ['liquid'] }),
|
|
202
167
|
),
|
|
203
168
|
}),
|
|
204
|
-
'Machine-readable liquidity, fee, and source signals for a
|
|
169
|
+
'Machine-readable liquidity, fee, and source signals for a successful quote.',
|
|
205
170
|
)
|
|
206
171
|
|
|
207
|
-
/** Provider-derived
|
|
208
|
-
export const
|
|
172
|
+
/** Provider-derived output, limits, and freshness data. */
|
|
173
|
+
export const QuoteDetails = Schema.describe(
|
|
209
174
|
z.object({
|
|
210
|
-
expiresAt: z
|
|
211
|
-
.nullable(z.iso.datetime())
|
|
212
|
-
.check(
|
|
213
|
-
z.describe('Provider quote expiry timestamp.'),
|
|
214
|
-
z.meta({ examples: ['2026-01-01T00:00:30Z'] }),
|
|
215
|
-
),
|
|
216
175
|
inputAmount: Schema.DecimalString.check(
|
|
217
176
|
z.describe('Source amount sent to the provider in base units.'),
|
|
218
177
|
z.meta({ examples: ['1000000'] }),
|
|
219
178
|
),
|
|
220
|
-
limits: z
|
|
221
|
-
.nullable(
|
|
222
|
-
z.object({
|
|
223
|
-
instantSourceAmount: z
|
|
224
|
-
.nullable(Schema.DecimalString)
|
|
225
|
-
.check(
|
|
226
|
-
z.describe('Provider-reported instant source amount capacity.'),
|
|
227
|
-
z.meta({ examples: ['12453940000'] }),
|
|
228
|
-
),
|
|
229
|
-
maxSourceAmount: z
|
|
230
|
-
.nullable(Schema.DecimalString)
|
|
231
|
-
.check(
|
|
232
|
-
z.describe('Provider-reported maximum source amount.'),
|
|
233
|
-
z.meta({ examples: ['1114274433200'] }),
|
|
234
|
-
),
|
|
235
|
-
minSourceAmount: z
|
|
236
|
-
.nullable(Schema.DecimalString)
|
|
237
|
-
.check(
|
|
238
|
-
z.describe('Provider-reported minimum source amount.'),
|
|
239
|
-
z.meta({ examples: ['500063'] }),
|
|
240
|
-
),
|
|
241
|
-
}),
|
|
242
|
-
)
|
|
243
|
-
.check(z.describe('Provider limits expressed in source base units.')),
|
|
244
179
|
minimumOutputAmount: z
|
|
245
|
-
.
|
|
180
|
+
.optional(Schema.DecimalString)
|
|
246
181
|
.check(
|
|
247
182
|
z.describe('Slippage-adjusted minimum destination amount in base units.'),
|
|
248
183
|
z.meta({ examples: ['988000'] }),
|
|
249
184
|
),
|
|
250
185
|
outputAmount: z
|
|
251
|
-
.
|
|
186
|
+
.string()
|
|
187
|
+
.check(z.regex(/^\d+$/))
|
|
252
188
|
.check(
|
|
253
189
|
z.describe('Expected destination amount in base units.'),
|
|
254
190
|
z.meta({ examples: ['989102'] }),
|
|
255
191
|
),
|
|
256
192
|
outputAmountFormatted: z
|
|
257
|
-
.
|
|
193
|
+
.string()
|
|
258
194
|
.check(
|
|
259
195
|
z.describe('Expected destination amount rendered with destination token decimals.'),
|
|
260
196
|
z.meta({ examples: ['0.989102'] }),
|
|
@@ -262,163 +198,40 @@ export namespace schema {
|
|
|
262
198
|
sampledAt: z.iso
|
|
263
199
|
.datetime()
|
|
264
200
|
.check(
|
|
265
|
-
z.describe('Timestamp for the live quote
|
|
201
|
+
z.describe('Timestamp for the live quote probe.'),
|
|
266
202
|
z.meta({ examples: ['2026-01-01T00:00:00Z'] }),
|
|
267
203
|
),
|
|
268
204
|
}),
|
|
269
|
-
'Provider-derived
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
/** Token reference attached to a normalized quote fee. */
|
|
273
|
-
export const QuoteFeeToken = Schema.describe(
|
|
274
|
-
z.object({
|
|
275
|
-
address: z
|
|
276
|
-
.string()
|
|
277
|
-
.check(
|
|
278
|
-
z.describe('Contract address of the fee token.'),
|
|
279
|
-
z.meta({ examples: ['0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'] }),
|
|
280
|
-
),
|
|
281
|
-
chainId: z
|
|
282
|
-
.string()
|
|
283
|
-
.check(z.describe('CAIP-2 chain id of the fee token.'), z.meta({ examples: ['eip155:8453'] })), // prettier-ignore
|
|
284
|
-
decimals: z
|
|
285
|
-
.number()
|
|
286
|
-
.check(
|
|
287
|
-
z.int(),
|
|
288
|
-
z.nonnegative(),
|
|
289
|
-
z.describe('Number of decimal places used by the fee token.'),
|
|
290
|
-
z.meta({ examples: [6] }),
|
|
291
|
-
),
|
|
292
|
-
symbol: z
|
|
293
|
-
.string()
|
|
294
|
-
.check(z.describe('Ticker symbol of the fee token.'), z.meta({ examples: ['USDC'] })),
|
|
295
|
-
}),
|
|
296
|
-
'Token in which a normalized quote fee is denominated.',
|
|
297
|
-
)
|
|
298
|
-
|
|
299
|
-
/** Normalized fee summary for an explicit funding quote. */
|
|
300
|
-
export const QuoteFee = Schema.describe(
|
|
301
|
-
z.object({
|
|
302
|
-
amount: Schema.DecimalString.check(
|
|
303
|
-
z.describe("Fee amount in the fee token's smallest unit."),
|
|
304
|
-
z.meta({ examples: ['1200'] }),
|
|
305
|
-
),
|
|
306
|
-
amountUsd: z
|
|
307
|
-
.nullable(z.string().check(z.regex(/^\d+(\.\d+)?$/)))
|
|
308
|
-
.check(
|
|
309
|
-
z.describe('Provider-estimated USD value of the fee.'),
|
|
310
|
-
z.meta({ examples: ['0.0012'] }),
|
|
311
|
-
),
|
|
312
|
-
bps: z
|
|
313
|
-
.nullable(z.number().check(z.int(), z.nonnegative()))
|
|
314
|
-
.check(z.describe('Fee as basis points of the quoted input.'), z.meta({ examples: [12] })),
|
|
315
|
-
token: QuoteFeeToken,
|
|
316
|
-
}),
|
|
317
|
-
'Provider-neutral fee amount and denomination.',
|
|
205
|
+
'Provider-derived output, limits, and freshness data for a funding quote.',
|
|
318
206
|
)
|
|
319
207
|
|
|
320
|
-
/**
|
|
208
|
+
/** Successful live funding quote. */
|
|
321
209
|
export const FundingQuote = Schema.describe(
|
|
322
|
-
z.object({
|
|
323
|
-
destinationChain: Chain.check(z.describe('Destination chain for the quoted route.')),
|
|
324
|
-
destinationToken: Token.check(z.describe('Token received on the destination chain.')),
|
|
325
|
-
estimatedSeconds: z
|
|
326
|
-
.nullable(z.number().check(z.int(), z.nonnegative()))
|
|
327
|
-
.check(z.describe('Estimated settlement time in seconds.'), z.meta({ examples: [2] })),
|
|
328
|
-
expiresAt: z.iso
|
|
329
|
-
.datetime()
|
|
330
|
-
.check(
|
|
331
|
-
z.describe('Timestamp after which the quote must not be used.'),
|
|
332
|
-
z.meta({ examples: ['2026-01-01T00:01:00Z'] }),
|
|
333
|
-
),
|
|
334
|
-
fees: z
|
|
335
|
-
.object({
|
|
336
|
-
total: QuoteFee.check(z.describe('Current estimated total fee.')),
|
|
337
|
-
totalMax: QuoteFee.check(z.describe('Maximum total fee allowed by the quote.')),
|
|
338
|
-
})
|
|
339
|
-
.check(z.describe('Current and maximum provider fee summaries.')),
|
|
340
|
-
inputAmount: Schema.DecimalString.check(
|
|
341
|
-
z.describe('Exact source amount quoted in base units.'),
|
|
342
|
-
z.meta({ examples: ['1000000'] }),
|
|
343
|
-
),
|
|
344
|
-
minimumOutputAmount: Schema.DecimalString.check(
|
|
345
|
-
z.describe('Slippage-adjusted minimum destination amount in base units.'),
|
|
346
|
-
z.meta({ examples: ['988000'] }),
|
|
347
|
-
),
|
|
348
|
-
outputAmount: Schema.DecimalString.check(
|
|
349
|
-
z.describe('Expected destination amount in base units.'),
|
|
350
|
-
z.meta({ examples: ['990000'] }),
|
|
351
|
-
),
|
|
352
|
-
outputAmountFormatted: z
|
|
353
|
-
.string()
|
|
354
|
-
.check(
|
|
355
|
-
z.describe('Expected destination amount rendered with token decimals.'),
|
|
356
|
-
z.meta({ examples: ['0.99'] }),
|
|
357
|
-
),
|
|
358
|
-
provider: ProviderRef.check(z.describe('Provider that produced the quote.')),
|
|
359
|
-
routeId: z
|
|
360
|
-
.string()
|
|
361
|
-
.check(
|
|
362
|
-
z.describe('Stable id of the curated route that was quoted.'),
|
|
363
|
-
z.meta({ examples: ['base-usdc-tempo-usdce-across'] }),
|
|
364
|
-
),
|
|
365
|
-
sampledAt: z.iso
|
|
366
|
-
.datetime()
|
|
367
|
-
.check(
|
|
368
|
-
z.describe('Timestamp when Tempo sampled the provider quote.'),
|
|
369
|
-
z.meta({ examples: ['2026-01-01T00:00:00Z'] }),
|
|
370
|
-
),
|
|
371
|
-
sourceChain: Chain.check(z.describe('Source chain for the quoted route.')),
|
|
372
|
-
sourceToken: Token.check(z.describe('Token spent on the source chain.')),
|
|
373
|
-
}),
|
|
374
|
-
'Normalized quote information without provider execution payloads.',
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
/** Static or live funding route candidate. */
|
|
378
|
-
export const RouteCandidate = Schema.describe(
|
|
379
210
|
z.object({
|
|
380
211
|
destinationChain: Chain.check(z.describe('Destination chain, always Tempo mainnet in V1.')),
|
|
381
|
-
destinationToken: Token.check(z.describe('Tempo token expected from this
|
|
382
|
-
errorCode: z
|
|
383
|
-
.nullable(z.string())
|
|
384
|
-
.check(
|
|
385
|
-
z.describe('Stable route error code, when status is `error`.'),
|
|
386
|
-
z.meta({ examples: ['provider_timeout'] }),
|
|
387
|
-
),
|
|
212
|
+
destinationToken: Token.check(z.describe('Tempo token expected from this quote.')),
|
|
388
213
|
id: z
|
|
389
214
|
.string()
|
|
390
215
|
.check(
|
|
391
|
-
z.describe('Stable deterministic
|
|
392
|
-
z.meta({ examples: ['base-usdc-tempo-usdce-
|
|
216
|
+
z.describe('Stable deterministic funding quote id.'),
|
|
217
|
+
z.meta({ examples: ['base-usdc-tempo-usdce-relay'] }),
|
|
393
218
|
),
|
|
394
219
|
provider: ProviderRef,
|
|
395
220
|
quality: Quality,
|
|
396
|
-
quote:
|
|
397
|
-
.nullable(RouteQuote)
|
|
398
|
-
.check(z.describe('Provider-derived quote data, when a live route probe succeeds.')),
|
|
221
|
+
quote: QuoteDetails,
|
|
399
222
|
sourceAmount: TokenAmount,
|
|
400
223
|
sourceChain: Chain.check(z.describe('Chain where the caller currently holds funds.')),
|
|
401
224
|
sourceToken: Token.check(z.describe('Token the caller currently holds.')),
|
|
402
|
-
status: z
|
|
403
|
-
.enum(['available', 'thin', 'unknown', 'unavailable', 'error'])
|
|
404
|
-
.check(
|
|
405
|
-
z.describe('Provider-specific route status for the requested amount.'),
|
|
406
|
-
z.meta({ examples: ['unknown'] }),
|
|
407
|
-
),
|
|
408
225
|
}),
|
|
409
|
-
'One provider-specific funding
|
|
226
|
+
'One successful provider-specific funding quote.',
|
|
410
227
|
)
|
|
411
228
|
|
|
412
|
-
/**
|
|
229
|
+
/** Funding quote provider catalog entry. */
|
|
413
230
|
export const Provider = Schema.describe(
|
|
414
231
|
z.object({
|
|
415
|
-
|
|
416
|
-
.
|
|
417
|
-
.check(
|
|
418
|
-
z.describe('Provider capabilities Tempo exposes through public APIs.'),
|
|
419
|
-
z.meta({ examples: [['fundingRoutes']] }),
|
|
420
|
-
),
|
|
421
|
-
id: z.string().check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
|
|
232
|
+
id: z
|
|
233
|
+
.literal('relay')
|
|
234
|
+
.check(z.describe('Stable provider id.'), z.meta({ examples: ['relay'] })),
|
|
422
235
|
kind: z
|
|
423
236
|
.string()
|
|
424
237
|
.check(z.describe('Provider category.'), z.meta({ examples: ['solverNetwork'] })),
|
|
@@ -432,15 +245,15 @@ export namespace schema {
|
|
|
432
245
|
z.meta({ examples: [false] }),
|
|
433
246
|
),
|
|
434
247
|
status: z
|
|
435
|
-
.enum(['configured', '
|
|
248
|
+
.enum(['configured', 'unconfigured'])
|
|
436
249
|
.check(
|
|
437
250
|
z.describe(
|
|
438
|
-
'`
|
|
251
|
+
'`configured` means live quotes are enabled for this deployment. `unconfigured` means the provider is supported but unavailable here.',
|
|
439
252
|
),
|
|
440
|
-
z.meta({ examples: ['
|
|
253
|
+
z.meta({ examples: ['configured', 'unconfigured'] }),
|
|
441
254
|
),
|
|
442
255
|
}),
|
|
443
|
-
'One
|
|
256
|
+
'One funding quote provider.',
|
|
444
257
|
)
|
|
445
258
|
|
|
446
259
|
/** Chain inventory entry returned by the funding chains endpoint. */
|
|
@@ -451,9 +264,9 @@ export namespace schema {
|
|
|
451
264
|
'One source chain and its known stablecoin inventory.',
|
|
452
265
|
)
|
|
453
266
|
|
|
454
|
-
/** Schemas for the
|
|
455
|
-
export namespace
|
|
456
|
-
/** Query parameters for funding
|
|
267
|
+
/** Schemas for the quoteFunding operation. */
|
|
268
|
+
export namespace quoteFunding {
|
|
269
|
+
/** Query parameters for live funding quotes. */
|
|
457
270
|
export const Query = z
|
|
458
271
|
.strictObject({
|
|
459
272
|
destinationToken: z
|
|
@@ -464,26 +277,21 @@ export namespace schema {
|
|
|
464
277
|
),
|
|
465
278
|
z.meta({ examples: ['USDC.e'] }),
|
|
466
279
|
),
|
|
467
|
-
include: z
|
|
468
|
-
.optional(z.string())
|
|
469
|
-
.check(
|
|
470
|
-
z.describe('Comma-separated response expansions. V1 accepts `quotes`.'),
|
|
471
|
-
z.meta({ examples: ['quotes'] }),
|
|
472
|
-
),
|
|
473
|
-
limit: Schema.Limit,
|
|
474
280
|
provider: z
|
|
475
|
-
.optional(z.
|
|
281
|
+
.optional(z.literal('relay'))
|
|
476
282
|
.check(
|
|
477
283
|
z.describe(
|
|
478
|
-
'Only
|
|
284
|
+
'Only request a quote from this provider. The supported id is `relay`; omit it to query every configured provider.',
|
|
479
285
|
),
|
|
480
|
-
z.meta({ examples: ['
|
|
286
|
+
z.meta({ examples: ['relay'] }),
|
|
481
287
|
),
|
|
482
288
|
sourceAmount: z
|
|
483
289
|
.string()
|
|
484
290
|
.check(
|
|
485
|
-
z.
|
|
486
|
-
z.describe(
|
|
291
|
+
z.regex(/^(?=.*[1-9])\d+(\.\d+)?$/),
|
|
292
|
+
z.describe(
|
|
293
|
+
'Positive source token amount. Base units by default, so 1 USDC is `1000000`.',
|
|
294
|
+
),
|
|
487
295
|
z.meta({ examples: ['1000000'] }),
|
|
488
296
|
),
|
|
489
297
|
sourceAmountUnits: z
|
|
@@ -493,98 +301,33 @@ export namespace schema {
|
|
|
493
301
|
z.meta({ examples: ['baseUnits', 'decimal'] }),
|
|
494
302
|
),
|
|
495
303
|
sourceChain: z
|
|
304
|
+
.string()
|
|
305
|
+
.check(
|
|
306
|
+
z.minLength(1),
|
|
307
|
+
z.describe('Source chain alias or CAIP-2 id, such as `base` or `eip155:8453`.'),
|
|
308
|
+
z.meta({ examples: ['base', 'eip155:8453'] }),
|
|
309
|
+
),
|
|
310
|
+
sourceToken: z
|
|
496
311
|
.string()
|
|
497
312
|
.check(
|
|
498
313
|
z.minLength(1),
|
|
499
314
|
z.describe(
|
|
500
|
-
'Source
|
|
315
|
+
'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.',
|
|
501
316
|
),
|
|
502
|
-
z.meta({ examples: ['
|
|
503
|
-
),
|
|
504
|
-
sourceToken: z.string().check(
|
|
505
|
-
z.minLength(1),
|
|
506
|
-
z.describe(
|
|
507
|
-
'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.',
|
|
317
|
+
z.meta({ examples: ['USDC', '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913'] }),
|
|
508
318
|
),
|
|
509
|
-
z.meta({
|
|
510
|
-
examples: [
|
|
511
|
-
'USDC',
|
|
512
|
-
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
|
513
|
-
'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
|
514
|
-
],
|
|
515
|
-
}),
|
|
516
|
-
),
|
|
517
319
|
})
|
|
518
|
-
.check(z.describe('Query parameters for
|
|
320
|
+
.check(z.describe('Query parameters for live funding quotes into Tempo.'))
|
|
519
321
|
|
|
520
|
-
/** Non-paginated list of funding
|
|
322
|
+
/** Non-paginated list of successful funding quotes. */
|
|
521
323
|
export const Response = Schema.describe(
|
|
522
324
|
z.object({
|
|
523
|
-
data: z
|
|
524
|
-
.array(RouteCandidate)
|
|
525
|
-
.check(z.describe('Funding route candidates matching the request.')),
|
|
325
|
+
data: z.array(FundingQuote).check(z.describe('Successful live funding quotes.')),
|
|
526
326
|
}),
|
|
527
|
-
'A non-paginated list of funding
|
|
327
|
+
'A non-paginated list of successful live funding quotes.',
|
|
528
328
|
)
|
|
529
329
|
}
|
|
530
330
|
|
|
531
|
-
/** Schemas for the quoteFundingRoute operation. */
|
|
532
|
-
export namespace quoteFundingRoute {
|
|
533
|
-
/** JSON body for an explicit funding route quote. */
|
|
534
|
-
export const Body = z
|
|
535
|
-
.strictObject({
|
|
536
|
-
depositor: Schema.Address.check(
|
|
537
|
-
z.describe('Address that would submit the funding transaction.'),
|
|
538
|
-
),
|
|
539
|
-
destinationToken: z
|
|
540
|
-
.optional(z.string())
|
|
541
|
-
.check(
|
|
542
|
-
z.describe('Tempo destination token symbol, address, or token key.'),
|
|
543
|
-
z.meta({ examples: ['USDC.e'] }),
|
|
544
|
-
),
|
|
545
|
-
provider: z
|
|
546
|
-
.literal('across')
|
|
547
|
-
.check(
|
|
548
|
-
z.describe('Provider id selected from funding route discovery.'),
|
|
549
|
-
z.meta({ examples: ['across'] }),
|
|
550
|
-
),
|
|
551
|
-
recipient: z
|
|
552
|
-
.optional(Schema.Address)
|
|
553
|
-
.check(z.describe('Optional destination recipient; defaults to the depositor.')),
|
|
554
|
-
sourceAmount: z
|
|
555
|
-
.string()
|
|
556
|
-
.check(
|
|
557
|
-
z.minLength(1),
|
|
558
|
-
z.describe('Exact source amount to quote.'),
|
|
559
|
-
z.meta({ examples: ['1000000'] }),
|
|
560
|
-
),
|
|
561
|
-
sourceAmountUnits: z
|
|
562
|
-
._default(z.enum(['baseUnits', 'decimal']), 'baseUnits')
|
|
563
|
-
.check(
|
|
564
|
-
z.describe('Whether `sourceAmount` uses base units or decimal notation.'),
|
|
565
|
-
z.meta({ examples: ['baseUnits'] }),
|
|
566
|
-
),
|
|
567
|
-
sourceChain: z
|
|
568
|
-
.string()
|
|
569
|
-
.check(
|
|
570
|
-
z.minLength(1),
|
|
571
|
-
z.describe('Source chain alias or CAIP-2 id.'),
|
|
572
|
-
z.meta({ examples: ['base'] }),
|
|
573
|
-
),
|
|
574
|
-
sourceToken: z
|
|
575
|
-
.string()
|
|
576
|
-
.check(
|
|
577
|
-
z.minLength(1),
|
|
578
|
-
z.describe('Source token symbol, address, mint, or token key.'),
|
|
579
|
-
z.meta({ examples: ['USDC'] }),
|
|
580
|
-
),
|
|
581
|
-
})
|
|
582
|
-
.check(z.describe('Parameters for a depositor-specific exact-input funding quote.'))
|
|
583
|
-
|
|
584
|
-
/** Normalized funding quote without provider execution payloads. */
|
|
585
|
-
export const Response = FundingQuote
|
|
586
|
-
}
|
|
587
|
-
|
|
588
331
|
/** Schemas for the listFundingChains operation. */
|
|
589
332
|
export namespace listFundingChains {
|
|
590
333
|
/** Non-paginated source-chain inventory. */
|
|
@@ -592,7 +335,7 @@ export namespace schema {
|
|
|
592
335
|
z.object({
|
|
593
336
|
data: z
|
|
594
337
|
.array(ChainInventory)
|
|
595
|
-
.check(z.describe('Source chains and stablecoins
|
|
338
|
+
.check(z.describe('Source chains and stablecoins supported by funding quotes.')),
|
|
596
339
|
}),
|
|
597
340
|
'A non-paginated list of source chains and stablecoin inventory.',
|
|
598
341
|
)
|
|
@@ -600,168 +343,89 @@ export namespace schema {
|
|
|
600
343
|
|
|
601
344
|
/** Schemas for the listProviders operation. */
|
|
602
345
|
export namespace listProviders {
|
|
603
|
-
/**
|
|
604
|
-
export const Query = z
|
|
605
|
-
.strictObject({
|
|
606
|
-
capability: z
|
|
607
|
-
.optional(z.enum(['fundingRoutes']))
|
|
608
|
-
.check(
|
|
609
|
-
z.describe('Optional provider capability filter.'),
|
|
610
|
-
z.meta({ examples: ['fundingRoutes'] }),
|
|
611
|
-
),
|
|
612
|
-
})
|
|
613
|
-
.check(z.describe('Query parameters for listing providers.'))
|
|
614
|
-
|
|
615
|
-
/** Non-paginated generic provider catalog. */
|
|
346
|
+
/** Non-paginated funding quote provider catalog. */
|
|
616
347
|
export const Response = Schema.describe(
|
|
617
348
|
z.object({
|
|
618
|
-
data: z.array(Provider).check(z.describe("Providers in Tempo's
|
|
349
|
+
data: z.array(Provider).check(z.describe("Providers in Tempo's funding quote catalog.")),
|
|
619
350
|
}),
|
|
620
|
-
'A non-paginated list of providers.',
|
|
351
|
+
'A non-paginated list of funding quote providers.',
|
|
621
352
|
)
|
|
622
353
|
}
|
|
623
354
|
}
|
|
624
355
|
|
|
625
|
-
|
|
626
|
-
const
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
} satisfies z.output<typeof schema.listFundingRoutes.Response>,
|
|
656
|
-
},
|
|
657
|
-
tronUsdt: {
|
|
658
|
-
description:
|
|
659
|
-
'`GET /v1/funding/routes?sourceChain=tron&sourceToken=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t&sourceAmount=1000000&provider=bridge`',
|
|
660
|
-
summary: 'Tron USDT',
|
|
661
|
-
value: {
|
|
662
|
-
data: FundingRoutes.listStaticRoutes({
|
|
663
|
-
limit: 10,
|
|
664
|
-
provider: 'bridge',
|
|
665
|
-
sourceAmount: '1000000',
|
|
666
|
-
sourceAmountUnits: 'baseUnits',
|
|
667
|
-
sourceChain: 'tron',
|
|
668
|
-
sourceToken: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
|
669
|
-
}),
|
|
670
|
-
} satisfies z.output<typeof schema.listFundingRoutes.Response>,
|
|
671
|
-
},
|
|
672
|
-
} satisfies OpenApi.responses.Options<
|
|
673
|
-
typeof schema.listFundingRoutes.Response
|
|
674
|
-
>['success']['examples']
|
|
356
|
+
const fundingQuoteResponseExample = (() => {
|
|
357
|
+
const [candidate] = FundingQuotes.listQuoteCandidates({
|
|
358
|
+
provider: 'relay',
|
|
359
|
+
sourceAmount: '1000000',
|
|
360
|
+
sourceAmountUnits: 'baseUnits',
|
|
361
|
+
sourceChain: 'base',
|
|
362
|
+
sourceToken: 'USDC',
|
|
363
|
+
})
|
|
364
|
+
if (!candidate) throw new Error('Missing Relay funding quote example candidate')
|
|
365
|
+
return {
|
|
366
|
+
data: [
|
|
367
|
+
{
|
|
368
|
+
...candidate,
|
|
369
|
+
quality: {
|
|
370
|
+
estimatedSeconds: 1,
|
|
371
|
+
liquiditySource: 'providerQuote',
|
|
372
|
+
sourceDetail: 'relay:quote-v2',
|
|
373
|
+
tier: 'liquid',
|
|
374
|
+
},
|
|
375
|
+
quote: {
|
|
376
|
+
inputAmount: '1000000',
|
|
377
|
+
minimumOutputAmount: '939242',
|
|
378
|
+
outputAmount: '979295',
|
|
379
|
+
outputAmountFormatted: '0.979295',
|
|
380
|
+
sampledAt: '2026-01-01T00:00:00.000Z',
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
}
|
|
385
|
+
})() satisfies z.output<typeof schema.quoteFunding.Response>
|
|
675
386
|
|
|
676
387
|
const fundingChainsResponseExample = {
|
|
677
|
-
data:
|
|
388
|
+
data: FundingQuotes.listChains(),
|
|
678
389
|
} satisfies z.output<typeof schema.listFundingChains.Response>
|
|
679
390
|
|
|
680
391
|
const providersResponseExample = {
|
|
681
|
-
data:
|
|
392
|
+
data: FundingQuotes.listProviders().map((provider) => ({
|
|
393
|
+
...provider,
|
|
394
|
+
status: 'configured' as const,
|
|
395
|
+
})),
|
|
682
396
|
} satisfies z.output<typeof schema.listProviders.Response>
|
|
683
397
|
|
|
684
|
-
|
|
685
|
-
destinationToken: 'USDC.e',
|
|
686
|
-
limit: 1,
|
|
687
|
-
provider: 'across',
|
|
688
|
-
sourceAmount: '1000000',
|
|
689
|
-
sourceAmountUnits: 'baseUnits',
|
|
690
|
-
sourceChain: 'base',
|
|
691
|
-
sourceToken: 'USDC',
|
|
692
|
-
})
|
|
693
|
-
|
|
694
|
-
const fundingQuoteResponseExample = {
|
|
695
|
-
destinationChain: fundingQuoteRouteExample!.destinationChain,
|
|
696
|
-
destinationToken: fundingQuoteRouteExample!.destinationToken,
|
|
697
|
-
estimatedSeconds: 2,
|
|
698
|
-
expiresAt: '2026-01-01T00:01:00Z',
|
|
699
|
-
fees: {
|
|
700
|
-
total: {
|
|
701
|
-
amount: '1200',
|
|
702
|
-
amountUsd: '0.0012',
|
|
703
|
-
bps: 12,
|
|
704
|
-
token: {
|
|
705
|
-
address: fundingQuoteRouteExample!.sourceToken.address,
|
|
706
|
-
chainId: fundingQuoteRouteExample!.sourceChain.id,
|
|
707
|
-
decimals: fundingQuoteRouteExample!.sourceToken.decimals,
|
|
708
|
-
symbol: fundingQuoteRouteExample!.sourceToken.symbol,
|
|
709
|
-
},
|
|
710
|
-
},
|
|
711
|
-
totalMax: {
|
|
712
|
-
amount: '1800',
|
|
713
|
-
amountUsd: '0.0018',
|
|
714
|
-
bps: 18,
|
|
715
|
-
token: {
|
|
716
|
-
address: fundingQuoteRouteExample!.sourceToken.address,
|
|
717
|
-
chainId: fundingQuoteRouteExample!.sourceChain.id,
|
|
718
|
-
decimals: fundingQuoteRouteExample!.sourceToken.decimals,
|
|
719
|
-
symbol: fundingQuoteRouteExample!.sourceToken.symbol,
|
|
720
|
-
},
|
|
721
|
-
},
|
|
722
|
-
},
|
|
723
|
-
inputAmount: '1000000',
|
|
724
|
-
minimumOutputAmount: '988000',
|
|
725
|
-
outputAmount: '990000',
|
|
726
|
-
outputAmountFormatted: '0.99',
|
|
727
|
-
provider: fundingQuoteRouteExample!.provider,
|
|
728
|
-
routeId: fundingQuoteRouteExample!.id,
|
|
729
|
-
sampledAt: '2026-01-01T00:00:00Z',
|
|
730
|
-
sourceChain: fundingQuoteRouteExample!.sourceChain,
|
|
731
|
-
sourceToken: fundingQuoteRouteExample!.sourceToken,
|
|
732
|
-
} satisfies z.output<typeof schema.quoteFundingRoute.Response>
|
|
733
|
-
|
|
734
|
-
/** Mounts funding route discovery and generic provider inventory endpoints. */
|
|
398
|
+
/** Mounts live funding quotes and their supporting inventory endpoints. */
|
|
735
399
|
export function funding(options: funding.Options = {}) {
|
|
736
400
|
return new Hono<App.Environment>()
|
|
737
401
|
.get(
|
|
738
|
-
'/v1/funding/
|
|
402
|
+
'/v1/funding/quotes',
|
|
739
403
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
740
|
-
OpenApi.validate('query', schema.
|
|
404
|
+
OpenApi.validate('query', schema.quoteFunding.Query, {
|
|
741
405
|
code: 'query_invalid',
|
|
742
406
|
message: 'Invalid query parameters',
|
|
743
407
|
}),
|
|
744
408
|
OpenApi.describeRoute({
|
|
745
409
|
description:
|
|
746
|
-
'
|
|
747
|
-
operationId: '
|
|
410
|
+
'Returns live quotes for funding Tempo with a stablecoin. Omit `provider` to query all configured providers. This endpoint does not execute a transfer.',
|
|
411
|
+
operationId: 'quoteFunding',
|
|
748
412
|
responses: OpenApi.responses({
|
|
749
|
-
errors: {
|
|
413
|
+
errors: {
|
|
414
|
+
400: { codes: ['query_invalid'] },
|
|
415
|
+
502: {
|
|
416
|
+
codes: ['upstream_error'],
|
|
417
|
+
description: 'Every matching quote provider failed unexpectedly.',
|
|
418
|
+
},
|
|
419
|
+
},
|
|
750
420
|
success: {
|
|
751
|
-
description:
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
schema: schema.listFundingRoutes.Response,
|
|
421
|
+
description: 'Live funding quotes. An empty list means no provider returned a quote.',
|
|
422
|
+
example: fundingQuoteResponseExample,
|
|
423
|
+
schema: schema.quoteFunding.Response,
|
|
755
424
|
},
|
|
756
425
|
}),
|
|
757
|
-
summary: '
|
|
426
|
+
summary: 'Get funding quotes',
|
|
758
427
|
tags: ['Funding'],
|
|
759
428
|
}),
|
|
760
|
-
Cache.response<App.Environment>({
|
|
761
|
-
cacheControl: Cache.policies.noStore,
|
|
762
|
-
name: 'tempo-api:funding-routes:v1',
|
|
763
|
-
key: (c) => Cache.urlKey(c, schema.listFundingRoutes.Query),
|
|
764
|
-
}),
|
|
765
429
|
async (c) => {
|
|
766
430
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
767
431
|
if (OpenApi.narrowValidation)
|
|
@@ -772,16 +436,14 @@ export function funding(options: funding.Options = {}) {
|
|
|
772
436
|
|
|
773
437
|
const query = c.req.valid('query')
|
|
774
438
|
try {
|
|
775
|
-
|
|
439
|
+
c.header('Cache-Control', 'no-store')
|
|
776
440
|
return c.json(
|
|
777
|
-
Response.validated(schema.
|
|
778
|
-
data: await
|
|
441
|
+
Response.validated(schema.quoteFunding.Response, {
|
|
442
|
+
data: await FundingQuotes.listQuotes({
|
|
779
443
|
adapters: options.adapters,
|
|
780
444
|
adapterTimeoutMs: options.adapterTimeoutMs,
|
|
781
445
|
cache: { bypass: cacheBypass(c.req.raw) },
|
|
782
446
|
destinationToken: query.destinationToken,
|
|
783
|
-
include,
|
|
784
|
-
limit: query.limit,
|
|
785
447
|
provider: query.provider,
|
|
786
448
|
sourceAmount: query.sourceAmount,
|
|
787
449
|
sourceAmountUnits: query.sourceAmountUnits,
|
|
@@ -794,103 +456,12 @@ export function funding(options: funding.Options = {}) {
|
|
|
794
456
|
} catch (cause) {
|
|
795
457
|
const message = requestErrorMessage(cause)
|
|
796
458
|
if (message) return Response.error(c, { code: 'query_invalid', message, status: 400 })
|
|
797
|
-
|
|
798
|
-
}
|
|
799
|
-
},
|
|
800
|
-
)
|
|
801
|
-
.post(
|
|
802
|
-
'/v1/funding/routes/quote',
|
|
803
|
-
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
804
|
-
OpenApi.validate('json', schema.quoteFundingRoute.Body, {
|
|
805
|
-
code: 'body_invalid',
|
|
806
|
-
message: 'Invalid quote parameters',
|
|
807
|
-
}),
|
|
808
|
-
OpenApi.describeRoute({
|
|
809
|
-
description:
|
|
810
|
-
'Gets a depositor-specific exact-input quote for one curated funding route. The response excludes provider transaction calldata, approvals, and wallet balance details.',
|
|
811
|
-
operationId: 'quoteFundingRoute',
|
|
812
|
-
responses: OpenApi.responses({
|
|
813
|
-
errors: {
|
|
814
|
-
400: { codes: ['body_invalid'] },
|
|
815
|
-
404: { codes: ['route_not_found', 'quote_unavailable'] },
|
|
816
|
-
501: { codes: ['provider_unconfigured'] },
|
|
817
|
-
502: { codes: ['provider_error', 'provider_rate_limited', 'provider_timeout'] },
|
|
818
|
-
},
|
|
819
|
-
success: {
|
|
820
|
-
description: 'Normalized route quote without provider execution payloads.',
|
|
821
|
-
example: fundingQuoteResponseExample,
|
|
822
|
-
schema: schema.quoteFundingRoute.Response,
|
|
823
|
-
},
|
|
824
|
-
}),
|
|
825
|
-
summary: 'Quote funding route',
|
|
826
|
-
tags: ['Funding'],
|
|
827
|
-
}),
|
|
828
|
-
async (c) => {
|
|
829
|
-
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
830
|
-
if (OpenApi.narrowValidation)
|
|
831
|
-
return OpenApi.validationError(c, {
|
|
832
|
-
code: 'body_invalid',
|
|
833
|
-
message: 'Invalid quote parameters',
|
|
834
|
-
})
|
|
835
|
-
|
|
836
|
-
const body = c.req.valid('json')
|
|
837
|
-
try {
|
|
838
|
-
const quote = await FundingRoutes.quoteRoute({
|
|
839
|
-
depositor: body.depositor,
|
|
840
|
-
destinationToken: body.destinationToken,
|
|
841
|
-
provider: body.provider,
|
|
842
|
-
quote: options.acrossQuote,
|
|
843
|
-
quoteTimeoutMs: options.quoteTimeoutMs,
|
|
844
|
-
recipient: body.recipient,
|
|
845
|
-
sourceAmount: body.sourceAmount,
|
|
846
|
-
sourceAmountUnits: body.sourceAmountUnits,
|
|
847
|
-
sourceChain: body.sourceChain,
|
|
848
|
-
sourceToken: body.sourceToken,
|
|
849
|
-
})
|
|
850
|
-
c.header('Cache-Control', 'no-store')
|
|
851
|
-
return c.json(Response.validated(schema.quoteFundingRoute.Response, quote), 200)
|
|
852
|
-
} catch (cause) {
|
|
853
|
-
const message = requestErrorMessage(cause)
|
|
854
|
-
if (message) return Response.error(c, { code: 'body_invalid', message, status: 400 })
|
|
855
|
-
if (cause instanceof FundingRoutes.FundingRouteNotFoundError)
|
|
459
|
+
if (cause instanceof FundingQuotes.ProviderQuoteError)
|
|
856
460
|
return Response.error(c, {
|
|
857
|
-
code: '
|
|
858
|
-
message: '
|
|
859
|
-
status: 404,
|
|
860
|
-
})
|
|
861
|
-
if (cause instanceof FundingRoutes.ProviderQuoteUnavailableError)
|
|
862
|
-
return Response.error(c, {
|
|
863
|
-
code: 'quote_unavailable',
|
|
864
|
-
message: 'The provider cannot quote this route.',
|
|
865
|
-
status: 404,
|
|
866
|
-
})
|
|
867
|
-
if (cause instanceof FundingRoutes.ProviderNotConfiguredError)
|
|
868
|
-
return Response.error(c, {
|
|
869
|
-
code: 'provider_unconfigured',
|
|
870
|
-
message: 'The provider quote integration is not configured.',
|
|
871
|
-
status: 501,
|
|
872
|
-
})
|
|
873
|
-
if (cause instanceof FundingRoutes.ProviderRateLimitError)
|
|
874
|
-
return Response.error(c, {
|
|
875
|
-
code: 'provider_rate_limited',
|
|
876
|
-
message: 'The provider temporarily rate-limited this quote.',
|
|
461
|
+
code: 'upstream_error',
|
|
462
|
+
message: 'Quote providers could not complete the request.',
|
|
877
463
|
status: 502,
|
|
878
464
|
})
|
|
879
|
-
if (cause instanceof FundingRoutes.ProviderAdapterTimeoutError)
|
|
880
|
-
return Response.error(c, {
|
|
881
|
-
code: 'provider_timeout',
|
|
882
|
-
message: 'The provider quote timed out.',
|
|
883
|
-
status: 502,
|
|
884
|
-
})
|
|
885
|
-
if (cause instanceof Error) {
|
|
886
|
-
const providerFailure = FundingRouteProviders.acrossQuoteFailure({ cause })
|
|
887
|
-
if (providerFailure) c.set('providerFailure', providerFailure)
|
|
888
|
-
return Response.error(c, {
|
|
889
|
-
code: 'provider_error',
|
|
890
|
-
message: 'The provider could not complete the quote.',
|
|
891
|
-
status: 502,
|
|
892
|
-
})
|
|
893
|
-
}
|
|
894
465
|
throw cause
|
|
895
466
|
}
|
|
896
467
|
},
|
|
@@ -900,11 +471,11 @@ export function funding(options: funding.Options = {}) {
|
|
|
900
471
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
901
472
|
OpenApi.describeRoute({
|
|
902
473
|
description:
|
|
903
|
-
'Lists source chains and stablecoins
|
|
474
|
+
'Lists the source chains and stablecoins you can use when requesting a funding quote.',
|
|
904
475
|
operationId: 'listFundingChains',
|
|
905
476
|
responses: OpenApi.responses({
|
|
906
477
|
success: {
|
|
907
|
-
description: '
|
|
478
|
+
description: 'Supported source chains and stablecoins.',
|
|
908
479
|
example: fundingChainsResponseExample,
|
|
909
480
|
schema: schema.listFundingChains.Response,
|
|
910
481
|
},
|
|
@@ -921,55 +492,39 @@ export function funding(options: funding.Options = {}) {
|
|
|
921
492
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
922
493
|
return c.json(
|
|
923
494
|
Response.validated(schema.listFundingChains.Response, {
|
|
924
|
-
data:
|
|
495
|
+
data: FundingQuotes.listChains(),
|
|
925
496
|
}),
|
|
926
497
|
200,
|
|
927
498
|
)
|
|
928
499
|
},
|
|
929
500
|
)
|
|
930
501
|
.get(
|
|
931
|
-
'/v1/providers',
|
|
502
|
+
'/v1/funding/providers',
|
|
932
503
|
Auth.policy({ apiKey: { scopes: ['data:read'] }, mpp: true, public: true }),
|
|
933
|
-
OpenApi.validate('query', schema.listProviders.Query, {
|
|
934
|
-
code: 'query_invalid',
|
|
935
|
-
message: 'Invalid query parameters',
|
|
936
|
-
}),
|
|
937
504
|
OpenApi.describeRoute({
|
|
938
505
|
description:
|
|
939
|
-
'Lists
|
|
940
|
-
operationId: '
|
|
506
|
+
'Lists funding quote providers and whether live quoting is configured for this deployment.',
|
|
507
|
+
operationId: 'listFundingProviders',
|
|
941
508
|
responses: OpenApi.responses({
|
|
942
|
-
errors: { 400: { codes: ['query_invalid'] } },
|
|
943
509
|
success: {
|
|
944
|
-
description: '
|
|
510
|
+
description: 'Funding quote providers supported by Tempo.',
|
|
945
511
|
example: providersResponseExample,
|
|
946
512
|
schema: schema.listProviders.Response,
|
|
947
513
|
},
|
|
948
514
|
}),
|
|
949
|
-
summary: 'List providers',
|
|
950
|
-
tags: ['
|
|
515
|
+
summary: 'List funding providers',
|
|
516
|
+
tags: ['Funding'],
|
|
951
517
|
}),
|
|
952
518
|
Cache.response<App.Environment>({
|
|
953
519
|
cacheControl: Cache.policies.stable,
|
|
954
|
-
name: 'tempo-api:providers:v1',
|
|
955
|
-
key: (c) =>
|
|
520
|
+
name: 'tempo-api:funding-providers:v1',
|
|
521
|
+
key: (c) => c.req.url,
|
|
956
522
|
}),
|
|
957
523
|
(c) => {
|
|
958
524
|
if (Auth.narrowAccess) return Auth.paidAccessError(c)
|
|
959
|
-
if (OpenApi.narrowValidation)
|
|
960
|
-
return OpenApi.validationError(c, {
|
|
961
|
-
code: 'query_invalid',
|
|
962
|
-
message: 'Invalid query parameters',
|
|
963
|
-
})
|
|
964
|
-
|
|
965
|
-
const query = c.req.valid('query')
|
|
966
525
|
return c.json(
|
|
967
526
|
Response.validated(schema.listProviders.Response, {
|
|
968
|
-
data:
|
|
969
|
-
adapters: options.adapters,
|
|
970
|
-
capability: query.capability,
|
|
971
|
-
configuredProviders: options.acrossQuote ? ['across'] : [],
|
|
972
|
-
}),
|
|
527
|
+
data: FundingQuotes.listProviders({ adapters: options.adapters }),
|
|
973
528
|
}),
|
|
974
529
|
200,
|
|
975
530
|
)
|
|
@@ -978,27 +533,22 @@ export function funding(options: funding.Options = {}) {
|
|
|
978
533
|
}
|
|
979
534
|
|
|
980
535
|
export declare namespace funding {
|
|
981
|
-
/** Options for funding
|
|
536
|
+
/** Options for live funding quotes. */
|
|
982
537
|
type Options = {
|
|
983
|
-
/**
|
|
984
|
-
|
|
985
|
-
/** Provider adapters used to enrich static inventory with live data. */
|
|
986
|
-
adapters?: FundingRoutes.ProviderAdapters | undefined
|
|
538
|
+
/** Provider adapters used to request live quotes. */
|
|
539
|
+
adapters?: FundingQuotes.ProviderAdapters | undefined
|
|
987
540
|
/** Per-provider quote timeout in milliseconds. */
|
|
988
541
|
adapterTimeoutMs?: number | undefined
|
|
989
|
-
/** Timeout for depositor-specific provider quotes. */
|
|
990
|
-
quoteTimeoutMs?: number | undefined
|
|
991
542
|
}
|
|
992
543
|
}
|
|
993
544
|
|
|
994
545
|
// Maps caller-input errors to a specific 400 message; anything else rethrows.
|
|
995
546
|
function requestErrorMessage(cause: unknown) {
|
|
996
|
-
if (cause instanceof
|
|
997
|
-
if (cause instanceof
|
|
998
|
-
if (cause instanceof FundingRoutes.UnsupportedDestinationTokenError)
|
|
547
|
+
if (cause instanceof FundingQuotes.InvalidAmountError) return 'Invalid `sourceAmount`.'
|
|
548
|
+
if (cause instanceof FundingQuotes.UnsupportedDestinationTokenError)
|
|
999
549
|
return 'Unsupported `destinationToken`.'
|
|
1000
|
-
if (cause instanceof
|
|
1001
|
-
if (cause instanceof
|
|
550
|
+
if (cause instanceof FundingQuotes.UnsupportedProviderError) return 'Unsupported `provider`.'
|
|
551
|
+
if (cause instanceof FundingQuotes.UnsupportedSourceChainError)
|
|
1002
552
|
return 'Unsupported `sourceChain`.'
|
|
1003
553
|
return undefined
|
|
1004
554
|
}
|