@dextopus/api-sdk 0.1.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/index.d.mts +391 -0
- package/dist/index.d.ts +391 -0
- package/dist/index.js +183 -0
- package/dist/index.mjs +153 -0
- package/package.json +22 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
type PartnerFee = {
|
|
2
|
+
recipient: string;
|
|
3
|
+
feeBPS: number;
|
|
4
|
+
};
|
|
5
|
+
type QuoteRequest = {
|
|
6
|
+
chainIdFrom: number;
|
|
7
|
+
chainIdTo?: number;
|
|
8
|
+
tokenIn: string;
|
|
9
|
+
tokenOut: string;
|
|
10
|
+
amountIn: string;
|
|
11
|
+
includeBridges?: string[];
|
|
12
|
+
partnerFees?: PartnerFee[];
|
|
13
|
+
};
|
|
14
|
+
type FeeBreakdown = {
|
|
15
|
+
type: 'protocol' | 'integrator' | 'gas' | 'bridge' | 'swap' | string;
|
|
16
|
+
amount: string;
|
|
17
|
+
token: string;
|
|
18
|
+
recipient?: string;
|
|
19
|
+
};
|
|
20
|
+
type FeeDetails = {
|
|
21
|
+
total: string;
|
|
22
|
+
breakdown: FeeBreakdown[];
|
|
23
|
+
};
|
|
24
|
+
type QuoteEdge = {
|
|
25
|
+
from: {
|
|
26
|
+
chainId: number;
|
|
27
|
+
tokenAddress: string;
|
|
28
|
+
};
|
|
29
|
+
to: {
|
|
30
|
+
chainId: number;
|
|
31
|
+
tokenAddress: string;
|
|
32
|
+
};
|
|
33
|
+
adaptor: string;
|
|
34
|
+
type: 'swap' | 'bridge';
|
|
35
|
+
amountIn: string;
|
|
36
|
+
estimatedAmountOut: string;
|
|
37
|
+
priceImpact: string;
|
|
38
|
+
fees: {
|
|
39
|
+
total: string;
|
|
40
|
+
breakdown: Array<{
|
|
41
|
+
type: string;
|
|
42
|
+
amount: string;
|
|
43
|
+
token?: string;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
46
|
+
gasEstimate: string;
|
|
47
|
+
metadata: Record<string, unknown>;
|
|
48
|
+
timestamp: number;
|
|
49
|
+
};
|
|
50
|
+
type QuoteRoute = {
|
|
51
|
+
quoteId: string;
|
|
52
|
+
path: QuoteEdge[];
|
|
53
|
+
sourceToken: {
|
|
54
|
+
chainId: number;
|
|
55
|
+
address: string;
|
|
56
|
+
symbol: string;
|
|
57
|
+
decimals: number;
|
|
58
|
+
};
|
|
59
|
+
destToken: {
|
|
60
|
+
chainId: number;
|
|
61
|
+
address: string;
|
|
62
|
+
symbol: string;
|
|
63
|
+
decimals: number;
|
|
64
|
+
};
|
|
65
|
+
amountIn: string;
|
|
66
|
+
amountOut: string;
|
|
67
|
+
fees: FeeDetails;
|
|
68
|
+
priceImpact: string;
|
|
69
|
+
estimatedGas: string;
|
|
70
|
+
expiresAt: number;
|
|
71
|
+
};
|
|
72
|
+
type QuoteAlternativeRoute = {
|
|
73
|
+
path: QuoteEdge[];
|
|
74
|
+
amountOut: string;
|
|
75
|
+
fees: FeeDetails;
|
|
76
|
+
};
|
|
77
|
+
type QuoteResponse = {
|
|
78
|
+
quoteId: string;
|
|
79
|
+
bestRoute: QuoteRoute;
|
|
80
|
+
alternativeRoutes: QuoteAlternativeRoute[];
|
|
81
|
+
};
|
|
82
|
+
type BuildTransactionRequest = {
|
|
83
|
+
quoteId: string;
|
|
84
|
+
userAddress: string;
|
|
85
|
+
recipient?: string;
|
|
86
|
+
partnerFees?: PartnerFee[];
|
|
87
|
+
simulate?: boolean;
|
|
88
|
+
};
|
|
89
|
+
type EvmTransactionPayload = {
|
|
90
|
+
from: string;
|
|
91
|
+
to: string;
|
|
92
|
+
data: string;
|
|
93
|
+
value: string;
|
|
94
|
+
chainId: number;
|
|
95
|
+
gasLimit?: string;
|
|
96
|
+
gasPrice?: string;
|
|
97
|
+
maxFeePerGas?: string;
|
|
98
|
+
maxPriorityFeePerGas?: string;
|
|
99
|
+
nonce?: number;
|
|
100
|
+
};
|
|
101
|
+
type TronTransactionPayload = {
|
|
102
|
+
from: string;
|
|
103
|
+
to: string;
|
|
104
|
+
input: string;
|
|
105
|
+
callValue: string;
|
|
106
|
+
chainId: number;
|
|
107
|
+
};
|
|
108
|
+
type TransactionPayload = EvmTransactionPayload | TronTransactionPayload;
|
|
109
|
+
type TransactionStep = {
|
|
110
|
+
step: number;
|
|
111
|
+
adaptor: string;
|
|
112
|
+
type: 'approval' | 'diamond';
|
|
113
|
+
chainId: number;
|
|
114
|
+
transaction: TransactionPayload;
|
|
115
|
+
description: string;
|
|
116
|
+
};
|
|
117
|
+
type TransactionSimulationStep = {
|
|
118
|
+
step: number;
|
|
119
|
+
type: string;
|
|
120
|
+
adaptor: string;
|
|
121
|
+
chainId: number;
|
|
122
|
+
estimated: boolean;
|
|
123
|
+
gas?: string;
|
|
124
|
+
error?: string;
|
|
125
|
+
};
|
|
126
|
+
type TransactionSimulation = {
|
|
127
|
+
allEstimated: boolean;
|
|
128
|
+
steps: TransactionSimulationStep[];
|
|
129
|
+
};
|
|
130
|
+
type BuildTransactionResponse = {
|
|
131
|
+
quoteId: string;
|
|
132
|
+
transactions: TransactionStep[];
|
|
133
|
+
totalSteps: number;
|
|
134
|
+
expiresAt: number;
|
|
135
|
+
simulation?: TransactionSimulation;
|
|
136
|
+
};
|
|
137
|
+
type DepositFee = {
|
|
138
|
+
recipient: string;
|
|
139
|
+
fee: number;
|
|
140
|
+
};
|
|
141
|
+
type DepositQuoteRequest = {
|
|
142
|
+
originChainId: number;
|
|
143
|
+
destinationChainId: number;
|
|
144
|
+
originAsset: string;
|
|
145
|
+
destinationAsset: string;
|
|
146
|
+
amount: string;
|
|
147
|
+
recipient: string;
|
|
148
|
+
refundTo?: string;
|
|
149
|
+
user?: string;
|
|
150
|
+
slippageBps?: number;
|
|
151
|
+
dry?: boolean;
|
|
152
|
+
partnerFees?: DepositFee[];
|
|
153
|
+
/**
|
|
154
|
+
* If provided, amount is treated as human-readable (e.g., "10" for 10 USDC)
|
|
155
|
+
* and will be converted to smallest unit using this decimals value.
|
|
156
|
+
* If not provided, amount is treated as smallest unit (backward compatible).
|
|
157
|
+
*/
|
|
158
|
+
decimals?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Request a static/reusable deposit address.
|
|
161
|
+
* When true, requests a deposit address that:
|
|
162
|
+
* - Can be reused for multiple deposits
|
|
163
|
+
* - Remains valid after quote rate expires (rate recalculated at deposit time)
|
|
164
|
+
* - Accepts different tokens (e.g., send USDC when quote was for SOL)
|
|
165
|
+
* Note: Only available for supported routes. Check supportsStaticAddress field.
|
|
166
|
+
*/
|
|
167
|
+
static?: boolean;
|
|
168
|
+
};
|
|
169
|
+
type DepositStatusParams = {
|
|
170
|
+
depositRequestId?: string;
|
|
171
|
+
depositAddress?: string;
|
|
172
|
+
requestId?: string;
|
|
173
|
+
};
|
|
174
|
+
type DepositSubmitRequest = {
|
|
175
|
+
depositRequestId?: string;
|
|
176
|
+
depositAddress?: string;
|
|
177
|
+
txHash: string;
|
|
178
|
+
};
|
|
179
|
+
type DepositQuoteResponse = {
|
|
180
|
+
success: boolean;
|
|
181
|
+
depositRequestId: string;
|
|
182
|
+
depositAddress: string;
|
|
183
|
+
isStaticAddress?: boolean;
|
|
184
|
+
upstreamRequestId?: string;
|
|
185
|
+
upstreamQuoteId?: string;
|
|
186
|
+
amountOut?: string;
|
|
187
|
+
minAmountOut?: string;
|
|
188
|
+
status?: string;
|
|
189
|
+
sentAppFees?: DepositFee[];
|
|
190
|
+
effectiveUpstreamAppFees?: DepositFee[];
|
|
191
|
+
expiresInSeconds?: number;
|
|
192
|
+
};
|
|
193
|
+
type DepositStatusResponse = {
|
|
194
|
+
success: boolean;
|
|
195
|
+
depositRequestId: string;
|
|
196
|
+
depositAddress?: string;
|
|
197
|
+
isStaticAddress?: boolean;
|
|
198
|
+
upstreamRequestId?: string;
|
|
199
|
+
status?: string;
|
|
200
|
+
executionStatus?: string;
|
|
201
|
+
sentAppFees?: DepositFee[];
|
|
202
|
+
effectiveUpstreamAppFees?: DepositFee[];
|
|
203
|
+
originTransactionHashes?: string[];
|
|
204
|
+
destinationTransactionHashes?: string[];
|
|
205
|
+
raw?: Record<string, unknown>;
|
|
206
|
+
};
|
|
207
|
+
type DepositSubmitResponse = {
|
|
208
|
+
success: boolean;
|
|
209
|
+
depositRequestId: string;
|
|
210
|
+
depositAddress: string;
|
|
211
|
+
result: Record<string, unknown>;
|
|
212
|
+
};
|
|
213
|
+
type Currency = {
|
|
214
|
+
address?: string;
|
|
215
|
+
id?: string;
|
|
216
|
+
symbol?: string;
|
|
217
|
+
name?: string;
|
|
218
|
+
decimals?: number;
|
|
219
|
+
};
|
|
220
|
+
type Chain = {
|
|
221
|
+
chainId?: number;
|
|
222
|
+
name?: string;
|
|
223
|
+
solverCurrencies: Currency[];
|
|
224
|
+
supportsStaticAddress?: boolean;
|
|
225
|
+
};
|
|
226
|
+
type DepositToken = {
|
|
227
|
+
address: string;
|
|
228
|
+
symbol: string;
|
|
229
|
+
blockchain: string;
|
|
230
|
+
chainId?: number;
|
|
231
|
+
decimals?: number;
|
|
232
|
+
supportsStaticAddress: boolean;
|
|
233
|
+
};
|
|
234
|
+
type DepositTokensResponse = {
|
|
235
|
+
success: boolean;
|
|
236
|
+
chains: Chain[];
|
|
237
|
+
tokens: DepositToken[];
|
|
238
|
+
countChains: number;
|
|
239
|
+
countTokens: number;
|
|
240
|
+
};
|
|
241
|
+
/** @deprecated Use Currency instead */
|
|
242
|
+
type RelayCurrency = Currency;
|
|
243
|
+
/** @deprecated Use Chain instead */
|
|
244
|
+
type RelayChain = Chain;
|
|
245
|
+
/** @deprecated Use DepositToken instead */
|
|
246
|
+
type NearToken = {
|
|
247
|
+
assetId: string;
|
|
248
|
+
decimals: number;
|
|
249
|
+
blockchain: string;
|
|
250
|
+
symbol: string;
|
|
251
|
+
price?: number;
|
|
252
|
+
priceUpdatedAt?: string;
|
|
253
|
+
contractAddress?: string | null;
|
|
254
|
+
};
|
|
255
|
+
/** @deprecated Use DepositToken instead */
|
|
256
|
+
type UnifiedToken = DepositToken;
|
|
257
|
+
type AddressKind = 'evm' | 'near' | 'solana' | 'tron' | 'bitcoin' | 'litecoin' | 'stellar' | 'sui' | 'ton' | 'xrp';
|
|
258
|
+
type DepositDestination = {
|
|
259
|
+
currency: string;
|
|
260
|
+
symbol?: string;
|
|
261
|
+
blockchain?: string;
|
|
262
|
+
destinationChainId?: number;
|
|
263
|
+
decimals?: number;
|
|
264
|
+
addressKind: AddressKind | null;
|
|
265
|
+
supportsStaticAddress: boolean;
|
|
266
|
+
};
|
|
267
|
+
type DepositDestinationChain = {
|
|
268
|
+
blockchain: string;
|
|
269
|
+
chainId?: number;
|
|
270
|
+
addressKind: AddressKind | null;
|
|
271
|
+
count: number;
|
|
272
|
+
supportsStaticAddress: boolean;
|
|
273
|
+
};
|
|
274
|
+
type DepositDestinationsResponse = {
|
|
275
|
+
success: boolean;
|
|
276
|
+
originAssetId?: string;
|
|
277
|
+
originAddress?: string;
|
|
278
|
+
originAddressKind: AddressKind | null;
|
|
279
|
+
destinations: DepositDestination[];
|
|
280
|
+
destinationChains: DepositDestinationChain[];
|
|
281
|
+
count: number;
|
|
282
|
+
};
|
|
283
|
+
type DepositSource = {
|
|
284
|
+
currency: string;
|
|
285
|
+
symbol?: string;
|
|
286
|
+
blockchain?: string;
|
|
287
|
+
sourceChainId?: number;
|
|
288
|
+
decimals?: number;
|
|
289
|
+
addressKind: AddressKind | null;
|
|
290
|
+
supportsStaticAddress: boolean;
|
|
291
|
+
};
|
|
292
|
+
type DepositSourceChain = {
|
|
293
|
+
blockchain: string;
|
|
294
|
+
chainId?: number;
|
|
295
|
+
addressKind: AddressKind | null;
|
|
296
|
+
count: number;
|
|
297
|
+
supportsStaticAddress: boolean;
|
|
298
|
+
};
|
|
299
|
+
type DepositSourcesResponse = {
|
|
300
|
+
success: boolean;
|
|
301
|
+
destinationAssetId?: string;
|
|
302
|
+
destinationAddress?: string;
|
|
303
|
+
destinationAddressKind: AddressKind | null;
|
|
304
|
+
sources: DepositSource[];
|
|
305
|
+
sourceChains: DepositSourceChain[];
|
|
306
|
+
count: number;
|
|
307
|
+
};
|
|
308
|
+
type DepositDestinationsParams = {
|
|
309
|
+
originAssetId?: string;
|
|
310
|
+
originAddress?: string;
|
|
311
|
+
originChainId?: number;
|
|
312
|
+
};
|
|
313
|
+
type DepositSourcesParams = {
|
|
314
|
+
destinationAssetId?: string;
|
|
315
|
+
destinationAddress?: string;
|
|
316
|
+
destinationChainId?: number;
|
|
317
|
+
};
|
|
318
|
+
type ValidateAddressRequest = {
|
|
319
|
+
chainType: AddressKind;
|
|
320
|
+
address: string;
|
|
321
|
+
};
|
|
322
|
+
type ValidateAddressResponse = {
|
|
323
|
+
success: boolean;
|
|
324
|
+
valid: boolean;
|
|
325
|
+
reason?: string;
|
|
326
|
+
};
|
|
327
|
+
type HealthResponse = {
|
|
328
|
+
status: 'healthy' | 'degraded';
|
|
329
|
+
service: string;
|
|
330
|
+
version: string;
|
|
331
|
+
timestamp: number;
|
|
332
|
+
dependencies: Record<string, 'up' | 'down'>;
|
|
333
|
+
};
|
|
334
|
+
type ApiErrorDetail = {
|
|
335
|
+
field: string;
|
|
336
|
+
message: string;
|
|
337
|
+
};
|
|
338
|
+
type ApiErrorShape = {
|
|
339
|
+
error?: string;
|
|
340
|
+
message?: string;
|
|
341
|
+
errorCode?: string;
|
|
342
|
+
quoteId?: string;
|
|
343
|
+
expiresAt?: number;
|
|
344
|
+
expiredAt?: string;
|
|
345
|
+
details?: ApiErrorDetail[];
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
type ApiClientOptions = {
|
|
349
|
+
baseUrl?: string;
|
|
350
|
+
apiKey?: string;
|
|
351
|
+
fetch?: typeof fetch;
|
|
352
|
+
timeoutMs?: number;
|
|
353
|
+
};
|
|
354
|
+
declare class ApiError extends Error {
|
|
355
|
+
status: number;
|
|
356
|
+
body?: ApiErrorShape | string;
|
|
357
|
+
constructor(status: number, message: string, body?: ApiErrorShape | string);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Convert human-readable amount to smallest unit
|
|
361
|
+
* @param amount Human-readable amount (e.g., "10" for 10 USDC)
|
|
362
|
+
* @param decimals Token decimals (e.g., 6 for USDC, 9 for SOL)
|
|
363
|
+
* @returns Amount in smallest unit as string
|
|
364
|
+
* @example toSmallestUnit("10", 6) // Returns "10000000" for 10 USDC
|
|
365
|
+
* @example toSmallestUnit("1.5", 9) // Returns "1500000000" for 1.5 SOL
|
|
366
|
+
*/
|
|
367
|
+
declare function toSmallestUnit(amount: string, decimals: number): string;
|
|
368
|
+
/**
|
|
369
|
+
* Convert smallest unit amount to human-readable format
|
|
370
|
+
* @param amount Amount in smallest unit (e.g., "10000000" for USDC)
|
|
371
|
+
* @param decimals Token decimals (e.g., 6 for USDC, 9 for SOL)
|
|
372
|
+
* @returns Human-readable amount as string
|
|
373
|
+
* @example fromSmallestUnit("10000000", 6) // Returns "10" for 10 USDC
|
|
374
|
+
* @example fromSmallestUnit("1500000000", 9) // Returns "1.5" for 1.5 SOL
|
|
375
|
+
*/
|
|
376
|
+
declare function fromSmallestUnit(amount: string, decimals: number): string;
|
|
377
|
+
declare function createApiClient(options?: ApiClientOptions): {
|
|
378
|
+
quote: (payload: QuoteRequest) => Promise<QuoteResponse>;
|
|
379
|
+
buildTransaction: (payload: BuildTransactionRequest) => Promise<BuildTransactionResponse>;
|
|
380
|
+
getQuoteById: (quoteId: string) => Promise<QuoteResponse>;
|
|
381
|
+
health: () => Promise<HealthResponse>;
|
|
382
|
+
depositQuote: (payload: DepositQuoteRequest) => Promise<DepositQuoteResponse>;
|
|
383
|
+
depositStatus: (params: DepositStatusParams) => Promise<DepositStatusResponse>;
|
|
384
|
+
depositSubmit: (payload: DepositSubmitRequest) => Promise<DepositSubmitResponse>;
|
|
385
|
+
depositTokens: () => Promise<DepositTokensResponse>;
|
|
386
|
+
depositDestinations: (params: DepositDestinationsParams) => Promise<DepositDestinationsResponse>;
|
|
387
|
+
depositSources: (params: DepositSourcesParams) => Promise<DepositSourcesResponse>;
|
|
388
|
+
depositValidateAddress: (payload: ValidateAddressRequest) => Promise<ValidateAddressResponse>;
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
export { type AddressKind, ApiError, type ApiErrorDetail, type ApiErrorShape, type BuildTransactionRequest, type BuildTransactionResponse, type Chain, type Currency, type DepositDestination, type DepositDestinationChain, type DepositDestinationsParams, type DepositDestinationsResponse, type DepositFee, type DepositQuoteRequest, type DepositQuoteResponse, type DepositSource, type DepositSourceChain, type DepositSourcesParams, type DepositSourcesResponse, type DepositStatusParams, type DepositStatusResponse, type DepositSubmitRequest, type DepositSubmitResponse, type DepositToken, type DepositTokensResponse, type EvmTransactionPayload, type FeeBreakdown, type FeeDetails, type HealthResponse, type NearToken, type PartnerFee, type QuoteAlternativeRoute, type QuoteEdge, type QuoteRequest, type QuoteResponse, type QuoteRoute, type RelayChain, type RelayCurrency, type TransactionPayload, type TransactionSimulation, type TransactionSimulationStep, type TransactionStep, type TronTransactionPayload, type UnifiedToken, type ValidateAddressRequest, type ValidateAddressResponse, createApiClient, fromSmallestUnit, toSmallestUnit };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
type PartnerFee = {
|
|
2
|
+
recipient: string;
|
|
3
|
+
feeBPS: number;
|
|
4
|
+
};
|
|
5
|
+
type QuoteRequest = {
|
|
6
|
+
chainIdFrom: number;
|
|
7
|
+
chainIdTo?: number;
|
|
8
|
+
tokenIn: string;
|
|
9
|
+
tokenOut: string;
|
|
10
|
+
amountIn: string;
|
|
11
|
+
includeBridges?: string[];
|
|
12
|
+
partnerFees?: PartnerFee[];
|
|
13
|
+
};
|
|
14
|
+
type FeeBreakdown = {
|
|
15
|
+
type: 'protocol' | 'integrator' | 'gas' | 'bridge' | 'swap' | string;
|
|
16
|
+
amount: string;
|
|
17
|
+
token: string;
|
|
18
|
+
recipient?: string;
|
|
19
|
+
};
|
|
20
|
+
type FeeDetails = {
|
|
21
|
+
total: string;
|
|
22
|
+
breakdown: FeeBreakdown[];
|
|
23
|
+
};
|
|
24
|
+
type QuoteEdge = {
|
|
25
|
+
from: {
|
|
26
|
+
chainId: number;
|
|
27
|
+
tokenAddress: string;
|
|
28
|
+
};
|
|
29
|
+
to: {
|
|
30
|
+
chainId: number;
|
|
31
|
+
tokenAddress: string;
|
|
32
|
+
};
|
|
33
|
+
adaptor: string;
|
|
34
|
+
type: 'swap' | 'bridge';
|
|
35
|
+
amountIn: string;
|
|
36
|
+
estimatedAmountOut: string;
|
|
37
|
+
priceImpact: string;
|
|
38
|
+
fees: {
|
|
39
|
+
total: string;
|
|
40
|
+
breakdown: Array<{
|
|
41
|
+
type: string;
|
|
42
|
+
amount: string;
|
|
43
|
+
token?: string;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
46
|
+
gasEstimate: string;
|
|
47
|
+
metadata: Record<string, unknown>;
|
|
48
|
+
timestamp: number;
|
|
49
|
+
};
|
|
50
|
+
type QuoteRoute = {
|
|
51
|
+
quoteId: string;
|
|
52
|
+
path: QuoteEdge[];
|
|
53
|
+
sourceToken: {
|
|
54
|
+
chainId: number;
|
|
55
|
+
address: string;
|
|
56
|
+
symbol: string;
|
|
57
|
+
decimals: number;
|
|
58
|
+
};
|
|
59
|
+
destToken: {
|
|
60
|
+
chainId: number;
|
|
61
|
+
address: string;
|
|
62
|
+
symbol: string;
|
|
63
|
+
decimals: number;
|
|
64
|
+
};
|
|
65
|
+
amountIn: string;
|
|
66
|
+
amountOut: string;
|
|
67
|
+
fees: FeeDetails;
|
|
68
|
+
priceImpact: string;
|
|
69
|
+
estimatedGas: string;
|
|
70
|
+
expiresAt: number;
|
|
71
|
+
};
|
|
72
|
+
type QuoteAlternativeRoute = {
|
|
73
|
+
path: QuoteEdge[];
|
|
74
|
+
amountOut: string;
|
|
75
|
+
fees: FeeDetails;
|
|
76
|
+
};
|
|
77
|
+
type QuoteResponse = {
|
|
78
|
+
quoteId: string;
|
|
79
|
+
bestRoute: QuoteRoute;
|
|
80
|
+
alternativeRoutes: QuoteAlternativeRoute[];
|
|
81
|
+
};
|
|
82
|
+
type BuildTransactionRequest = {
|
|
83
|
+
quoteId: string;
|
|
84
|
+
userAddress: string;
|
|
85
|
+
recipient?: string;
|
|
86
|
+
partnerFees?: PartnerFee[];
|
|
87
|
+
simulate?: boolean;
|
|
88
|
+
};
|
|
89
|
+
type EvmTransactionPayload = {
|
|
90
|
+
from: string;
|
|
91
|
+
to: string;
|
|
92
|
+
data: string;
|
|
93
|
+
value: string;
|
|
94
|
+
chainId: number;
|
|
95
|
+
gasLimit?: string;
|
|
96
|
+
gasPrice?: string;
|
|
97
|
+
maxFeePerGas?: string;
|
|
98
|
+
maxPriorityFeePerGas?: string;
|
|
99
|
+
nonce?: number;
|
|
100
|
+
};
|
|
101
|
+
type TronTransactionPayload = {
|
|
102
|
+
from: string;
|
|
103
|
+
to: string;
|
|
104
|
+
input: string;
|
|
105
|
+
callValue: string;
|
|
106
|
+
chainId: number;
|
|
107
|
+
};
|
|
108
|
+
type TransactionPayload = EvmTransactionPayload | TronTransactionPayload;
|
|
109
|
+
type TransactionStep = {
|
|
110
|
+
step: number;
|
|
111
|
+
adaptor: string;
|
|
112
|
+
type: 'approval' | 'diamond';
|
|
113
|
+
chainId: number;
|
|
114
|
+
transaction: TransactionPayload;
|
|
115
|
+
description: string;
|
|
116
|
+
};
|
|
117
|
+
type TransactionSimulationStep = {
|
|
118
|
+
step: number;
|
|
119
|
+
type: string;
|
|
120
|
+
adaptor: string;
|
|
121
|
+
chainId: number;
|
|
122
|
+
estimated: boolean;
|
|
123
|
+
gas?: string;
|
|
124
|
+
error?: string;
|
|
125
|
+
};
|
|
126
|
+
type TransactionSimulation = {
|
|
127
|
+
allEstimated: boolean;
|
|
128
|
+
steps: TransactionSimulationStep[];
|
|
129
|
+
};
|
|
130
|
+
type BuildTransactionResponse = {
|
|
131
|
+
quoteId: string;
|
|
132
|
+
transactions: TransactionStep[];
|
|
133
|
+
totalSteps: number;
|
|
134
|
+
expiresAt: number;
|
|
135
|
+
simulation?: TransactionSimulation;
|
|
136
|
+
};
|
|
137
|
+
type DepositFee = {
|
|
138
|
+
recipient: string;
|
|
139
|
+
fee: number;
|
|
140
|
+
};
|
|
141
|
+
type DepositQuoteRequest = {
|
|
142
|
+
originChainId: number;
|
|
143
|
+
destinationChainId: number;
|
|
144
|
+
originAsset: string;
|
|
145
|
+
destinationAsset: string;
|
|
146
|
+
amount: string;
|
|
147
|
+
recipient: string;
|
|
148
|
+
refundTo?: string;
|
|
149
|
+
user?: string;
|
|
150
|
+
slippageBps?: number;
|
|
151
|
+
dry?: boolean;
|
|
152
|
+
partnerFees?: DepositFee[];
|
|
153
|
+
/**
|
|
154
|
+
* If provided, amount is treated as human-readable (e.g., "10" for 10 USDC)
|
|
155
|
+
* and will be converted to smallest unit using this decimals value.
|
|
156
|
+
* If not provided, amount is treated as smallest unit (backward compatible).
|
|
157
|
+
*/
|
|
158
|
+
decimals?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Request a static/reusable deposit address.
|
|
161
|
+
* When true, requests a deposit address that:
|
|
162
|
+
* - Can be reused for multiple deposits
|
|
163
|
+
* - Remains valid after quote rate expires (rate recalculated at deposit time)
|
|
164
|
+
* - Accepts different tokens (e.g., send USDC when quote was for SOL)
|
|
165
|
+
* Note: Only available for supported routes. Check supportsStaticAddress field.
|
|
166
|
+
*/
|
|
167
|
+
static?: boolean;
|
|
168
|
+
};
|
|
169
|
+
type DepositStatusParams = {
|
|
170
|
+
depositRequestId?: string;
|
|
171
|
+
depositAddress?: string;
|
|
172
|
+
requestId?: string;
|
|
173
|
+
};
|
|
174
|
+
type DepositSubmitRequest = {
|
|
175
|
+
depositRequestId?: string;
|
|
176
|
+
depositAddress?: string;
|
|
177
|
+
txHash: string;
|
|
178
|
+
};
|
|
179
|
+
type DepositQuoteResponse = {
|
|
180
|
+
success: boolean;
|
|
181
|
+
depositRequestId: string;
|
|
182
|
+
depositAddress: string;
|
|
183
|
+
isStaticAddress?: boolean;
|
|
184
|
+
upstreamRequestId?: string;
|
|
185
|
+
upstreamQuoteId?: string;
|
|
186
|
+
amountOut?: string;
|
|
187
|
+
minAmountOut?: string;
|
|
188
|
+
status?: string;
|
|
189
|
+
sentAppFees?: DepositFee[];
|
|
190
|
+
effectiveUpstreamAppFees?: DepositFee[];
|
|
191
|
+
expiresInSeconds?: number;
|
|
192
|
+
};
|
|
193
|
+
type DepositStatusResponse = {
|
|
194
|
+
success: boolean;
|
|
195
|
+
depositRequestId: string;
|
|
196
|
+
depositAddress?: string;
|
|
197
|
+
isStaticAddress?: boolean;
|
|
198
|
+
upstreamRequestId?: string;
|
|
199
|
+
status?: string;
|
|
200
|
+
executionStatus?: string;
|
|
201
|
+
sentAppFees?: DepositFee[];
|
|
202
|
+
effectiveUpstreamAppFees?: DepositFee[];
|
|
203
|
+
originTransactionHashes?: string[];
|
|
204
|
+
destinationTransactionHashes?: string[];
|
|
205
|
+
raw?: Record<string, unknown>;
|
|
206
|
+
};
|
|
207
|
+
type DepositSubmitResponse = {
|
|
208
|
+
success: boolean;
|
|
209
|
+
depositRequestId: string;
|
|
210
|
+
depositAddress: string;
|
|
211
|
+
result: Record<string, unknown>;
|
|
212
|
+
};
|
|
213
|
+
type Currency = {
|
|
214
|
+
address?: string;
|
|
215
|
+
id?: string;
|
|
216
|
+
symbol?: string;
|
|
217
|
+
name?: string;
|
|
218
|
+
decimals?: number;
|
|
219
|
+
};
|
|
220
|
+
type Chain = {
|
|
221
|
+
chainId?: number;
|
|
222
|
+
name?: string;
|
|
223
|
+
solverCurrencies: Currency[];
|
|
224
|
+
supportsStaticAddress?: boolean;
|
|
225
|
+
};
|
|
226
|
+
type DepositToken = {
|
|
227
|
+
address: string;
|
|
228
|
+
symbol: string;
|
|
229
|
+
blockchain: string;
|
|
230
|
+
chainId?: number;
|
|
231
|
+
decimals?: number;
|
|
232
|
+
supportsStaticAddress: boolean;
|
|
233
|
+
};
|
|
234
|
+
type DepositTokensResponse = {
|
|
235
|
+
success: boolean;
|
|
236
|
+
chains: Chain[];
|
|
237
|
+
tokens: DepositToken[];
|
|
238
|
+
countChains: number;
|
|
239
|
+
countTokens: number;
|
|
240
|
+
};
|
|
241
|
+
/** @deprecated Use Currency instead */
|
|
242
|
+
type RelayCurrency = Currency;
|
|
243
|
+
/** @deprecated Use Chain instead */
|
|
244
|
+
type RelayChain = Chain;
|
|
245
|
+
/** @deprecated Use DepositToken instead */
|
|
246
|
+
type NearToken = {
|
|
247
|
+
assetId: string;
|
|
248
|
+
decimals: number;
|
|
249
|
+
blockchain: string;
|
|
250
|
+
symbol: string;
|
|
251
|
+
price?: number;
|
|
252
|
+
priceUpdatedAt?: string;
|
|
253
|
+
contractAddress?: string | null;
|
|
254
|
+
};
|
|
255
|
+
/** @deprecated Use DepositToken instead */
|
|
256
|
+
type UnifiedToken = DepositToken;
|
|
257
|
+
type AddressKind = 'evm' | 'near' | 'solana' | 'tron' | 'bitcoin' | 'litecoin' | 'stellar' | 'sui' | 'ton' | 'xrp';
|
|
258
|
+
type DepositDestination = {
|
|
259
|
+
currency: string;
|
|
260
|
+
symbol?: string;
|
|
261
|
+
blockchain?: string;
|
|
262
|
+
destinationChainId?: number;
|
|
263
|
+
decimals?: number;
|
|
264
|
+
addressKind: AddressKind | null;
|
|
265
|
+
supportsStaticAddress: boolean;
|
|
266
|
+
};
|
|
267
|
+
type DepositDestinationChain = {
|
|
268
|
+
blockchain: string;
|
|
269
|
+
chainId?: number;
|
|
270
|
+
addressKind: AddressKind | null;
|
|
271
|
+
count: number;
|
|
272
|
+
supportsStaticAddress: boolean;
|
|
273
|
+
};
|
|
274
|
+
type DepositDestinationsResponse = {
|
|
275
|
+
success: boolean;
|
|
276
|
+
originAssetId?: string;
|
|
277
|
+
originAddress?: string;
|
|
278
|
+
originAddressKind: AddressKind | null;
|
|
279
|
+
destinations: DepositDestination[];
|
|
280
|
+
destinationChains: DepositDestinationChain[];
|
|
281
|
+
count: number;
|
|
282
|
+
};
|
|
283
|
+
type DepositSource = {
|
|
284
|
+
currency: string;
|
|
285
|
+
symbol?: string;
|
|
286
|
+
blockchain?: string;
|
|
287
|
+
sourceChainId?: number;
|
|
288
|
+
decimals?: number;
|
|
289
|
+
addressKind: AddressKind | null;
|
|
290
|
+
supportsStaticAddress: boolean;
|
|
291
|
+
};
|
|
292
|
+
type DepositSourceChain = {
|
|
293
|
+
blockchain: string;
|
|
294
|
+
chainId?: number;
|
|
295
|
+
addressKind: AddressKind | null;
|
|
296
|
+
count: number;
|
|
297
|
+
supportsStaticAddress: boolean;
|
|
298
|
+
};
|
|
299
|
+
type DepositSourcesResponse = {
|
|
300
|
+
success: boolean;
|
|
301
|
+
destinationAssetId?: string;
|
|
302
|
+
destinationAddress?: string;
|
|
303
|
+
destinationAddressKind: AddressKind | null;
|
|
304
|
+
sources: DepositSource[];
|
|
305
|
+
sourceChains: DepositSourceChain[];
|
|
306
|
+
count: number;
|
|
307
|
+
};
|
|
308
|
+
type DepositDestinationsParams = {
|
|
309
|
+
originAssetId?: string;
|
|
310
|
+
originAddress?: string;
|
|
311
|
+
originChainId?: number;
|
|
312
|
+
};
|
|
313
|
+
type DepositSourcesParams = {
|
|
314
|
+
destinationAssetId?: string;
|
|
315
|
+
destinationAddress?: string;
|
|
316
|
+
destinationChainId?: number;
|
|
317
|
+
};
|
|
318
|
+
type ValidateAddressRequest = {
|
|
319
|
+
chainType: AddressKind;
|
|
320
|
+
address: string;
|
|
321
|
+
};
|
|
322
|
+
type ValidateAddressResponse = {
|
|
323
|
+
success: boolean;
|
|
324
|
+
valid: boolean;
|
|
325
|
+
reason?: string;
|
|
326
|
+
};
|
|
327
|
+
type HealthResponse = {
|
|
328
|
+
status: 'healthy' | 'degraded';
|
|
329
|
+
service: string;
|
|
330
|
+
version: string;
|
|
331
|
+
timestamp: number;
|
|
332
|
+
dependencies: Record<string, 'up' | 'down'>;
|
|
333
|
+
};
|
|
334
|
+
type ApiErrorDetail = {
|
|
335
|
+
field: string;
|
|
336
|
+
message: string;
|
|
337
|
+
};
|
|
338
|
+
type ApiErrorShape = {
|
|
339
|
+
error?: string;
|
|
340
|
+
message?: string;
|
|
341
|
+
errorCode?: string;
|
|
342
|
+
quoteId?: string;
|
|
343
|
+
expiresAt?: number;
|
|
344
|
+
expiredAt?: string;
|
|
345
|
+
details?: ApiErrorDetail[];
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
type ApiClientOptions = {
|
|
349
|
+
baseUrl?: string;
|
|
350
|
+
apiKey?: string;
|
|
351
|
+
fetch?: typeof fetch;
|
|
352
|
+
timeoutMs?: number;
|
|
353
|
+
};
|
|
354
|
+
declare class ApiError extends Error {
|
|
355
|
+
status: number;
|
|
356
|
+
body?: ApiErrorShape | string;
|
|
357
|
+
constructor(status: number, message: string, body?: ApiErrorShape | string);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Convert human-readable amount to smallest unit
|
|
361
|
+
* @param amount Human-readable amount (e.g., "10" for 10 USDC)
|
|
362
|
+
* @param decimals Token decimals (e.g., 6 for USDC, 9 for SOL)
|
|
363
|
+
* @returns Amount in smallest unit as string
|
|
364
|
+
* @example toSmallestUnit("10", 6) // Returns "10000000" for 10 USDC
|
|
365
|
+
* @example toSmallestUnit("1.5", 9) // Returns "1500000000" for 1.5 SOL
|
|
366
|
+
*/
|
|
367
|
+
declare function toSmallestUnit(amount: string, decimals: number): string;
|
|
368
|
+
/**
|
|
369
|
+
* Convert smallest unit amount to human-readable format
|
|
370
|
+
* @param amount Amount in smallest unit (e.g., "10000000" for USDC)
|
|
371
|
+
* @param decimals Token decimals (e.g., 6 for USDC, 9 for SOL)
|
|
372
|
+
* @returns Human-readable amount as string
|
|
373
|
+
* @example fromSmallestUnit("10000000", 6) // Returns "10" for 10 USDC
|
|
374
|
+
* @example fromSmallestUnit("1500000000", 9) // Returns "1.5" for 1.5 SOL
|
|
375
|
+
*/
|
|
376
|
+
declare function fromSmallestUnit(amount: string, decimals: number): string;
|
|
377
|
+
declare function createApiClient(options?: ApiClientOptions): {
|
|
378
|
+
quote: (payload: QuoteRequest) => Promise<QuoteResponse>;
|
|
379
|
+
buildTransaction: (payload: BuildTransactionRequest) => Promise<BuildTransactionResponse>;
|
|
380
|
+
getQuoteById: (quoteId: string) => Promise<QuoteResponse>;
|
|
381
|
+
health: () => Promise<HealthResponse>;
|
|
382
|
+
depositQuote: (payload: DepositQuoteRequest) => Promise<DepositQuoteResponse>;
|
|
383
|
+
depositStatus: (params: DepositStatusParams) => Promise<DepositStatusResponse>;
|
|
384
|
+
depositSubmit: (payload: DepositSubmitRequest) => Promise<DepositSubmitResponse>;
|
|
385
|
+
depositTokens: () => Promise<DepositTokensResponse>;
|
|
386
|
+
depositDestinations: (params: DepositDestinationsParams) => Promise<DepositDestinationsResponse>;
|
|
387
|
+
depositSources: (params: DepositSourcesParams) => Promise<DepositSourcesResponse>;
|
|
388
|
+
depositValidateAddress: (payload: ValidateAddressRequest) => Promise<ValidateAddressResponse>;
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
export { type AddressKind, ApiError, type ApiErrorDetail, type ApiErrorShape, type BuildTransactionRequest, type BuildTransactionResponse, type Chain, type Currency, type DepositDestination, type DepositDestinationChain, type DepositDestinationsParams, type DepositDestinationsResponse, type DepositFee, type DepositQuoteRequest, type DepositQuoteResponse, type DepositSource, type DepositSourceChain, type DepositSourcesParams, type DepositSourcesResponse, type DepositStatusParams, type DepositStatusResponse, type DepositSubmitRequest, type DepositSubmitResponse, type DepositToken, type DepositTokensResponse, type EvmTransactionPayload, type FeeBreakdown, type FeeDetails, type HealthResponse, type NearToken, type PartnerFee, type QuoteAlternativeRoute, type QuoteEdge, type QuoteRequest, type QuoteResponse, type QuoteRoute, type RelayChain, type RelayCurrency, type TransactionPayload, type TransactionSimulation, type TransactionSimulationStep, type TransactionStep, type TronTransactionPayload, type UnifiedToken, type ValidateAddressRequest, type ValidateAddressResponse, createApiClient, fromSmallestUnit, toSmallestUnit };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ApiError: () => ApiError,
|
|
24
|
+
createApiClient: () => createApiClient,
|
|
25
|
+
fromSmallestUnit: () => fromSmallestUnit,
|
|
26
|
+
toSmallestUnit: () => toSmallestUnit
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/client.ts
|
|
31
|
+
var ApiError = class extends Error {
|
|
32
|
+
status;
|
|
33
|
+
body;
|
|
34
|
+
constructor(status, message, body) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = "ApiError";
|
|
37
|
+
this.status = status;
|
|
38
|
+
this.body = body;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function buildHeaders(apiKey) {
|
|
42
|
+
const headers = { "content-type": "application/json" };
|
|
43
|
+
if (apiKey) headers["x-api-key"] = apiKey;
|
|
44
|
+
return headers;
|
|
45
|
+
}
|
|
46
|
+
function toSmallestUnit(amount, decimals) {
|
|
47
|
+
const num = parseFloat(amount);
|
|
48
|
+
if (isNaN(num)) {
|
|
49
|
+
throw new Error(`Invalid amount: ${amount}`);
|
|
50
|
+
}
|
|
51
|
+
const multiplier = Math.pow(10, decimals);
|
|
52
|
+
const smallestUnit = Math.floor(num * multiplier);
|
|
53
|
+
return smallestUnit.toString();
|
|
54
|
+
}
|
|
55
|
+
function fromSmallestUnit(amount, decimals) {
|
|
56
|
+
const num = parseFloat(amount);
|
|
57
|
+
if (isNaN(num)) {
|
|
58
|
+
throw new Error(`Invalid amount: ${amount}`);
|
|
59
|
+
}
|
|
60
|
+
const divisor = Math.pow(10, decimals);
|
|
61
|
+
return (num / divisor).toString();
|
|
62
|
+
}
|
|
63
|
+
async function requestJson(fetcher, url, options, timeoutMs) {
|
|
64
|
+
const controller = new AbortController();
|
|
65
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
66
|
+
try {
|
|
67
|
+
const res = await fetcher(url, { ...options, signal: controller.signal });
|
|
68
|
+
const text = await res.text();
|
|
69
|
+
const body = text ? JSON.parse(text) : void 0;
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
throw new ApiError(res.status, body?.message || res.statusText, body || text);
|
|
72
|
+
}
|
|
73
|
+
return body;
|
|
74
|
+
} finally {
|
|
75
|
+
clearTimeout(timeout);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function createApiClient(options = {}) {
|
|
79
|
+
const rawBaseUrl = options.baseUrl || "https://swap-api.dextopus.com";
|
|
80
|
+
const trimmedBaseUrl = rawBaseUrl.replace(/\/+$/, "");
|
|
81
|
+
const baseUrl = trimmedBaseUrl.endsWith("/api") ? trimmedBaseUrl.slice(0, -4) : trimmedBaseUrl;
|
|
82
|
+
const apiKey = options.apiKey;
|
|
83
|
+
const fetcher = options.fetch || fetch;
|
|
84
|
+
const timeoutMs = options.timeoutMs ?? 1e4;
|
|
85
|
+
const headers = buildHeaders(apiKey);
|
|
86
|
+
return {
|
|
87
|
+
quote: (payload) => requestJson(
|
|
88
|
+
fetcher,
|
|
89
|
+
`${baseUrl}/api/quote`,
|
|
90
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
91
|
+
timeoutMs
|
|
92
|
+
),
|
|
93
|
+
buildTransaction: (payload) => requestJson(
|
|
94
|
+
fetcher,
|
|
95
|
+
`${baseUrl}/api/build-transaction`,
|
|
96
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
97
|
+
timeoutMs
|
|
98
|
+
),
|
|
99
|
+
getQuoteById: (quoteId) => requestJson(
|
|
100
|
+
fetcher,
|
|
101
|
+
`${baseUrl}/api/quote/${quoteId}`,
|
|
102
|
+
{ method: "GET", headers },
|
|
103
|
+
timeoutMs
|
|
104
|
+
),
|
|
105
|
+
health: () => requestJson(
|
|
106
|
+
fetcher,
|
|
107
|
+
`${baseUrl}/health`,
|
|
108
|
+
{ method: "GET", headers },
|
|
109
|
+
timeoutMs
|
|
110
|
+
),
|
|
111
|
+
depositQuote: (payload) => {
|
|
112
|
+
const apiPayload = { ...payload };
|
|
113
|
+
if (payload.decimals !== void 0) {
|
|
114
|
+
apiPayload.amount = toSmallestUnit(payload.amount, payload.decimals);
|
|
115
|
+
delete apiPayload.decimals;
|
|
116
|
+
}
|
|
117
|
+
return requestJson(
|
|
118
|
+
fetcher,
|
|
119
|
+
`${baseUrl}/api/deposit/quote`,
|
|
120
|
+
{ method: "POST", headers, body: JSON.stringify(apiPayload) },
|
|
121
|
+
timeoutMs
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
depositStatus: (params) => {
|
|
125
|
+
const query = new URLSearchParams(
|
|
126
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
|
|
127
|
+
).toString();
|
|
128
|
+
return requestJson(
|
|
129
|
+
fetcher,
|
|
130
|
+
`${baseUrl}/api/deposit/status?${query}`,
|
|
131
|
+
{ method: "GET", headers },
|
|
132
|
+
timeoutMs
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
depositSubmit: (payload) => requestJson(
|
|
136
|
+
fetcher,
|
|
137
|
+
`${baseUrl}/api/deposit/submit`,
|
|
138
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
139
|
+
timeoutMs
|
|
140
|
+
),
|
|
141
|
+
depositTokens: () => requestJson(
|
|
142
|
+
fetcher,
|
|
143
|
+
`${baseUrl}/api/deposit/tokens`,
|
|
144
|
+
{ method: "GET", headers },
|
|
145
|
+
timeoutMs
|
|
146
|
+
),
|
|
147
|
+
depositDestinations: (params) => {
|
|
148
|
+
const query = new URLSearchParams(
|
|
149
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
|
|
150
|
+
).toString();
|
|
151
|
+
return requestJson(
|
|
152
|
+
fetcher,
|
|
153
|
+
`${baseUrl}/api/deposit/destinations?${query}`,
|
|
154
|
+
{ method: "GET", headers },
|
|
155
|
+
timeoutMs
|
|
156
|
+
);
|
|
157
|
+
},
|
|
158
|
+
depositSources: (params) => {
|
|
159
|
+
const query = new URLSearchParams(
|
|
160
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
|
|
161
|
+
).toString();
|
|
162
|
+
return requestJson(
|
|
163
|
+
fetcher,
|
|
164
|
+
`${baseUrl}/api/deposit/sources?${query}`,
|
|
165
|
+
{ method: "GET", headers },
|
|
166
|
+
timeoutMs
|
|
167
|
+
);
|
|
168
|
+
},
|
|
169
|
+
depositValidateAddress: (payload) => requestJson(
|
|
170
|
+
fetcher,
|
|
171
|
+
`${baseUrl}/api/deposit/validate-address`,
|
|
172
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
173
|
+
timeoutMs
|
|
174
|
+
)
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
178
|
+
0 && (module.exports = {
|
|
179
|
+
ApiError,
|
|
180
|
+
createApiClient,
|
|
181
|
+
fromSmallestUnit,
|
|
182
|
+
toSmallestUnit
|
|
183
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var ApiError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
body;
|
|
5
|
+
constructor(status, message, body) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "ApiError";
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.body = body;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function buildHeaders(apiKey) {
|
|
13
|
+
const headers = { "content-type": "application/json" };
|
|
14
|
+
if (apiKey) headers["x-api-key"] = apiKey;
|
|
15
|
+
return headers;
|
|
16
|
+
}
|
|
17
|
+
function toSmallestUnit(amount, decimals) {
|
|
18
|
+
const num = parseFloat(amount);
|
|
19
|
+
if (isNaN(num)) {
|
|
20
|
+
throw new Error(`Invalid amount: ${amount}`);
|
|
21
|
+
}
|
|
22
|
+
const multiplier = Math.pow(10, decimals);
|
|
23
|
+
const smallestUnit = Math.floor(num * multiplier);
|
|
24
|
+
return smallestUnit.toString();
|
|
25
|
+
}
|
|
26
|
+
function fromSmallestUnit(amount, decimals) {
|
|
27
|
+
const num = parseFloat(amount);
|
|
28
|
+
if (isNaN(num)) {
|
|
29
|
+
throw new Error(`Invalid amount: ${amount}`);
|
|
30
|
+
}
|
|
31
|
+
const divisor = Math.pow(10, decimals);
|
|
32
|
+
return (num / divisor).toString();
|
|
33
|
+
}
|
|
34
|
+
async function requestJson(fetcher, url, options, timeoutMs) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
37
|
+
try {
|
|
38
|
+
const res = await fetcher(url, { ...options, signal: controller.signal });
|
|
39
|
+
const text = await res.text();
|
|
40
|
+
const body = text ? JSON.parse(text) : void 0;
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
throw new ApiError(res.status, body?.message || res.statusText, body || text);
|
|
43
|
+
}
|
|
44
|
+
return body;
|
|
45
|
+
} finally {
|
|
46
|
+
clearTimeout(timeout);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function createApiClient(options = {}) {
|
|
50
|
+
const rawBaseUrl = options.baseUrl || "https://swap-api.dextopus.com";
|
|
51
|
+
const trimmedBaseUrl = rawBaseUrl.replace(/\/+$/, "");
|
|
52
|
+
const baseUrl = trimmedBaseUrl.endsWith("/api") ? trimmedBaseUrl.slice(0, -4) : trimmedBaseUrl;
|
|
53
|
+
const apiKey = options.apiKey;
|
|
54
|
+
const fetcher = options.fetch || fetch;
|
|
55
|
+
const timeoutMs = options.timeoutMs ?? 1e4;
|
|
56
|
+
const headers = buildHeaders(apiKey);
|
|
57
|
+
return {
|
|
58
|
+
quote: (payload) => requestJson(
|
|
59
|
+
fetcher,
|
|
60
|
+
`${baseUrl}/api/quote`,
|
|
61
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
62
|
+
timeoutMs
|
|
63
|
+
),
|
|
64
|
+
buildTransaction: (payload) => requestJson(
|
|
65
|
+
fetcher,
|
|
66
|
+
`${baseUrl}/api/build-transaction`,
|
|
67
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
68
|
+
timeoutMs
|
|
69
|
+
),
|
|
70
|
+
getQuoteById: (quoteId) => requestJson(
|
|
71
|
+
fetcher,
|
|
72
|
+
`${baseUrl}/api/quote/${quoteId}`,
|
|
73
|
+
{ method: "GET", headers },
|
|
74
|
+
timeoutMs
|
|
75
|
+
),
|
|
76
|
+
health: () => requestJson(
|
|
77
|
+
fetcher,
|
|
78
|
+
`${baseUrl}/health`,
|
|
79
|
+
{ method: "GET", headers },
|
|
80
|
+
timeoutMs
|
|
81
|
+
),
|
|
82
|
+
depositQuote: (payload) => {
|
|
83
|
+
const apiPayload = { ...payload };
|
|
84
|
+
if (payload.decimals !== void 0) {
|
|
85
|
+
apiPayload.amount = toSmallestUnit(payload.amount, payload.decimals);
|
|
86
|
+
delete apiPayload.decimals;
|
|
87
|
+
}
|
|
88
|
+
return requestJson(
|
|
89
|
+
fetcher,
|
|
90
|
+
`${baseUrl}/api/deposit/quote`,
|
|
91
|
+
{ method: "POST", headers, body: JSON.stringify(apiPayload) },
|
|
92
|
+
timeoutMs
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
depositStatus: (params) => {
|
|
96
|
+
const query = new URLSearchParams(
|
|
97
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
|
|
98
|
+
).toString();
|
|
99
|
+
return requestJson(
|
|
100
|
+
fetcher,
|
|
101
|
+
`${baseUrl}/api/deposit/status?${query}`,
|
|
102
|
+
{ method: "GET", headers },
|
|
103
|
+
timeoutMs
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
depositSubmit: (payload) => requestJson(
|
|
107
|
+
fetcher,
|
|
108
|
+
`${baseUrl}/api/deposit/submit`,
|
|
109
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
110
|
+
timeoutMs
|
|
111
|
+
),
|
|
112
|
+
depositTokens: () => requestJson(
|
|
113
|
+
fetcher,
|
|
114
|
+
`${baseUrl}/api/deposit/tokens`,
|
|
115
|
+
{ method: "GET", headers },
|
|
116
|
+
timeoutMs
|
|
117
|
+
),
|
|
118
|
+
depositDestinations: (params) => {
|
|
119
|
+
const query = new URLSearchParams(
|
|
120
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
|
|
121
|
+
).toString();
|
|
122
|
+
return requestJson(
|
|
123
|
+
fetcher,
|
|
124
|
+
`${baseUrl}/api/deposit/destinations?${query}`,
|
|
125
|
+
{ method: "GET", headers },
|
|
126
|
+
timeoutMs
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
depositSources: (params) => {
|
|
130
|
+
const query = new URLSearchParams(
|
|
131
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [key, String(value)])
|
|
132
|
+
).toString();
|
|
133
|
+
return requestJson(
|
|
134
|
+
fetcher,
|
|
135
|
+
`${baseUrl}/api/deposit/sources?${query}`,
|
|
136
|
+
{ method: "GET", headers },
|
|
137
|
+
timeoutMs
|
|
138
|
+
);
|
|
139
|
+
},
|
|
140
|
+
depositValidateAddress: (payload) => requestJson(
|
|
141
|
+
fetcher,
|
|
142
|
+
`${baseUrl}/api/deposit/validate-address`,
|
|
143
|
+
{ method: "POST", headers, body: JSON.stringify(payload) },
|
|
144
|
+
timeoutMs
|
|
145
|
+
)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export {
|
|
149
|
+
ApiError,
|
|
150
|
+
createApiClient,
|
|
151
|
+
fromSmallestUnit,
|
|
152
|
+
toSmallestUnit
|
|
153
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dextopus/api-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dextopus API SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"development": "./src/index.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"lint": "echo 'lint skipped'"
|
|
21
|
+
}
|
|
22
|
+
}
|