@coinlist-co/react 0.10.1 → 0.11.1-rc.10770e8

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.
Files changed (38) hide show
  1. package/README.md +32 -0
  2. package/dist/chunk-7CTH4KPU.js +2399 -0
  3. package/dist/chunk-7CTH4KPU.js.map +1 -0
  4. package/dist/{chunk-AQVCOWOV.js → chunk-LSPZETDH.js} +249 -317
  5. package/dist/chunk-LSPZETDH.js.map +1 -0
  6. package/dist/chunk-UZUQALFY.js +279 -0
  7. package/dist/chunk-UZUQALFY.js.map +1 -0
  8. package/dist/client/index.cjs +13430 -3308
  9. package/dist/client/index.cjs.map +1 -1
  10. package/dist/client/index.d.cts +5486 -899
  11. package/dist/client/index.d.ts +5486 -899
  12. package/dist/client/index.js +11025 -2388
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/collections-BBI_XydI.d.cts +116 -0
  15. package/dist/collections-BrX9rRWc.d.ts +116 -0
  16. package/dist/config-CMl1bR3F.d.cts +2959 -0
  17. package/dist/config-CMl1bR3F.d.ts +2959 -0
  18. package/dist/server/index.cjs +1768 -511
  19. package/dist/server/index.cjs.map +1 -1
  20. package/dist/server/index.d.cts +266 -162
  21. package/dist/server/index.d.ts +266 -162
  22. package/dist/server/index.js +235 -169
  23. package/dist/server/index.js.map +1 -1
  24. package/dist/shared/index.cjs +2423 -926
  25. package/dist/shared/index.cjs.map +1 -1
  26. package/dist/shared/index.d.cts +325 -132
  27. package/dist/shared/index.d.ts +325 -132
  28. package/dist/shared/index.js +112 -28
  29. package/package.json +12 -8
  30. package/dist/chunk-AQVCOWOV.js.map +0 -1
  31. package/dist/chunk-TBU3EBNM.js +0 -442
  32. package/dist/chunk-TBU3EBNM.js.map +0 -1
  33. package/dist/chunk-UOHD7US2.js +0 -855
  34. package/dist/chunk-UOHD7US2.js.map +0 -1
  35. package/dist/collections-Bv1Oxzu_.d.ts +0 -28
  36. package/dist/collections-DDyxbOPZ.d.cts +0 -28
  37. package/dist/requirement-oVZA1INj.d.cts +0 -1040
  38. package/dist/requirement-oVZA1INj.d.ts +0 -1040
@@ -0,0 +1,2399 @@
1
+ // src/shared/api/http-attributes.ts
2
+ var empty = {};
3
+ var concat = (left, right) => ({
4
+ ...left,
5
+ ...right
6
+ });
7
+ var concatAll = (...items) => {
8
+ let result = empty;
9
+ for (const item of items) {
10
+ result = concat(result, item);
11
+ }
12
+ return result;
13
+ };
14
+ var protectedRequest = () => ({ protected: true });
15
+ var userAgent = () => ({ userAgent: true });
16
+ var idempotencyKey = () => ({
17
+ idempotencyKey: true
18
+ });
19
+ var clientCredentials = (credentials) => ({
20
+ clientCredentials: credentials
21
+ });
22
+ var retryAttempt = (attempt) => ({
23
+ retryAttempt: attempt
24
+ });
25
+ var renewAttempted = (value) => ({
26
+ renewAttempted: value
27
+ });
28
+ var requestId = (id) => ({ requestId: id });
29
+ var getRequestId = (attrs) => attrs?.requestId ?? null;
30
+ var isProtected = (attrs) => attrs?.protected === true;
31
+ var needUserAgent = (attrs) => attrs?.userAgent === true;
32
+ var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
33
+ var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
34
+ var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
35
+ var getClientCredentials = (attrs) => attrs?.clientCredentials;
36
+ var Attributes = {
37
+ empty,
38
+ concat,
39
+ concatAll,
40
+ protected: protectedRequest,
41
+ isProtected,
42
+ userAgent,
43
+ needUserAgent,
44
+ idempotencyKey,
45
+ isIdempotent,
46
+ retryAttempt,
47
+ getRetryAttempt,
48
+ renewAttempted,
49
+ wasRenewAttempted,
50
+ clientCredentials,
51
+ getClientCredentials,
52
+ requestId,
53
+ getRequestId
54
+ };
55
+
56
+ // src/shared/api/http.ts
57
+ var HttpError = class extends Error {
58
+ constructor(response) {
59
+ super(`Request failed with ${response.status} status`);
60
+ this.name = "HttpError";
61
+ this.response = response;
62
+ }
63
+ /**
64
+ * Correlates this failure with the `[HTTP]` log lines for the same request,
65
+ * which carry the method, the URL, the duration and every retry. `null` when
66
+ * the response did not come from an {@link HttpClient}.
67
+ *
68
+ * Worth quoting in a bug report: it is what makes a log excerpt readable.
69
+ */
70
+ get requestId() {
71
+ return this.response.requestId ?? null;
72
+ }
73
+ };
74
+ function apiErrorCode(error) {
75
+ if (!(error instanceof HttpError)) return null;
76
+ const body = error.response.body;
77
+ if (typeof body !== "object" || body === null) return null;
78
+ const code = body.code;
79
+ return typeof code === "string" ? code : null;
80
+ }
81
+ async function makeRequest(request) {
82
+ const headers = {
83
+ Accept: "application/json",
84
+ ...request.method === "POST" && request.body !== void 0 ? { "Content-Type": "application/json" } : {},
85
+ ...request.headers ?? {}
86
+ };
87
+ const init = {
88
+ method: request.method,
89
+ headers,
90
+ ...request.redirect !== void 0 ? { redirect: request.redirect } : {}
91
+ };
92
+ if (request.method === "POST" && request.body !== void 0) {
93
+ init.body = JSON.stringify(request.body);
94
+ }
95
+ const response = await fetch(
96
+ buildUrlWithQueryParams(request.url, request.queryParams),
97
+ init
98
+ );
99
+ const responseHeaders = headersToRecord(response.headers);
100
+ if (response.status === 204 || response.status === 205) {
101
+ return {
102
+ status: response.status,
103
+ body: null,
104
+ headers: responseHeaders
105
+ };
106
+ }
107
+ if (response.status >= 300 && response.status < 400) {
108
+ await response.text();
109
+ return {
110
+ status: response.status,
111
+ body: null,
112
+ headers: responseHeaders
113
+ };
114
+ }
115
+ const text = await response.text();
116
+ let body;
117
+ try {
118
+ body = text ? JSON.parse(text) : null;
119
+ } catch (_) {
120
+ throw new HttpError({
121
+ status: response.status,
122
+ headers: responseHeaders,
123
+ body: text
124
+ });
125
+ }
126
+ return {
127
+ status: response.status,
128
+ body,
129
+ headers: responseHeaders
130
+ };
131
+ }
132
+ function buildUrlWithQueryParams(url, queryParams) {
133
+ if (!queryParams) {
134
+ return url;
135
+ }
136
+ const searchParams = new URLSearchParams();
137
+ for (const [key, value] of Object.entries(queryParams)) {
138
+ if (value === void 0 || value === null) {
139
+ continue;
140
+ }
141
+ if (Array.isArray(value)) {
142
+ for (const item of value) {
143
+ if (item === void 0 || item === null) {
144
+ continue;
145
+ }
146
+ searchParams.append(key, String(item));
147
+ }
148
+ continue;
149
+ }
150
+ searchParams.append(key, String(value));
151
+ }
152
+ const queryString = searchParams.toString();
153
+ if (!queryString) {
154
+ return url;
155
+ }
156
+ return url.includes("?") ? `${url}&${queryString}` : `${url}?${queryString}`;
157
+ }
158
+ function headersToRecord(headers) {
159
+ const record = {};
160
+ headers.forEach((value, key) => {
161
+ record[key.toLowerCase()] = value;
162
+ });
163
+ return record;
164
+ }
165
+ function concatAttributes(request, attrs) {
166
+ const nextAttributes = Attributes.concat(
167
+ request.attributes ?? Attributes.empty,
168
+ attrs
169
+ );
170
+ const nextRequest = {
171
+ ...request,
172
+ attributes: nextAttributes
173
+ };
174
+ return nextRequest;
175
+ }
176
+ var Request = {
177
+ concatAttributes
178
+ };
179
+
180
+ // src/shared/types/errors.ts
181
+ var NotImplementedError = class extends Error {
182
+ constructor(message = "Not implemented yet") {
183
+ super(message);
184
+ this.name = "NotImplementedError";
185
+ }
186
+ };
187
+ var NotAuthenticatedError = class extends Error {
188
+ constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
189
+ super(message);
190
+ this.name = "NotAuthenticatedError";
191
+ }
192
+ };
193
+ var ValidationError = class extends Error {
194
+ constructor(message) {
195
+ super(message);
196
+ this.name = "ValidationError";
197
+ }
198
+ };
199
+ var InvariantError = class extends Error {
200
+ constructor(message) {
201
+ super(message);
202
+ this.name = "InvariantError";
203
+ }
204
+ };
205
+ var MathError = class extends Error {
206
+ constructor(message) {
207
+ super(message);
208
+ this.name = "MathError";
209
+ }
210
+ };
211
+
212
+ // src/shared/api/pagination.ts
213
+ async function fetchAllPages(fetchPage, baseParams) {
214
+ const items = [];
215
+ let cursor = null;
216
+ do {
217
+ const params = {
218
+ ...baseParams ?? {},
219
+ after: cursor ?? void 0
220
+ };
221
+ const page = await fetchPage(params);
222
+ items.push(...page.data);
223
+ cursor = page.startingAfter;
224
+ } while (cursor);
225
+ return items;
226
+ }
227
+
228
+ // src/shared/types/blockchain/core.ts
229
+ var ETHEREUM_CHAINS = {
230
+ ethereum_mainnet: true,
231
+ ethereum_sepolia: true,
232
+ base_mainnet: true,
233
+ base_sepolia: true
234
+ };
235
+ var EthereumChain = (value) => {
236
+ if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {
237
+ throw new ValidationError(`Unsupported Ethereum chain: "${value}"`);
238
+ }
239
+ return value;
240
+ };
241
+ var SOLANA_CHAINS = {
242
+ solana_mainnet: true,
243
+ solana_devnet: true
244
+ };
245
+ var SolanaChain = (value) => {
246
+ if (!Object.keys(SOLANA_CHAINS).includes(value)) {
247
+ throw new ValidationError(`Unsupported Solana chain: "${value}"`);
248
+ }
249
+ return value;
250
+ };
251
+ var Chain = (value) => {
252
+ if (!Object.keys(ETHEREUM_CHAINS).includes(value) && !Object.keys(SOLANA_CHAINS).includes(value)) {
253
+ throw new ValidationError(`Unsupported chain: "${value}"`);
254
+ }
255
+ return value;
256
+ };
257
+ var EvmWalletAddress = (value) => value;
258
+ var EvmContractAddress = (value) => value;
259
+ var HexEncodedTransactionData = (value) => value;
260
+ var MAX_ASSET_DECIMALS = 77;
261
+ var AssetDecimals = (value) => {
262
+ if (!Number.isInteger(value)) {
263
+ throw new ValidationError(`Asset decimals must be an integer: ${value}`);
264
+ }
265
+ if (value < 0 || value > MAX_ASSET_DECIMALS) {
266
+ throw new ValidationError(
267
+ `Asset decimals out of range [0, ${MAX_ASSET_DECIMALS}]: ${value}`
268
+ );
269
+ }
270
+ return value;
271
+ };
272
+ var STABLE_DECIMALS = AssetDecimals(6);
273
+ var DecimalString = (value) => value;
274
+ var MAX_UINT_256 = 2n ** 256n - 1n;
275
+ var assertUint256 = (value) => {
276
+ if (isUint256(value)) return value;
277
+ throw new InvariantError(`Value out of uint256 bounds: ${value}`);
278
+ };
279
+ var parseUint256 = (value, label) => {
280
+ if (isUint256(value)) return value;
281
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
282
+ };
283
+ var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
284
+ var BlockchainAmount = Object.assign(
285
+ (value) => value,
286
+ {
287
+ add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
288
+ sub: (a, b) => combineAmounts(a, b, (x, y) => x - y),
289
+ mul: multiplyAmounts,
290
+ div: divideAmounts
291
+ }
292
+ );
293
+ function multiplyAmounts(a, b) {
294
+ const product = a.raw * b.raw;
295
+ return BlockchainAmount({
296
+ raw: product / 10n ** BigInt(b.decimals),
297
+ decimals: a.decimals
298
+ });
299
+ }
300
+ function divideAmounts(a, b) {
301
+ if (b.raw === 0n) {
302
+ throw new MathError("Cannot divide a BlockchainAmount by zero");
303
+ }
304
+ const scaled = a.raw * 10n ** BigInt(b.decimals);
305
+ return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
306
+ }
307
+ function combineAmounts(a, b, op) {
308
+ if (a.decimals !== b.decimals) {
309
+ throw new InvariantError(
310
+ `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
311
+ );
312
+ }
313
+ const raw = op(a.raw, b.raw);
314
+ if (raw < 0n || raw > MAX_UINT_256) {
315
+ throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
316
+ }
317
+ return BlockchainAmount({ raw, decimals: a.decimals });
318
+ }
319
+ var AssetSymbol = (value) => value;
320
+ var StablecoinSymbol = (value) => value;
321
+ var KnownAssetSymbol = StablecoinSymbol;
322
+ var Bps = (value) => value;
323
+
324
+ // src/shared/types/blockchain/ui.ts
325
+ var FormattedAmountUi = (value) => value;
326
+ var FormattedPercentUi = (value) => value;
327
+ var TxExplorerUrl = (value) => value;
328
+ var ShortenedWalletAddress = (value) => value;
329
+ var FormattedAmountAssetUi = (value) => value;
330
+ var AssetIconUrl = (value) => value;
331
+
332
+ // src/shared/core/blockchain/chain.ts
333
+ var CHAIN_IDS = {
334
+ ethereum_mainnet: 1,
335
+ ethereum_sepolia: 11155111,
336
+ base_mainnet: 8453,
337
+ base_sepolia: 84532
338
+ };
339
+ function getChainId(chain) {
340
+ return CHAIN_IDS[chain];
341
+ }
342
+ function chainFromId(chainId) {
343
+ const chains = Object.keys(CHAIN_IDS);
344
+ const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);
345
+ if (!chain) {
346
+ throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
347
+ }
348
+ return chain;
349
+ }
350
+ function getNetworkName(chain) {
351
+ switch (chain) {
352
+ case "ethereum_mainnet":
353
+ return "Ethereum";
354
+ case "ethereum_sepolia":
355
+ return "Ethereum Sepolia";
356
+ case "base_mainnet":
357
+ return "Base";
358
+ case "base_sepolia":
359
+ return "Base Sepolia";
360
+ default: {
361
+ const _exhaustive = chain;
362
+ return _exhaustive;
363
+ }
364
+ }
365
+ }
366
+ function txExplorerUrl(chain, txHash) {
367
+ return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);
368
+ }
369
+ function explorerBaseUrl(chain) {
370
+ switch (chain) {
371
+ case "ethereum_mainnet":
372
+ return "https://etherscan.io";
373
+ case "ethereum_sepolia":
374
+ return "https://sepolia.etherscan.io";
375
+ case "base_mainnet":
376
+ return "https://basescan.org";
377
+ case "base_sepolia":
378
+ return "https://sepolia-explorer.base.org";
379
+ default: {
380
+ const _exhaustive = chain;
381
+ return _exhaustive;
382
+ }
383
+ }
384
+ }
385
+
386
+ // src/shared/types/providers/superstate/swap.ts
387
+ var SwapAuthorization = {
388
+ fromDto: (dto) => ({
389
+ authorized: dto.authorized
390
+ })
391
+ };
392
+ var SwapPreview = {
393
+ fromDto: (dto) => ({
394
+ inputAmount: parseUint256(
395
+ BigInt(dto.pay_input_amount),
396
+ "SwapPreview.pay_input_amount"
397
+ ),
398
+ fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
399
+ outputAmount: parseUint256(
400
+ BigInt(dto.receive_output_amount),
401
+ "SwapPreview.receive_output_amount"
402
+ )
403
+ })
404
+ };
405
+ var SwapStatus = {
406
+ fromDto: (dto) => ({
407
+ stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
408
+ swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
409
+ })
410
+ };
411
+ var TokenAllowance = {
412
+ fromDto: (dto) => ({
413
+ allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
414
+ })
415
+ };
416
+ var TokenBalance = {
417
+ fromDto: (dto) => ({
418
+ balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
419
+ })
420
+ };
421
+ var AllowWalletResponse = {
422
+ fromDto: (dto) => {
423
+ switch (dto.action) {
424
+ case "broadcast_transaction":
425
+ return {
426
+ action: "broadcast_transaction",
427
+ to: EvmContractAddress(dto.to),
428
+ data: HexEncodedTransactionData(dto.data)
429
+ };
430
+ case "none":
431
+ return {
432
+ action: "none",
433
+ alreadyAllowed: dto.already_allowed
434
+ };
435
+ default: {
436
+ const _exhaustive = dto;
437
+ return _exhaustive;
438
+ }
439
+ }
440
+ }
441
+ };
442
+
443
+ // src/shared/api/frontline/providers/superstate/swap.ts
444
+ async function getSwapAuthorization(api, params) {
445
+ const dto = await api.send({
446
+ method: "GET",
447
+ url: "/v1/wallet/authorized",
448
+ queryParams: {
449
+ chain: params.chain,
450
+ contract_address: params.contractAddress,
451
+ wallet_address: params.walletAddress
452
+ },
453
+ attributes: Attributes.protected()
454
+ });
455
+ return SwapAuthorization.fromDto(dto);
456
+ }
457
+ async function getSwapOutputToken(api, params) {
458
+ const dto = await api.send({
459
+ method: "GET",
460
+ url: "/v1/swap/output-token",
461
+ queryParams: {
462
+ chain: params.chain,
463
+ contract_address: params.contractAddress
464
+ },
465
+ attributes: Attributes.protected()
466
+ });
467
+ return toErc20Asset(dto);
468
+ }
469
+ async function getSwapPreview(api, params) {
470
+ const dto = await api.send({
471
+ method: "GET",
472
+ url: "/v1/swap/preview",
473
+ queryParams: {
474
+ chain: params.chain,
475
+ contract_address: params.contractAddress,
476
+ input_token: params.inputToken,
477
+ amount: params.amount.toString()
478
+ },
479
+ attributes: Attributes.protected()
480
+ });
481
+ return SwapPreview.fromDto(dto);
482
+ }
483
+ async function getSwapStatus(api, params) {
484
+ const dto = await api.send({
485
+ method: "GET",
486
+ url: "/v1/swap/status",
487
+ queryParams: {
488
+ chain: params.chain,
489
+ contract_address: params.contractAddress
490
+ },
491
+ attributes: Attributes.protected()
492
+ });
493
+ return SwapStatus.fromDto(dto);
494
+ }
495
+ async function getTokenAllowance(api, params) {
496
+ const dto = await api.send({
497
+ method: "GET",
498
+ url: "/v1/token/allowance",
499
+ queryParams: {
500
+ chain: params.chain,
501
+ token_address: params.tokenAddress,
502
+ owner: params.owner,
503
+ spender: params.spender
504
+ },
505
+ attributes: Attributes.protected()
506
+ });
507
+ return TokenAllowance.fromDto(dto);
508
+ }
509
+ async function getTokenBalance(api, params) {
510
+ const dto = await api.send({
511
+ method: "GET",
512
+ url: "/v1/token/balance",
513
+ queryParams: {
514
+ chain: params.chain,
515
+ token_address: params.tokenAddress,
516
+ owner: params.owner
517
+ },
518
+ attributes: Attributes.protected()
519
+ });
520
+ return TokenBalance.fromDto(dto);
521
+ }
522
+ async function allowWallet(api, params) {
523
+ const dto = await api.send({
524
+ method: "POST",
525
+ url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
526
+ body: {
527
+ wallet_address: params.walletAddress,
528
+ chain: params.chain,
529
+ signature: params.signature
530
+ },
531
+ attributes: Attributes.protected()
532
+ });
533
+ return AllowWalletResponse.fromDto(dto);
534
+ }
535
+ function toErc20Asset(dto) {
536
+ return {
537
+ name: dto.name,
538
+ symbol: AssetSymbol(dto.symbol),
539
+ decimals: AssetDecimals(dto.decimals)
540
+ };
541
+ }
542
+
543
+ // src/shared/core/observability/log-cause.ts
544
+ function classifyLogCause(error) {
545
+ if (error instanceof HttpError) {
546
+ return httpCause(error);
547
+ }
548
+ if (error instanceof ValidationError) {
549
+ return { type: "validation", message: error.message };
550
+ }
551
+ if (error instanceof InvariantError) {
552
+ return { type: "invariant", message: error.message };
553
+ }
554
+ if (error instanceof MathError) {
555
+ return { type: "math", message: error.message };
556
+ }
557
+ if (error instanceof NotAuthenticatedError) {
558
+ return { type: "not-authenticated" };
559
+ }
560
+ if (error instanceof NotImplementedError) {
561
+ return { type: "not-implemented" };
562
+ }
563
+ return { type: "generic-error", name: errorName(error) };
564
+ }
565
+ function describeErrorUnredacted(error) {
566
+ if (error instanceof HttpError) {
567
+ return describeHttpErrorRedacted(error);
568
+ }
569
+ if (error instanceof Error) {
570
+ return `${error.name}: ${error.message}`;
571
+ }
572
+ return `thrown non-error: ${stringifyUnredacted(error)}`;
573
+ }
574
+ function stringifyUnredacted(value) {
575
+ if (value === void 0) return "";
576
+ try {
577
+ return JSON.stringify(
578
+ value,
579
+ (_key, item) => typeof item === "bigint" ? `${item}` : item
580
+ ) ?? String(value);
581
+ } catch (_) {
582
+ return "<unserializable>";
583
+ }
584
+ }
585
+ function describeHttpErrorRedacted(error) {
586
+ const code = apiErrorCode(error);
587
+ const status = error.response.status;
588
+ return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
589
+ }
590
+ function errorName(error) {
591
+ return error instanceof Error ? error.name : `non-error ${typeof error}`;
592
+ }
593
+ function httpCause(error) {
594
+ return {
595
+ type: "http",
596
+ requestId: error.requestId,
597
+ status: error.response.status,
598
+ code: apiErrorCode(error),
599
+ eventId: apiErrorEventId(error)
600
+ };
601
+ }
602
+ function apiErrorEventId(error) {
603
+ const body = error.response.body;
604
+ if (typeof body !== "object" || body === null) return null;
605
+ const eventId = body.event_id;
606
+ return typeof eventId === "string" ? eventId : null;
607
+ }
608
+
609
+ // src/shared/core/observability/internal-logger.ts
610
+ function internalLogger(logger, scope) {
611
+ return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
612
+ }
613
+ var LEVEL_RANK = {
614
+ none: 0,
615
+ error: 1,
616
+ warn: 2,
617
+ info: 3,
618
+ debug: 4
619
+ };
620
+ function scopedLogger(logger, scope, bindings) {
621
+ const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
622
+ const safe = (event) => ({
623
+ msg: event.msg,
624
+ scope,
625
+ bindings,
626
+ fields: event.fields ?? {},
627
+ ...event.cause === void 0 ? {} : { cause: event.cause }
628
+ });
629
+ const unredacted = (event) => ({
630
+ msg: event.msg,
631
+ scope,
632
+ bindings,
633
+ fields: event.fields ?? {}
634
+ });
635
+ const self = {
636
+ child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
637
+ debug: (event) => {
638
+ if (admits("debug")) logger.debug(() => unredacted(event()));
639
+ },
640
+ info: (event) => {
641
+ if (admits("info")) logger.info(() => safe(event()));
642
+ },
643
+ warn: (event) => {
644
+ if (admits("warn")) logger.warn(() => safe(event()));
645
+ },
646
+ error: (event) => {
647
+ if (admits("error")) logger.error(() => safe(event()));
648
+ },
649
+ failure: (event, error) => {
650
+ if (admits("debug"))
651
+ logger.debug(() => unredacted(verbatim(event(), error)));
652
+ if (admits("error")) logger.error(() => safe(classified(event(), error)));
653
+ },
654
+ warning: (event, error) => {
655
+ if (admits("debug"))
656
+ logger.debug(() => unredacted(verbatim(event(), error)));
657
+ if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
658
+ },
659
+ wrap: async (op, params, run) => {
660
+ const opLog = self.child({ op });
661
+ opLog.debug(() => ({ msg: "call", fields: { params } }));
662
+ try {
663
+ return await run();
664
+ } catch (error) {
665
+ opLog.failure(() => ({ msg: "call failed" }), error);
666
+ throw error;
667
+ }
668
+ }
669
+ };
670
+ return self;
671
+ }
672
+ function verbatim(event, error) {
673
+ return {
674
+ msg: event.msg,
675
+ fields: { ...event.fields, error: describeErrorUnredacted(error) }
676
+ };
677
+ }
678
+ function classified(event, error) {
679
+ return { ...event, cause: event.cause ?? classifyLogCause(error) };
680
+ }
681
+ var noopInternalLogger = {
682
+ child: () => noopInternalLogger,
683
+ debug: () => void 0,
684
+ info: () => void 0,
685
+ warn: () => void 0,
686
+ error: () => void 0,
687
+ failure: () => void 0,
688
+ warning: () => void 0,
689
+ wrap: (_op, _params, run) => run()
690
+ };
691
+
692
+ // src/shared/core/blockchain/erc20/erc20-namespace.ts
693
+ var Erc20NamespaceImpl = class {
694
+ constructor(ctx) {
695
+ this.ctx = ctx;
696
+ this.log = internalLogger(ctx.logger, "ERC20");
697
+ }
698
+ async getAllowance(params) {
699
+ return this.log.wrap("getAllowance", params, async () => {
700
+ await this.ctx.ensureUserAuthenticated();
701
+ return getTokenAllowance(this.ctx.api, params);
702
+ });
703
+ }
704
+ async getBalance(params) {
705
+ return this.log.wrap("getBalance", params, async () => {
706
+ await this.ctx.ensureUserAuthenticated();
707
+ return getTokenBalance(this.ctx.api, params);
708
+ });
709
+ }
710
+ };
711
+
712
+ // src/shared/core/blockchain/formatters.ts
713
+ import { formatUnits } from "viem";
714
+ function shortenAddress(address) {
715
+ const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
716
+ return ShortenedWalletAddress(short);
717
+ }
718
+ function formatAmount(amount, locale, options) {
719
+ const decimal = formatRawAmount(amount);
720
+ let [integerPart, fractionPart = ""] = decimal.split(".");
721
+ const maxFractionDigits = options?.maxFractionDigits;
722
+ const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
723
+ if (maxFractionDigits !== void 0 && fractionPart.length > maxFractionDigits) {
724
+ ({ integerPart, fractionPart } = roundFractionHalfUp(
725
+ integerPart,
726
+ fractionPart,
727
+ maxFractionDigits
728
+ ));
729
+ }
730
+ const fraction = minFractionDigits === 0 ? "" : fractionPart.padEnd(minFractionDigits, "0");
731
+ const integerFormatted = BigInt(integerPart).toLocaleString(locale);
732
+ if (minFractionDigits === 0 && fraction === "") {
733
+ return FormattedAmountUi(integerFormatted);
734
+ }
735
+ const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
736
+ return FormattedAmountUi(`${integerFormatted}${decimalSeparator}${fraction}`);
737
+ }
738
+ function roundFractionHalfUp(integerPart, fractionPart, maxFractionDigits) {
739
+ if (fractionPart.length <= maxFractionDigits) {
740
+ return { integerPart, fractionPart };
741
+ }
742
+ if (maxFractionDigits === 0) {
743
+ const roundUp = fractionPart[0] >= "5";
744
+ const integer = BigInt(integerPart) + (roundUp ? 1n : 0n);
745
+ return { integerPart: integer.toString(), fractionPart: "" };
746
+ }
747
+ const trimmed = fractionPart.slice(0, maxFractionDigits);
748
+ if (fractionPart[maxFractionDigits] < "5") {
749
+ return { integerPart, fractionPart: trimmed };
750
+ }
751
+ const digits = trimmed.split("").map((digit) => Number.parseInt(digit, 10));
752
+ let carry = 1;
753
+ for (let i = digits.length - 1; i >= 0 && carry > 0; i -= 1) {
754
+ const sum = digits[i] + carry;
755
+ if (sum === 10) {
756
+ digits[i] = 0;
757
+ carry = 1;
758
+ } else {
759
+ digits[i] = sum;
760
+ carry = 0;
761
+ }
762
+ }
763
+ return {
764
+ integerPart: carry > 0 ? (BigInt(integerPart) + 1n).toString() : integerPart,
765
+ fractionPart: digits.join("")
766
+ };
767
+ }
768
+ function formatRawAmount(amount) {
769
+ return formatUnits(amount.raw, amount.decimals);
770
+ }
771
+ function formatCompactAmount(amount, locale) {
772
+ const value = Number(formatRawAmount(amount));
773
+ const formatted = new Intl.NumberFormat(locale, {
774
+ notation: "compact",
775
+ maximumFractionDigits: 2
776
+ }).format(value);
777
+ return FormattedAmountUi(formatted);
778
+ }
779
+ function formatBpsAsPercent(bps, locale) {
780
+ const whole = bps / 100n;
781
+ const fraction = bps % 100n;
782
+ const wholeFormatted = whole.toLocaleString(locale);
783
+ const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
784
+ if (fraction === 0n) {
785
+ return FormattedPercentUi(`${wholeFormatted}%`);
786
+ }
787
+ const fractionFormatted = fraction.toString().padStart(2, "0").replace(/0+$/, "");
788
+ return FormattedPercentUi(
789
+ `${wholeFormatted}${decimalSeparator}${fractionFormatted}%`
790
+ );
791
+ }
792
+ function usdAmount(amount) {
793
+ return FormattedAmountAssetUi(`$${amount}`);
794
+ }
795
+ function assetAmount(amount, symbol) {
796
+ return FormattedAmountAssetUi(`${amount} ${symbol}`);
797
+ }
798
+ var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
799
+ var USD_FRACTION_DIGITS = AssetDecimals(2);
800
+ function formattedUsdPrice(amount, locale) {
801
+ if (!amount) return NA_AMOUNT_ASSET_UI;
802
+ return usdAmount(
803
+ formatAmount(amount, locale, { maxFractionDigits: USD_FRACTION_DIGITS })
804
+ );
805
+ }
806
+
807
+ // src/shared/core/blockchain/math.ts
808
+ import { parseUnits } from "viem";
809
+ function blockchainAmountFromRawOrThrow({
810
+ label,
811
+ raw,
812
+ decimals
813
+ }) {
814
+ const trimmed = raw.trim();
815
+ if (trimmed === "") {
816
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
817
+ }
818
+ let value;
819
+ try {
820
+ value = BigInt(trimmed);
821
+ } catch {
822
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
823
+ }
824
+ try {
825
+ return BlockchainAmount({ raw: assertUint256(value), decimals });
826
+ } catch {
827
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
828
+ }
829
+ }
830
+ function parseBlockchainAmount(amount, decimals) {
831
+ const trimmed = amount.trim();
832
+ if (trimmed === "") return { valid: false, reason: { type: "empty" } };
833
+ if (trimmed.startsWith("-")) {
834
+ return { valid: false, reason: { type: "negative" } };
835
+ }
836
+ if (/[eE]/.test(trimmed)) {
837
+ return { valid: false, reason: { type: "invalid-format" } };
838
+ }
839
+ if (!/^\d+(\.\d+)?$/.test(trimmed)) {
840
+ return { valid: false, reason: { type: "invalid-format" } };
841
+ }
842
+ const [, fraction = ""] = trimmed.split(".");
843
+ if (fraction.length > decimals) {
844
+ return {
845
+ valid: false,
846
+ reason: { type: "too-many-decimals", maxDecimals: decimals }
847
+ };
848
+ }
849
+ try {
850
+ const raw = parseUnits(trimmed, decimals);
851
+ if (raw > MAX_UINT_256) {
852
+ return { valid: false, reason: { type: "overflow" } };
853
+ }
854
+ return {
855
+ valid: true,
856
+ amount: BlockchainAmount({ raw, decimals })
857
+ };
858
+ } catch {
859
+ return { valid: false, reason: { type: "invalid-format" } };
860
+ }
861
+ }
862
+
863
+ // src/shared/types/pagination.ts
864
+ var Cursor = (value) => value;
865
+ var PaginatedResponse = {
866
+ fromDto: (dto, itemMapper) => ({
867
+ data: dto.data.map(itemMapper),
868
+ startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
869
+ startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
870
+ })
871
+ };
872
+ var PaginationParams = {
873
+ toQueryParams: (params) => {
874
+ const queryParams = {};
875
+ if (params.after) {
876
+ queryParams.starting_after = params.after;
877
+ }
878
+ if (params.before) {
879
+ queryParams.starting_before = params.before;
880
+ }
881
+ if (params.limit) {
882
+ queryParams.limit = params.limit;
883
+ }
884
+ return queryParams;
885
+ }
886
+ };
887
+
888
+ // src/shared/types/asset.ts
889
+ var AssetId = (value) => value;
890
+ var AssetCode = (value) => value;
891
+ var Asset = {
892
+ fromDto: (dto) => ({
893
+ id: AssetId(dto.id),
894
+ code: AssetCode(dto.code),
895
+ name: dto.name,
896
+ fractionalDigits: dto.fractional_digits
897
+ })
898
+ };
899
+
900
+ // src/shared/types/offer.ts
901
+ var OfferId = (value) => value;
902
+ var OfferSlug = (value) => value;
903
+ var Offer = {
904
+ fromDto: (dto) => {
905
+ if (!Array.isArray(dto.tokens)) {
906
+ throw new ValidationError(
907
+ `Offer.tokens: expected an array, got ${typeof dto.tokens}`
908
+ );
909
+ }
910
+ return {
911
+ id: OfferId(dto.id),
912
+ slug: OfferSlug(dto.slug),
913
+ type: dto.type,
914
+ tagline: dto.tagline,
915
+ bannerUrl: dto.banner_url,
916
+ logoUrl: dto.logo_url,
917
+ startsAt: new Date(dto.starts_at),
918
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
919
+ tokens: dto.tokens.map(OfferToken.fromDto)
920
+ };
921
+ }
922
+ };
923
+ var OfferToken = {
924
+ fromDto: (dto) => ({
925
+ role: dto.role,
926
+ chain: Chain(dto.chain),
927
+ address: EvmContractAddress(dto.address)
928
+ })
929
+ };
930
+
931
+ // src/shared/core/utils/crypto.ts
932
+ async function sha256(data) {
933
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
934
+ const buffer = bytes.buffer.slice(
935
+ bytes.byteOffset,
936
+ bytes.byteOffset + bytes.byteLength
937
+ );
938
+ return crypto.subtle.digest("SHA-256", buffer);
939
+ }
940
+ function arrayBufferToBase64Url(buffer, padding = true) {
941
+ const bytes = new Uint8Array(buffer);
942
+ let binary = "";
943
+ for (let i = 0; i < bytes.length; i++) {
944
+ binary += String.fromCharCode(bytes[i]);
945
+ }
946
+ let base64 = btoa(binary);
947
+ base64 = base64.replace(/\+/g, "-").replace(/\//g, "_");
948
+ if (!padding) {
949
+ base64 = base64.replace(/=+$/, "");
950
+ }
951
+ return base64;
952
+ }
953
+ function generateSecureRandomBase64Url(byteLength) {
954
+ const bytes = new Uint8Array(byteLength);
955
+ crypto.getRandomValues(bytes);
956
+ const buffer = bytes.buffer;
957
+ return arrayBufferToBase64Url(buffer, false);
958
+ }
959
+ function getUUIDv4() {
960
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
961
+ return crypto.randomUUID();
962
+ }
963
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
964
+ const bytes = new Uint8Array(16);
965
+ crypto.getRandomValues(bytes);
966
+ bytes[6] = bytes[6] & 15 | 64;
967
+ bytes[8] = bytes[8] & 63 | 128;
968
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
969
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
970
+ }
971
+ return `${Date.now()}-${Math.random().toString(36).slice(2, 12)}`;
972
+ }
973
+ function notBlankStringOrNull(value) {
974
+ if (value?.trim()) {
975
+ return value;
976
+ } else {
977
+ return null;
978
+ }
979
+ }
980
+
981
+ // src/shared/types/offer-detail.ts
982
+ var OfferOptionId = (value) => value;
983
+ var OfferOptionSlug = (value) => value;
984
+ var OfferDetail = {
985
+ fromDto: (dto) => {
986
+ if (!Array.isArray(dto.funding_assets)) {
987
+ throw new ValidationError(
988
+ `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
989
+ );
990
+ }
991
+ if (!Array.isArray(dto.options)) {
992
+ throw new ValidationError(
993
+ `OfferDetail.options: expected an array, got ${typeof dto.options}`
994
+ );
995
+ }
996
+ if (!Array.isArray(dto.terms)) {
997
+ throw new ValidationError(
998
+ `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
999
+ );
1000
+ }
1001
+ if (!Array.isArray(dto.links)) {
1002
+ throw new ValidationError(
1003
+ `OfferDetail.links: expected an array, got ${typeof dto.links}`
1004
+ );
1005
+ }
1006
+ if (!Array.isArray(dto.faqs)) {
1007
+ throw new ValidationError(
1008
+ `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
1009
+ );
1010
+ }
1011
+ if (!Array.isArray(dto.milestones)) {
1012
+ throw new ValidationError(
1013
+ `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
1014
+ );
1015
+ }
1016
+ if (!Array.isArray(dto.tokens)) {
1017
+ throw new ValidationError(
1018
+ `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1019
+ );
1020
+ }
1021
+ return {
1022
+ id: OfferId(dto.id),
1023
+ slug: OfferSlug(dto.slug),
1024
+ type: dto.type,
1025
+ name: dto.name,
1026
+ asset: Asset.fromDto(dto.asset),
1027
+ fundingAssets: dto.funding_assets.map(Asset.fromDto),
1028
+ tokens: dto.tokens.map(OfferToken.fromDto),
1029
+ about: notBlankStringOrNull(dto.about),
1030
+ tagline: dto.tagline,
1031
+ bannerUrl: dto.banner_url,
1032
+ logoUrl: dto.logo_url,
1033
+ category: dto.category,
1034
+ startsAt: new Date(dto.starts_at),
1035
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1036
+ faqs: dto.faqs.map(FaqItem.fromDto),
1037
+ links: dto.links.map(Link.fromDto),
1038
+ milestones: dto.milestones.map(Milestone.fromDto),
1039
+ options: dto.options.map(OfferOption.fromDto),
1040
+ terms: dto.terms.map(TermItem.fromDto)
1041
+ };
1042
+ }
1043
+ };
1044
+ var OfferOption = {
1045
+ fromDto: (dto) => ({
1046
+ id: OfferOptionId(dto.id),
1047
+ slug: OfferOptionSlug(dto.slug),
1048
+ bidIncrement: dto.bid_increment,
1049
+ floorPriceUsd: dto.floor_price_usd,
1050
+ minimumPurchaseUsd: dto.minimum_purchase_usd,
1051
+ priceUsd: dto.price_usd,
1052
+ saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),
1053
+ totalTokenSupply: dto.total_token_supply
1054
+ })
1055
+ };
1056
+ var FaqItem = {
1057
+ fromDto: (dto) => ({
1058
+ question: notBlankStringOrNull(dto.question),
1059
+ answer: notBlankStringOrNull(dto.answer)
1060
+ })
1061
+ };
1062
+ var Link = {
1063
+ fromDto: (dto) => ({
1064
+ label: notBlankStringOrNull(dto.label),
1065
+ url: notBlankStringOrNull(dto.url)
1066
+ })
1067
+ };
1068
+ var TermItem = {
1069
+ fromDto: (dto) => ({
1070
+ key: notBlankStringOrNull(dto.key),
1071
+ value: notBlankStringOrNull(dto.value)
1072
+ })
1073
+ };
1074
+ var Milestone = {
1075
+ fromDto: (dto) => ({
1076
+ name: notBlankStringOrNull(dto.name),
1077
+ schedule: notBlankStringOrNull(dto.schedule),
1078
+ status: dto.status
1079
+ })
1080
+ };
1081
+
1082
+ // src/shared/types/providers/coin-list/token-sale.ts
1083
+ var ParticipationId = (value) => value;
1084
+ var Blockchain = (value) => value;
1085
+ var WalletAddress = (value) => value;
1086
+ var ParticipationsPaginationParams = {
1087
+ toQueryParams: (params) => {
1088
+ const queryParams = PaginationParams.toQueryParams(params);
1089
+ if (params.offerId) {
1090
+ queryParams["filters[0][field]"] = "offer_id";
1091
+ queryParams["filters[0][op]"] = "==";
1092
+ queryParams["filters[0][value]"] = params.offerId;
1093
+ }
1094
+ return queryParams;
1095
+ }
1096
+ };
1097
+ var Participation = {
1098
+ /** Maps API DTO shape into the SDK participation domain model. */
1099
+ fromDto: (dto) => {
1100
+ const walletAddress = notBlankStringOrNull(dto.wallet_address);
1101
+ return {
1102
+ id: ParticipationId(dto.id),
1103
+ offerId: OfferId(dto.offer_id),
1104
+ offerOptionId: OfferOptionId(dto.offer_option_id),
1105
+ status: dto.status,
1106
+ amount: dto.amount,
1107
+ displayAmount: dto.amount_string,
1108
+ asset: Asset.fromDto(dto.asset),
1109
+ chain: Blockchain(dto.chain),
1110
+ insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
1111
+ updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
1112
+ walletAddress: walletAddress ? WalletAddress(walletAddress) : null
1113
+ };
1114
+ }
1115
+ };
1116
+ var CreateParticipationParams = {
1117
+ /** Maps participation creation params into API DTO payload. */
1118
+ toDto: (params) => ({
1119
+ offer_id: params.offerId,
1120
+ offer_option_id: params.offerOptionId,
1121
+ chain: params.chain,
1122
+ wallet_address: params.walletAddress,
1123
+ amount: params.amount,
1124
+ asset_id: params.assetId,
1125
+ approval_transaction_hash: params.approvalTransactionHash
1126
+ })
1127
+ };
1128
+
1129
+ // src/shared/api/frontline/providers/coin-list/token-sale.ts
1130
+ async function fetchParticipations(api, offerId) {
1131
+ return fetchAllPages(
1132
+ (params) => fetchParticipationsPage(api, params),
1133
+ { offerId }
1134
+ );
1135
+ }
1136
+ async function fetchParticipationsPage(api, params) {
1137
+ const pageDto = await api.send({
1138
+ method: "GET",
1139
+ url: "/v1/participations",
1140
+ queryParams: ParticipationsPaginationParams.toQueryParams(params),
1141
+ attributes: Attributes.protected()
1142
+ });
1143
+ return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
1144
+ }
1145
+ async function fetchParticipation(api, id) {
1146
+ const dto = await api.send({
1147
+ method: "GET",
1148
+ url: `/v1/participations/${id}`,
1149
+ attributes: Attributes.protected()
1150
+ });
1151
+ return Participation.fromDto(dto);
1152
+ }
1153
+ async function createParticipation(api, params) {
1154
+ const dto = await api.send({
1155
+ method: "POST",
1156
+ url: "/v1/participations",
1157
+ body: CreateParticipationParams.toDto(params),
1158
+ attributes: Attributes.protected()
1159
+ });
1160
+ return Participation.fromDto(dto);
1161
+ }
1162
+
1163
+ // src/shared/core/checkout/coin-list/token-sale-namespace.ts
1164
+ var CoinListTokenSaleNamespaceImpl = class {
1165
+ constructor(ctx) {
1166
+ this.ctx = ctx;
1167
+ this.log = internalLogger(ctx.logger, "TOKEN_SALE");
1168
+ }
1169
+ async list(offerId) {
1170
+ return this.log.wrap("list", offerId, async () => {
1171
+ await this.ctx.ensureUserAuthenticated();
1172
+ return fetchParticipations(this.ctx.api, offerId);
1173
+ });
1174
+ }
1175
+ async listPage(params) {
1176
+ return this.log.wrap("listPage", params, async () => {
1177
+ await this.ctx.ensureUserAuthenticated();
1178
+ return fetchParticipationsPage(this.ctx.api, params);
1179
+ });
1180
+ }
1181
+ async get(id) {
1182
+ return this.log.wrap("get", id, async () => {
1183
+ await this.ctx.ensureUserAuthenticated();
1184
+ return fetchParticipation(this.ctx.api, id);
1185
+ });
1186
+ }
1187
+ async createParticipation(params) {
1188
+ return this.log.wrap("createParticipation", params, async () => {
1189
+ await this.ctx.ensureUserAuthenticated();
1190
+ return createParticipation(this.ctx.api, params);
1191
+ });
1192
+ }
1193
+ };
1194
+
1195
+ // src/shared/types/trading.ts
1196
+ var Ticker = (value) => value;
1197
+
1198
+ // src/shared/types/providers/ondo/ondo.ts
1199
+ var OndoTradingStatus = {
1200
+ fromDto: (dto) => {
1201
+ if (!dto.tradable) return { type: "not-tradable", side: dto.side };
1202
+ return {
1203
+ type: "tradable",
1204
+ side: dto.side,
1205
+ grossMaxTokens: decimalOrNull(dto.gross_max_tokens),
1206
+ grossMaxNotionalValue: decimalOrNull(dto.gross_max_notional_value),
1207
+ grossMaxActiveNotionalValue: decimalOrNull(
1208
+ dto.gross_max_active_notional_value
1209
+ )
1210
+ };
1211
+ }
1212
+ };
1213
+ var decimalOrNull = (value) => value === null ? null : DecimalString(value);
1214
+ var OndoQuote = {
1215
+ fromDto: (dto) => {
1216
+ const assetDecimals = AssetDecimals(dto.asset_decimals);
1217
+ return {
1218
+ chain: chainFromId(dto.chain_id),
1219
+ ticker: Ticker(dto.ticker),
1220
+ assetAddress: EvmContractAddress(dto.asset_address),
1221
+ asset: {
1222
+ name: dto.ticker,
1223
+ symbol: AssetSymbol(dto.symbol),
1224
+ decimals: assetDecimals
1225
+ },
1226
+ side: dto.side,
1227
+ tokenBaseUnits: blockchainAmountFromRawOrThrow({
1228
+ label: "tokenBaseUnits",
1229
+ raw: dto.token_base_units,
1230
+ decimals: assetDecimals
1231
+ }),
1232
+ price: DecimalString(dto.price)
1233
+ };
1234
+ }
1235
+ };
1236
+ var OndoBuyTransaction = {
1237
+ fromDto: (dto) => {
1238
+ const spendDecimals = AssetDecimals(dto.spend_input_decimals);
1239
+ const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1240
+ return {
1241
+ ...parseSwapCore(dto, spendDecimals),
1242
+ side: "buy",
1243
+ fee: blockchainAmountFromRawOrThrow({
1244
+ label: "fee",
1245
+ raw: dto.fee,
1246
+ decimals: spendDecimals
1247
+ }),
1248
+ notionalValue: blockchainAmountFromRawOrThrow({
1249
+ label: "notional_value",
1250
+ raw: dto.notional_value,
1251
+ decimals: spendDecimals
1252
+ }),
1253
+ receiveOutputAmount: parsePositiveAmount({
1254
+ label: "receive_output_amount",
1255
+ raw: dto.receive_output_amount,
1256
+ decimals: outputDecimals,
1257
+ // A transaction that yields nothing is not one to sign - the user
1258
+ // would pay the deposit and receive no asset - and frontline refuses
1259
+ // to emit one. A zero here is a changed encoding, not a small order.
1260
+ // Rejecting it at the boundary is also what lets `computeOndoBuyPrice`
1261
+ // divide by it without a fallible result: the failure surfaces as the
1262
+ // data hook's ERROR state rather than as a division during render.
1263
+ reason: "a buy that yields nothing is not fillable"
1264
+ })
1265
+ };
1266
+ }
1267
+ };
1268
+ var OndoSellTransaction = {
1269
+ fromDto: (dto) => {
1270
+ const spendDecimals = AssetDecimals(dto.spend_input_decimals);
1271
+ const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1272
+ const expectedQuantity = parsePositiveAmount({
1273
+ label: "expected_quantity",
1274
+ raw: dto.expected_quantity,
1275
+ decimals: outputDecimals,
1276
+ reason: "a sale that yields nothing is not fillable"
1277
+ });
1278
+ return {
1279
+ ...parseSwapCore(dto, spendDecimals),
1280
+ side: "sell",
1281
+ expected: {
1282
+ quantity: expectedQuantity,
1283
+ fee: blockchainAmountFromRawOrThrow({
1284
+ label: "expected_fee",
1285
+ raw: dto.expected_fee,
1286
+ decimals: outputDecimals
1287
+ })
1288
+ },
1289
+ minimum: {
1290
+ quantity: parseMinimumQuantity(
1291
+ dto.minimum_quantity,
1292
+ outputDecimals,
1293
+ expectedQuantity
1294
+ ),
1295
+ fee: blockchainAmountFromRawOrThrow({
1296
+ label: "minimum_fee",
1297
+ raw: dto.minimum_fee,
1298
+ decimals: outputDecimals
1299
+ })
1300
+ }
1301
+ };
1302
+ }
1303
+ };
1304
+ function parseSwapCore(dto, spendDecimals) {
1305
+ return {
1306
+ tx: {
1307
+ to: EvmContractAddress(dto.to),
1308
+ data: HexEncodedTransactionData(dto.data)
1309
+ },
1310
+ expiresAt: parseExpiresAt(dto.expires_at),
1311
+ spendInputAmount: parsePositiveAmount({
1312
+ label: "spend_input_amount",
1313
+ raw: dto.spend_input_amount,
1314
+ decimals: spendDecimals,
1315
+ // A transaction that takes nothing from the wallet is not one to sign:
1316
+ // it would settle one leg of a trade and skip the other. Frontline
1317
+ // refuses an `amount` of zero whichever way the trade runs, so this is a
1318
+ // changed encoding rather than a small order.
1319
+ //
1320
+ // Guarded on both sides rather than on the sale alone, because which
1321
+ // amount becomes the divisor in the price flips with the direction: a
1322
+ // guard placed by that would be a rule about the arithmetic rather than
1323
+ // about the trade.
1324
+ reason: "a swap that spends nothing is not fillable"
1325
+ })
1326
+ };
1327
+ }
1328
+ function parseMinimumQuantity(raw, decimals, expectedQuantity) {
1329
+ const amount = parsePositiveAmount({
1330
+ label: "minimum_quantity",
1331
+ raw,
1332
+ decimals,
1333
+ reason: "a floor of zero guarantees nothing"
1334
+ });
1335
+ if (amount.raw > expectedQuantity.raw) {
1336
+ throw new ValidationError(
1337
+ `minimum_quantity: must not exceed expected_quantity ("${raw}" > "${expectedQuantity.raw}")`
1338
+ );
1339
+ }
1340
+ return amount;
1341
+ }
1342
+ function parsePositiveAmount({
1343
+ label,
1344
+ raw,
1345
+ decimals,
1346
+ reason
1347
+ }) {
1348
+ const amount = blockchainAmountFromRawOrThrow({ label, raw, decimals });
1349
+ if (amount.raw <= 0n) {
1350
+ throw new ValidationError(
1351
+ `${label}: must be greater than zero ("${raw}") - ${reason}`
1352
+ );
1353
+ }
1354
+ return amount;
1355
+ }
1356
+ function parseExpiresAt(value) {
1357
+ const date = new Date(value);
1358
+ if (Number.isNaN(date.getTime())) {
1359
+ throw new ValidationError(`expires_at: not a date ("${value}")`);
1360
+ }
1361
+ return date;
1362
+ }
1363
+
1364
+ // src/shared/api/frontline/providers/ondo/ondo.ts
1365
+ async function getOndoTradingStatus(api, params) {
1366
+ const dto = await api.send({
1367
+ method: "GET",
1368
+ url: "/v1/ondo/swap/trading-status",
1369
+ queryParams: { symbol: params.symbol, side: params.side },
1370
+ attributes: Attributes.protected()
1371
+ });
1372
+ return OndoTradingStatus.fromDto(dto);
1373
+ }
1374
+ async function getOndoQuote(api, params) {
1375
+ const dto = await api.send({
1376
+ method: "GET",
1377
+ url: "/v1/ondo/swap/quote",
1378
+ queryParams: {
1379
+ symbol: params.symbol,
1380
+ side: params.side,
1381
+ duration: params.duration,
1382
+ ...sizeParam(params)
1383
+ },
1384
+ attributes: Attributes.protected()
1385
+ });
1386
+ return OndoQuote.fromDto(dto);
1387
+ }
1388
+ async function buildOndoBuy(api, params) {
1389
+ const dto = await api.send({
1390
+ method: "POST",
1391
+ url: "/v1/ondo/swap/buy",
1392
+ body: swapBody(params),
1393
+ attributes: Attributes.protected()
1394
+ });
1395
+ assertSpendScaleAgrees({
1396
+ published: dto.spend_input_decimals,
1397
+ sized: params.amount,
1398
+ trade: "purchase"
1399
+ });
1400
+ return OndoBuyTransaction.fromDto(dto);
1401
+ }
1402
+ async function buildOndoSell(api, params) {
1403
+ const dto = await api.send({
1404
+ method: "POST",
1405
+ url: "/v1/ondo/swap/sell",
1406
+ body: swapBody(params),
1407
+ attributes: Attributes.protected()
1408
+ });
1409
+ assertSpendScaleAgrees({
1410
+ published: dto.spend_input_decimals,
1411
+ sized: params.amount,
1412
+ trade: "sale",
1413
+ // The two answers come from two chains, so on a testnet they can disagree
1414
+ // for a reason that is neither the caller's nor a corrupt response. Say so,
1415
+ // or a QA run reads as a puzzle rather than a diagnosis.
1416
+ note: "the quote resolves the asset on Ethereum mainnet while the swap executes on the chain requested, so these disagree until frontline serves a chain-scoped quote"
1417
+ });
1418
+ return OndoSellTransaction.fromDto(dto);
1419
+ }
1420
+ function swapBody(params) {
1421
+ return {
1422
+ symbol: params.symbol,
1423
+ chain: params.chain,
1424
+ wallet_address: params.walletAddress,
1425
+ amount: params.amount.raw.toString()
1426
+ };
1427
+ }
1428
+ function assertSpendScaleAgrees({
1429
+ published,
1430
+ sized,
1431
+ trade,
1432
+ note
1433
+ }) {
1434
+ if (published === sized.decimals) return;
1435
+ const because = note === void 0 ? "" : ` - ${note}`;
1436
+ throw new ValidationError(
1437
+ `spend_input_decimals: the ${trade} was priced in ${published} decimals but the order was sized in ${sized.decimals}${because}`
1438
+ );
1439
+ }
1440
+ function sizeParam(params) {
1441
+ const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
1442
+ const notionalValue = "notionalValue" in params ? params.notionalValue : void 0;
1443
+ if (tokenAmount !== void 0) {
1444
+ if (notionalValue !== void 0) {
1445
+ throw new ValidationError(
1446
+ "An Ondo quote takes tokenAmount or notionalValue, not both"
1447
+ );
1448
+ }
1449
+ return { token_amount: formatRawAmount(tokenAmount) };
1450
+ }
1451
+ if (notionalValue === void 0) {
1452
+ throw new ValidationError(
1453
+ "An Ondo quote must be sized by tokenAmount or notionalValue"
1454
+ );
1455
+ }
1456
+ return { notional_value: notionalValue };
1457
+ }
1458
+
1459
+ // src/shared/core/checkout/ondo/ondo-namespace.ts
1460
+ var OndoNamespaceImpl = class {
1461
+ constructor(ctx) {
1462
+ this.ctx = ctx;
1463
+ this.log = internalLogger(ctx.logger, "ONDO");
1464
+ }
1465
+ async getTradingStatus(params) {
1466
+ return this.log.wrap("getTradingStatus", params, async () => {
1467
+ await this.ctx.ensureUserAuthenticated();
1468
+ return getOndoTradingStatus(this.ctx.api, params);
1469
+ });
1470
+ }
1471
+ async getQuote(params) {
1472
+ return this.log.wrap("getQuote", params, async () => {
1473
+ await this.ctx.ensureUserAuthenticated();
1474
+ return getOndoQuote(this.ctx.api, params);
1475
+ });
1476
+ }
1477
+ async buildBuyTransaction(params) {
1478
+ return this.log.wrap("buildBuyTransaction", params, async () => {
1479
+ await this.ctx.ensureUserAuthenticated();
1480
+ return buildOndoBuy(this.ctx.api, params);
1481
+ });
1482
+ }
1483
+ async buildSellTransaction(params) {
1484
+ return this.log.wrap("buildSellTransaction", params, async () => {
1485
+ await this.ctx.ensureUserAuthenticated();
1486
+ return buildOndoSell(this.ctx.api, params);
1487
+ });
1488
+ }
1489
+ };
1490
+
1491
+ // src/shared/core/checkout/superstate/swap-namespace.ts
1492
+ var SuperstateSwapNamespaceImpl = class {
1493
+ constructor(ctx) {
1494
+ this.ctx = ctx;
1495
+ this.log = internalLogger(ctx.logger, "SUPERSTATE");
1496
+ }
1497
+ async getAuthorization(params) {
1498
+ return this.log.wrap("getAuthorization", params, async () => {
1499
+ await this.ctx.ensureUserAuthenticated();
1500
+ return getSwapAuthorization(this.ctx.api, params);
1501
+ });
1502
+ }
1503
+ async getPreview(params) {
1504
+ return this.log.wrap("getPreview", params, async () => {
1505
+ await this.ctx.ensureUserAuthenticated();
1506
+ return getSwapPreview(this.ctx.api, params);
1507
+ });
1508
+ }
1509
+ async getStatus(params) {
1510
+ return this.log.wrap("getStatus", params, async () => {
1511
+ await this.ctx.ensureUserAuthenticated();
1512
+ return getSwapStatus(this.ctx.api, params);
1513
+ });
1514
+ }
1515
+ async getOutputToken(params) {
1516
+ return this.log.wrap("getOutputToken", params, async () => {
1517
+ await this.ctx.ensureUserAuthenticated();
1518
+ return getSwapOutputToken(this.ctx.api, params);
1519
+ });
1520
+ }
1521
+ async allowWallet(params) {
1522
+ return this.log.wrap("allowWallet", params, async () => {
1523
+ await this.ctx.ensureUserAuthenticated();
1524
+ return allowWallet(this.ctx.api, params);
1525
+ });
1526
+ }
1527
+ };
1528
+
1529
+ // src/shared/types/document-submission.ts
1530
+ var DocumentSubmission = {
1531
+ fromDto: (dto) => ({
1532
+ status: dto.status,
1533
+ formType: dto.form_type
1534
+ })
1535
+ };
1536
+
1537
+ // src/shared/types/kyc.ts
1538
+ var KycToken = {
1539
+ fromDto: (dto) => ({
1540
+ token: dto.token
1541
+ })
1542
+ };
1543
+
1544
+ // src/shared/types/pii.ts
1545
+ var Iso2CountryCode = (value) => value;
1546
+ var PiiJurisdiction = {
1547
+ fromDto: (dto) => ({
1548
+ iso2: Iso2CountryCode(dto.iso_2),
1549
+ name: dto.name
1550
+ })
1551
+ };
1552
+ var PiiAddress = {
1553
+ fromDto: (dto) => ({
1554
+ street: dto.street,
1555
+ city: dto.city,
1556
+ state: dto.state,
1557
+ postalCode: dto.postal_code,
1558
+ country: dto.country
1559
+ })
1560
+ };
1561
+ var Pii = {
1562
+ fromDto: (dto) => ({
1563
+ kind: dto.kind,
1564
+ fullLegalName: dto.full_legal_name,
1565
+ dateOfBirth: dto.date_of_birth,
1566
+ jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
1567
+ taxId: dto.tax_id,
1568
+ permanentAddress: PiiAddress.fromDto(dto.permanent_address)
1569
+ })
1570
+ };
1571
+
1572
+ // src/shared/types/requirement.ts
1573
+ var RequirementId = (value) => value;
1574
+ var Requirement = {
1575
+ fromDto: (dto) => ({
1576
+ id: RequirementId(dto.id),
1577
+ type: dto.type,
1578
+ details: dto.details
1579
+ })
1580
+ };
1581
+ var RequirementStatusInfo = {
1582
+ fromStatusesDto: (dto) => Object.entries(dto.statuses).map(
1583
+ ([id, value]) => typeof value === "string" ? { id: RequirementId(id), status: value, action: null } : {
1584
+ id: RequirementId(id),
1585
+ status: value.status,
1586
+ action: value.action ?? null,
1587
+ kycLevel: value.kyc_level,
1588
+ kycReset: value.kyc_reset
1589
+ }
1590
+ )
1591
+ };
1592
+
1593
+ // src/shared/api/frontline/documents.ts
1594
+ async function submitDocument(api, documentType, fields) {
1595
+ const dto = await api.send({
1596
+ method: "POST",
1597
+ url: `/v1/documents/${documentType}/submission`,
1598
+ body: fields,
1599
+ attributes: Attributes.protected()
1600
+ });
1601
+ return DocumentSubmission.fromDto(dto);
1602
+ }
1603
+
1604
+ // src/shared/api/frontline/kyc.ts
1605
+ async function createKycToken(api, levelName, reset) {
1606
+ const dto = await api.send({
1607
+ method: "POST",
1608
+ url: "/v1/kyc-token",
1609
+ body: {
1610
+ ...levelName === void 0 ? {} : { level_name: levelName },
1611
+ ...reset === void 0 ? {} : { reset }
1612
+ },
1613
+ attributes: Attributes.protected()
1614
+ });
1615
+ return KycToken.fromDto(dto);
1616
+ }
1617
+
1618
+ // src/shared/api/frontline/pii.ts
1619
+ async function fetchPii(api) {
1620
+ const dto = await api.send({
1621
+ method: "GET",
1622
+ url: "/v1/pii",
1623
+ attributes: Attributes.protected()
1624
+ });
1625
+ return Pii.fromDto(dto);
1626
+ }
1627
+
1628
+ // src/shared/api/frontline/requirements.ts
1629
+ async function fetchOfferRequirements(api, offerId, clientCreds) {
1630
+ const response = await api.send({
1631
+ method: "GET",
1632
+ url: `/v1/offers/${offerId}/requirements`,
1633
+ attributes: Attributes.concat(
1634
+ Attributes.protected(),
1635
+ Attributes.clientCredentials(clientCreds)
1636
+ )
1637
+ });
1638
+ return Object.fromEntries(
1639
+ Object.entries(response.options).map(([optionId, list]) => [
1640
+ optionId,
1641
+ list.data.map(Requirement.fromDto)
1642
+ ])
1643
+ );
1644
+ }
1645
+ async function fetchRequirementStatuses(api, offerId) {
1646
+ const response = await api.send({
1647
+ method: "GET",
1648
+ url: `/v1/offers/${offerId}/requirements/statuses`,
1649
+ attributes: Attributes.protected()
1650
+ });
1651
+ return RequirementStatusInfo.fromStatusesDto(response);
1652
+ }
1653
+
1654
+ // src/shared/core/requirements/requirements-namespace.ts
1655
+ var RequirementsNamespaceImpl = class {
1656
+ constructor(ctx) {
1657
+ this.ctx = ctx;
1658
+ this.log = internalLogger(ctx.logger, "REQUIREMENTS");
1659
+ }
1660
+ async forOffer(offerId) {
1661
+ return this.log.wrap("forOffer", offerId, async () => {
1662
+ await this.ctx.ensureUserAuthenticated();
1663
+ return fetchOfferRequirements(
1664
+ this.ctx.api,
1665
+ offerId,
1666
+ void 0
1667
+ );
1668
+ });
1669
+ }
1670
+ async statuses(offerId) {
1671
+ return this.log.wrap("statuses", offerId, async () => {
1672
+ await this.ctx.ensureUserAuthenticated();
1673
+ return fetchRequirementStatuses(this.ctx.api, offerId);
1674
+ });
1675
+ }
1676
+ async createKycToken(params) {
1677
+ return this.log.wrap("createKycToken", params, async () => {
1678
+ await this.ctx.ensureUserAuthenticated();
1679
+ return createKycToken(
1680
+ this.ctx.api,
1681
+ params?.levelName,
1682
+ params?.reset
1683
+ );
1684
+ });
1685
+ }
1686
+ async getPii() {
1687
+ return this.log.wrap("getPii", void 0, async () => {
1688
+ await this.ctx.ensureUserAuthenticated();
1689
+ return fetchPii(this.ctx.api);
1690
+ });
1691
+ }
1692
+ async submitDocument(params) {
1693
+ return this.log.wrap("submitDocument", params, async () => {
1694
+ await this.ctx.ensureUserAuthenticated();
1695
+ return submitDocument(
1696
+ this.ctx.api,
1697
+ params.documentType,
1698
+ params.fields
1699
+ );
1700
+ });
1701
+ }
1702
+ };
1703
+
1704
+ // src/shared/types/token-metadata.ts
1705
+ var TokenLogoUrl = (value) => value;
1706
+ var TokenLogo = {
1707
+ /** `baseUrl` is the registry origin; registry URLs are root-relative. */
1708
+ fromDto: (dto, baseUrl) => dto.kind === "VECTOR" ? { kind: "VECTOR", url: resolveLogoUrl(dto.url, baseUrl) } : {
1709
+ kind: "RASTER",
1710
+ original: logoImageFromDto(dto.original, baseUrl),
1711
+ variants: dto.variants.map((v) => logoImageFromDto(v, baseUrl))
1712
+ }
1713
+ };
1714
+ var TokenMetadata = {
1715
+ /** `baseUrl` is the registry origin; registry logo URLs are root-relative. */
1716
+ fromDto: (dto, baseUrl) => {
1717
+ assertSupportedSchemaVersion(dto.schema_version);
1718
+ return {
1719
+ identifier: {
1720
+ chain: EthereumChain(dto.chain),
1721
+ address: EvmContractAddress(dto.address)
1722
+ },
1723
+ name: dto.name,
1724
+ symbol: AssetSymbol(dto.symbol),
1725
+ decimals: AssetDecimals(dto.decimals),
1726
+ logo: TokenLogo.fromDto(dto.logo, baseUrl),
1727
+ logoDark: dto.logo_dark === void 0 ? null : TokenLogo.fromDto(dto.logo_dark, baseUrl)
1728
+ };
1729
+ },
1730
+ /**
1731
+ * Maps the complete registry snapshot to every token it lists across the
1732
+ * chains this SDK models, skipping native coins and chains outside
1733
+ * {@link EthereumChain} (e.g. Solana) rather than failing on them — the
1734
+ * registry may serve chains ahead of the SDK's type surface.
1735
+ */
1736
+ fromRegistryDto: (dto, baseUrl) => {
1737
+ assertSupportedSchemaVersion(dto.schema_version);
1738
+ return dto.chains.flatMap((chainDto) => {
1739
+ let chain;
1740
+ try {
1741
+ chain = EthereumChain(chainDto.chain);
1742
+ } catch {
1743
+ return [];
1744
+ }
1745
+ return tokensOfChain(chain, chainDto.assets, baseUrl);
1746
+ });
1747
+ },
1748
+ /**
1749
+ * Maps a chain snapshot to the tokens it lists, skipping the chain's native
1750
+ * coin (`kind: 'COIN'`, no contract address).
1751
+ */
1752
+ fromChainAssetsDto: (dto, baseUrl) => {
1753
+ assertSupportedSchemaVersion(dto.schema_version);
1754
+ return tokensOfChain(EthereumChain(dto.chain), dto.assets, baseUrl);
1755
+ }
1756
+ };
1757
+ function tokensOfChain(chain, assets, baseUrl) {
1758
+ return assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
1759
+ identifier: {
1760
+ chain,
1761
+ // The filter above cannot narrow `address` for the type checker.
1762
+ address: EvmContractAddress(asset.address)
1763
+ },
1764
+ name: asset.name,
1765
+ symbol: AssetSymbol(asset.symbol),
1766
+ decimals: AssetDecimals(asset.decimals),
1767
+ logo: TokenLogo.fromDto(asset.logo, baseUrl),
1768
+ logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
1769
+ }));
1770
+ }
1771
+ function assertSupportedSchemaVersion(version) {
1772
+ if (version !== 1) {
1773
+ throw new ValidationError(
1774
+ `Unsupported token registry schema_version: ${version}`
1775
+ );
1776
+ }
1777
+ }
1778
+ var logoImageFromDto = (dto, baseUrl) => ({
1779
+ url: resolveLogoUrl(dto.url, baseUrl),
1780
+ width: dto.width,
1781
+ height: dto.height
1782
+ });
1783
+ var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
1784
+ url.startsWith("http") ? url : `${baseUrl.replace(/\/$/, "")}${url}`
1785
+ );
1786
+
1787
+ // src/shared/api/nabu/tokens.ts
1788
+ import { getAddress } from "viem";
1789
+
1790
+ // src/shared/api/frontline/config.ts
1791
+ var PUBLIC_API_BASE_URL = "https://api.coinlist.co";
1792
+ var HEADER_API_VERSION = "X-API-Version";
1793
+ var HEADER_USER_AGENT = "User-Agent";
1794
+ var HEADER_IDEMPOTENCY_KEY = "Idempotency-Key";
1795
+ var API_VERSION = "2025-10-17";
1796
+ var COINLIST_BASE_URL = "https://coinlist.co";
1797
+ var OAUTH_PAGE_PATH = "/oauth/authorize";
1798
+ var SUPPORT_NEW_TICKET_URL = "https://support.coinlist.co/support/tickets/new";
1799
+ var VERIFY_IDENTITY_PATH = "/verify-identity";
1800
+ var VERIFY_IDENTITY_ACCREDITATION_PATH = "/verify-identity/accreditation_full";
1801
+ var WALLET_PATH = "/wallet";
1802
+
1803
+ // src/shared/api/http-client.ts
1804
+ var HttpClient = class {
1805
+ constructor(config, middleware = {}, logger = null, options = {}) {
1806
+ this.config = config;
1807
+ this.middleware = middleware;
1808
+ this.log = internalLogger(logger, "HTTP");
1809
+ this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
1810
+ }
1811
+ async send(request) {
1812
+ return this.runRequestWithAfterMiddleware(request);
1813
+ }
1814
+ /**
1815
+ * Runs beforeRequest, executeRequest, then the full afterRequest middleware
1816
+ * chain. Used by send() and by the retry() callback so that when a
1817
+ * middleware calls retry(), the retried response also goes through all
1818
+ * afterRequest middleware (e.g. session renewal, retry). Middleware
1819
+ * must use request.attributes.retryAttempt (or similar) to avoid infinite
1820
+ * recursion when they trigger retries.
1821
+ */
1822
+ async runRequestWithAfterMiddleware(request) {
1823
+ const preparedRequest = await this.runBeforeRequestMiddleware(
1824
+ this.withClientDefaults(request)
1825
+ );
1826
+ let response = await this.executeRequest(preparedRequest);
1827
+ for (const middleware of this.middleware.afterRequest ?? []) {
1828
+ response = await middleware({
1829
+ request: preparedRequest,
1830
+ response,
1831
+ retry: (nextRequest = preparedRequest) => this.runRequestWithAfterMiddleware(nextRequest)
1832
+ });
1833
+ }
1834
+ return response;
1835
+ }
1836
+ withClientDefaults(request) {
1837
+ const url = this.resolveUrl(request.url);
1838
+ const headers = {
1839
+ ...request.headers ?? {},
1840
+ ...this.config.xApiVersion !== void 0 ? { [HEADER_API_VERSION]: this.config.xApiVersion } : {}
1841
+ };
1842
+ return {
1843
+ ...request,
1844
+ url,
1845
+ headers,
1846
+ // Only when absent: a retry or a post-renewal re-send arrives with the
1847
+ // first attempt's id already on it, and keeping it is the whole point.
1848
+ attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
1849
+ request.attributes ?? Attributes.empty,
1850
+ Attributes.requestId(this.makeRequestId())
1851
+ ) : request.attributes
1852
+ };
1853
+ }
1854
+ /**
1855
+ * Resolves a request URL against the client's baseUrl.
1856
+ *
1857
+ * @internal Public only for testing. Do not use in application code; use
1858
+ * {@link HttpClient.send} with a path and the client will resolve the URL.
1859
+ */
1860
+ resolveUrl(url) {
1861
+ if (url.startsWith("http://") || url.startsWith("https://")) {
1862
+ return url;
1863
+ }
1864
+ const base = this.config.baseUrl.replace(/\/$/, "");
1865
+ const path = url.startsWith("/") ? url : `/${url}`;
1866
+ return base + path;
1867
+ }
1868
+ async runBeforeRequestMiddleware(initialRequest) {
1869
+ let request = initialRequest;
1870
+ for (const middleware of this.middleware.beforeRequest ?? []) {
1871
+ request = await middleware(request);
1872
+ }
1873
+ return request;
1874
+ }
1875
+ /**
1876
+ * One physical attempt, logged as one line.
1877
+ *
1878
+ * A non-2xx is a `warn` rather than an `error` because the wire does not
1879
+ * know whether it is a failure: the retry middleware may turn a 503 into a
1880
+ * success, and the token registry reads a 404 as "not listed". The namespace
1881
+ * above decides, and logs the `error` when it does.
1882
+ */
1883
+ async executeRequest(request) {
1884
+ const requestId2 = Attributes.getRequestId(request.attributes);
1885
+ const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
1886
+ const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
1887
+ const startedAt = Date.now();
1888
+ log.debug(() => ({
1889
+ msg: "request sent",
1890
+ fields: describeRequestUnredacted(request)
1891
+ }));
1892
+ try {
1893
+ const response = await makeRequest(request);
1894
+ const elapsed = Date.now() - startedAt;
1895
+ const outcome = () => ({
1896
+ msg: "request completed",
1897
+ fields: {
1898
+ ...identifyRequest(request),
1899
+ "http.response.status_code": response.status,
1900
+ duration_ms: elapsed,
1901
+ attempt
1902
+ }
1903
+ });
1904
+ if (response.status >= 200 && response.status < 300) {
1905
+ log.info(outcome);
1906
+ } else {
1907
+ log.warn(outcome);
1908
+ }
1909
+ log.debug(() => ({
1910
+ msg: "response received",
1911
+ fields: { body: response.body }
1912
+ }));
1913
+ return requestId2 === null ? response : { ...response, requestId: requestId2 };
1914
+ } catch (error) {
1915
+ const elapsed = Date.now() - startedAt;
1916
+ log.warning(
1917
+ () => ({
1918
+ msg: "request threw",
1919
+ fields: {
1920
+ ...identifyRequest(request),
1921
+ duration_ms: elapsed,
1922
+ attempt
1923
+ }
1924
+ }),
1925
+ error
1926
+ );
1927
+ throw error;
1928
+ }
1929
+ }
1930
+ };
1931
+ function identifyRequest(request) {
1932
+ const { host, path } = splitUrl(request.url);
1933
+ return {
1934
+ "http.request.method": request.method,
1935
+ "server.address": host,
1936
+ "url.path": path
1937
+ };
1938
+ }
1939
+ function splitUrl(url) {
1940
+ try {
1941
+ const parsed = new URL(url);
1942
+ return { host: parsed.host, path: parsed.pathname };
1943
+ } catch (_) {
1944
+ return { host: null, path: url };
1945
+ }
1946
+ }
1947
+ function defaultMakeRequestId() {
1948
+ return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
1949
+ }
1950
+ function describeRequestUnredacted(request) {
1951
+ return {
1952
+ "http.request.method": request.method,
1953
+ "url.full": buildUrlWithQueryParams(request.url, request.queryParams),
1954
+ headers: request.headers,
1955
+ ...request.method === "POST" ? { body: request.body } : {}
1956
+ };
1957
+ }
1958
+
1959
+ // src/shared/api/nabu/tokens.ts
1960
+ function createNabuApiClient(baseUrl, logger = null) {
1961
+ return new HttpClient({ baseUrl }, {}, logger);
1962
+ }
1963
+ async function fetchTokenMetadata(client, token) {
1964
+ const address = checksummed(token.address);
1965
+ let response;
1966
+ try {
1967
+ response = await client.send({
1968
+ method: "GET",
1969
+ url: `/${token.chain}/token/${address}`
1970
+ });
1971
+ } catch (error) {
1972
+ if (isRegistryHtmlFallback(error)) {
1973
+ return null;
1974
+ }
1975
+ throw error;
1976
+ }
1977
+ if (response.status === 404) {
1978
+ return null;
1979
+ }
1980
+ assertOk(response);
1981
+ if (response.body === null) {
1982
+ throw new ValidationError(
1983
+ `Token registry returned an empty body for token "${address}" on "${token.chain}"`
1984
+ );
1985
+ }
1986
+ return TokenMetadata.fromDto(response.body, client.config.baseUrl);
1987
+ }
1988
+ async function fetchTokensMetadata(client, chain) {
1989
+ let response;
1990
+ try {
1991
+ response = await client.send({
1992
+ method: "GET",
1993
+ url: `/${chain}/assets.json`
1994
+ });
1995
+ } catch (error) {
1996
+ if (isRegistryHtmlFallback(error)) {
1997
+ throw new ValidationError(
1998
+ `Token registry returned non-JSON for the "${chain}" snapshot`
1999
+ );
2000
+ }
2001
+ throw error;
2002
+ }
2003
+ assertOk(response);
2004
+ if (response.body === null) {
2005
+ throw new ValidationError(
2006
+ `Token registry returned an empty "${chain}" snapshot`
2007
+ );
2008
+ }
2009
+ return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);
2010
+ }
2011
+ async function fetchAllTokensMetadata(client) {
2012
+ let response;
2013
+ try {
2014
+ response = await client.send({
2015
+ method: "GET",
2016
+ url: `/assets.json`
2017
+ });
2018
+ } catch (error) {
2019
+ if (isRegistryHtmlFallback(error)) {
2020
+ throw new ValidationError(
2021
+ "Token registry returned non-JSON for the complete snapshot"
2022
+ );
2023
+ }
2024
+ throw error;
2025
+ }
2026
+ assertOk(response);
2027
+ if (response.body === null) {
2028
+ throw new ValidationError(
2029
+ "Token registry returned an empty complete snapshot"
2030
+ );
2031
+ }
2032
+ return TokenMetadata.fromRegistryDto(response.body, client.config.baseUrl);
2033
+ }
2034
+ function isRegistryHtmlFallback(error) {
2035
+ return error instanceof HttpError && error.response.status >= 200 && error.response.status < 300;
2036
+ }
2037
+ function assertOk(response) {
2038
+ if (response.status < 200 || response.status >= 300) {
2039
+ throw new HttpError(response);
2040
+ }
2041
+ }
2042
+ function checksummed(address) {
2043
+ try {
2044
+ return getAddress(address);
2045
+ } catch (_) {
2046
+ throw new ValidationError(`Invalid EVM contract address: "${address}"`);
2047
+ }
2048
+ }
2049
+
2050
+ // src/shared/core/tokens/tokens-namespace.ts
2051
+ var TokensNamespaceImpl = class {
2052
+ /**
2053
+ * Takes the registry origin rather than a `SharedNamespaceContext`: the
2054
+ * registry is unauthenticated and on its own host, so the frontline sender
2055
+ * and the auth check would both be dead weight here.
2056
+ */
2057
+ constructor(baseUrl, logger = null) {
2058
+ this.api = createNabuApiClient(baseUrl, logger);
2059
+ this.log = internalLogger(logger, "TOKENS");
2060
+ }
2061
+ get(token) {
2062
+ return this.log.wrap(
2063
+ "get",
2064
+ token,
2065
+ () => fetchTokenMetadata(this.api, token)
2066
+ );
2067
+ }
2068
+ list(chain) {
2069
+ return this.log.wrap(
2070
+ "list",
2071
+ chain,
2072
+ () => chain === void 0 ? fetchAllTokensMetadata(this.api) : fetchTokensMetadata(this.api, chain)
2073
+ );
2074
+ }
2075
+ };
2076
+
2077
+ // src/shared/types/offer-option-address.ts
2078
+ var OfferOptionAddressId = (value) => value;
2079
+ var OfferOptionAddress = {
2080
+ /** Maps the API DTO into the SDK offer-option-address domain model. */
2081
+ fromDto: (dto) => ({
2082
+ id: OfferOptionAddressId(dto.id),
2083
+ offerOptionId: OfferOptionId(dto.offer_option_id),
2084
+ address: EvmWalletAddress(dto.address),
2085
+ protocol: dto.protocol,
2086
+ createdAt: new Date(dto.created_at)
2087
+ })
2088
+ };
2089
+ var ConnectExternalWalletParams = {
2090
+ /** Maps connect-wallet params into the API DTO payload. */
2091
+ toDto: (params) => ({
2092
+ offer_option_id: params.offerOptionId,
2093
+ wallet_address: params.walletAddress,
2094
+ chain: params.chain,
2095
+ signature: params.signature
2096
+ })
2097
+ };
2098
+
2099
+ // src/shared/types/wallet-ownership-challenge.ts
2100
+ var WalletOwnershipChallenge = {
2101
+ /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
2102
+ fromDto: (dto) => ({
2103
+ message: dto.message,
2104
+ expiresAt: new Date(dto.expires_at)
2105
+ })
2106
+ };
2107
+ var CreateWalletOwnershipChallengeParams = {
2108
+ /**
2109
+ * Maps challenge-request params into the API DTO payload. The discriminated
2110
+ * union guarantees SIWE fields are present exactly when `challengeType` is
2111
+ * `siwe`, so the mapping narrows on the discriminant.
2112
+ */
2113
+ toDto: (params) => {
2114
+ switch (params.challengeType) {
2115
+ case "plain":
2116
+ return {
2117
+ wallet_address: params.walletAddress,
2118
+ chain: params.chain,
2119
+ challenge_type: "plain"
2120
+ };
2121
+ case "siwe":
2122
+ return {
2123
+ wallet_address: params.walletAddress,
2124
+ chain: params.chain,
2125
+ challenge_type: "siwe",
2126
+ domain: params.domain,
2127
+ uri: params.uri,
2128
+ statement: params.statement
2129
+ };
2130
+ default: {
2131
+ const _exhaustive = params;
2132
+ return _exhaustive;
2133
+ }
2134
+ }
2135
+ }
2136
+ };
2137
+
2138
+ // src/shared/api/frontline/wallet-connect.ts
2139
+ async function createWalletOwnershipChallenge(api, params) {
2140
+ const dto = await api.send({
2141
+ method: "POST",
2142
+ url: "/v1/wallet-ownership",
2143
+ body: CreateWalletOwnershipChallengeParams.toDto(params),
2144
+ attributes: Attributes.protected()
2145
+ });
2146
+ return WalletOwnershipChallenge.fromDto(dto);
2147
+ }
2148
+ async function connectExternalWallet(api, params) {
2149
+ const dto = await api.send({
2150
+ method: "POST",
2151
+ url: `/v1/offers/${params.offerId}/addresses`,
2152
+ body: ConnectExternalWalletParams.toDto(params),
2153
+ attributes: Attributes.protected()
2154
+ });
2155
+ return OfferOptionAddress.fromDto(dto);
2156
+ }
2157
+ async function listOptionAddresses(api, offerId, offerOptionId) {
2158
+ const { data } = await api.send({
2159
+ method: "GET",
2160
+ url: `/v1/offers/${offerId}/addresses`,
2161
+ queryParams: { offer_option_id: offerOptionId },
2162
+ attributes: Attributes.protected()
2163
+ });
2164
+ return data.map(OfferOptionAddress.fromDto);
2165
+ }
2166
+ async function removeOptionAddress(api, offerId, addressId) {
2167
+ const dto = await api.send({
2168
+ method: "DELETE",
2169
+ url: `/v1/offers/${offerId}/addresses/${addressId}`,
2170
+ attributes: Attributes.protected()
2171
+ });
2172
+ return OfferOptionAddress.fromDto(dto);
2173
+ }
2174
+
2175
+ // src/shared/core/wallets/wallets-namespace.ts
2176
+ var WalletsNamespaceImpl = class {
2177
+ constructor(ctx) {
2178
+ this.ctx = ctx;
2179
+ this.log = internalLogger(ctx.logger, "WALLETS");
2180
+ }
2181
+ async createOwnershipChallenge(params) {
2182
+ return this.log.wrap("createOwnershipChallenge", params, async () => {
2183
+ await this.ctx.ensureUserAuthenticated();
2184
+ return createWalletOwnershipChallenge(
2185
+ this.ctx.api,
2186
+ params
2187
+ );
2188
+ });
2189
+ }
2190
+ async connectExternal(params) {
2191
+ return this.log.wrap("connectExternal", params, async () => {
2192
+ await this.ctx.ensureUserAuthenticated();
2193
+ return connectExternalWallet(this.ctx.api, params);
2194
+ });
2195
+ }
2196
+ async list(params) {
2197
+ return this.log.wrap("list", params, async () => {
2198
+ await this.ctx.ensureUserAuthenticated();
2199
+ return listOptionAddresses(
2200
+ this.ctx.api,
2201
+ params.offerId,
2202
+ params.offerOptionId
2203
+ );
2204
+ });
2205
+ }
2206
+ async remove(params) {
2207
+ return this.log.wrap("remove", params, async () => {
2208
+ await this.ctx.ensureUserAuthenticated();
2209
+ return removeOptionAddress(
2210
+ this.ctx.api,
2211
+ params.offerId,
2212
+ params.addressId
2213
+ );
2214
+ });
2215
+ }
2216
+ };
2217
+
2218
+ // src/shared/types/oauth-session.ts
2219
+ var ClientCredentialsOAuth = (value) => value;
2220
+ var OAuthRefreshToken = (value) => value;
2221
+ var OAuthSession = {
2222
+ fromDto: (dto) => {
2223
+ const expiresAt = new Date(Date.now() + dto.expires_in * 1e3);
2224
+ return {
2225
+ accessToken: {
2226
+ value: dto.access_token,
2227
+ expiresAt
2228
+ },
2229
+ ...dto.refresh_token != null && dto.refresh_token !== "" ? { refreshToken: OAuthRefreshToken(dto.refresh_token) } : void 0
2230
+ };
2231
+ }
2232
+ };
2233
+
2234
+ // src/shared/api/frontline/offers.ts
2235
+ async function fetchOffers(api, clientCreds) {
2236
+ return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
2237
+ }
2238
+ async function fetchOffersPage(api, params, clientCreds) {
2239
+ const queryParams = PaginationParams.toQueryParams(params);
2240
+ const pageDto = await api.send({
2241
+ method: "GET",
2242
+ url: "/v1/offers",
2243
+ queryParams,
2244
+ attributes: Attributes.concat(
2245
+ Attributes.protected(),
2246
+ Attributes.clientCredentials(clientCreds)
2247
+ )
2248
+ });
2249
+ return PaginatedResponse.fromDto(pageDto, Offer.fromDto);
2250
+ }
2251
+ async function fetchOfferDetails(api, id, clientCreds) {
2252
+ const dto = await api.send({
2253
+ method: "GET",
2254
+ url: `/v1/offers/${id}`,
2255
+ attributes: Attributes.concat(
2256
+ Attributes.protected(),
2257
+ Attributes.clientCredentials(clientCreds)
2258
+ )
2259
+ });
2260
+ return OfferDetail.fromDto(dto);
2261
+ }
2262
+
2263
+ export {
2264
+ sha256,
2265
+ arrayBufferToBase64Url,
2266
+ generateSecureRandomBase64Url,
2267
+ getUUIDv4,
2268
+ PUBLIC_API_BASE_URL,
2269
+ HEADER_USER_AGENT,
2270
+ HEADER_IDEMPOTENCY_KEY,
2271
+ API_VERSION,
2272
+ COINLIST_BASE_URL,
2273
+ OAUTH_PAGE_PATH,
2274
+ SUPPORT_NEW_TICKET_URL,
2275
+ VERIFY_IDENTITY_PATH,
2276
+ VERIFY_IDENTITY_ACCREDITATION_PATH,
2277
+ WALLET_PATH,
2278
+ Attributes,
2279
+ HttpError,
2280
+ apiErrorCode,
2281
+ Request,
2282
+ NotImplementedError,
2283
+ NotAuthenticatedError,
2284
+ ValidationError,
2285
+ InvariantError,
2286
+ MathError,
2287
+ describeErrorUnredacted,
2288
+ internalLogger,
2289
+ HttpClient,
2290
+ fetchAllPages,
2291
+ ETHEREUM_CHAINS,
2292
+ EthereumChain,
2293
+ SOLANA_CHAINS,
2294
+ SolanaChain,
2295
+ Chain,
2296
+ EvmWalletAddress,
2297
+ EvmContractAddress,
2298
+ HexEncodedTransactionData,
2299
+ MAX_ASSET_DECIMALS,
2300
+ AssetDecimals,
2301
+ STABLE_DECIMALS,
2302
+ DecimalString,
2303
+ MAX_UINT_256,
2304
+ assertUint256,
2305
+ parseUint256,
2306
+ BlockchainAmount,
2307
+ AssetSymbol,
2308
+ StablecoinSymbol,
2309
+ KnownAssetSymbol,
2310
+ Bps,
2311
+ FormattedAmountUi,
2312
+ FormattedPercentUi,
2313
+ TxExplorerUrl,
2314
+ ShortenedWalletAddress,
2315
+ FormattedAmountAssetUi,
2316
+ AssetIconUrl,
2317
+ getChainId,
2318
+ chainFromId,
2319
+ getNetworkName,
2320
+ txExplorerUrl,
2321
+ SwapAuthorization,
2322
+ SwapPreview,
2323
+ SwapStatus,
2324
+ TokenAllowance,
2325
+ TokenBalance,
2326
+ AllowWalletResponse,
2327
+ Erc20NamespaceImpl,
2328
+ shortenAddress,
2329
+ formatAmount,
2330
+ formatRawAmount,
2331
+ formatCompactAmount,
2332
+ formatBpsAsPercent,
2333
+ usdAmount,
2334
+ assetAmount,
2335
+ NA_AMOUNT_ASSET_UI,
2336
+ formattedUsdPrice,
2337
+ blockchainAmountFromRawOrThrow,
2338
+ parseBlockchainAmount,
2339
+ Cursor,
2340
+ PaginatedResponse,
2341
+ PaginationParams,
2342
+ AssetId,
2343
+ AssetCode,
2344
+ Asset,
2345
+ OfferId,
2346
+ OfferSlug,
2347
+ Offer,
2348
+ OfferToken,
2349
+ OfferOptionId,
2350
+ OfferOptionSlug,
2351
+ OfferDetail,
2352
+ OfferOption,
2353
+ FaqItem,
2354
+ Link,
2355
+ TermItem,
2356
+ Milestone,
2357
+ ParticipationId,
2358
+ Blockchain,
2359
+ WalletAddress,
2360
+ ParticipationsPaginationParams,
2361
+ Participation,
2362
+ CreateParticipationParams,
2363
+ CoinListTokenSaleNamespaceImpl,
2364
+ Ticker,
2365
+ OndoTradingStatus,
2366
+ OndoQuote,
2367
+ OndoBuyTransaction,
2368
+ OndoSellTransaction,
2369
+ OndoNamespaceImpl,
2370
+ SuperstateSwapNamespaceImpl,
2371
+ fetchOffers,
2372
+ fetchOffersPage,
2373
+ fetchOfferDetails,
2374
+ DocumentSubmission,
2375
+ KycToken,
2376
+ Iso2CountryCode,
2377
+ PiiJurisdiction,
2378
+ PiiAddress,
2379
+ Pii,
2380
+ RequirementId,
2381
+ Requirement,
2382
+ RequirementStatusInfo,
2383
+ fetchOfferRequirements,
2384
+ RequirementsNamespaceImpl,
2385
+ TokenLogoUrl,
2386
+ TokenLogo,
2387
+ TokenMetadata,
2388
+ TokensNamespaceImpl,
2389
+ OfferOptionAddressId,
2390
+ OfferOptionAddress,
2391
+ ConnectExternalWalletParams,
2392
+ WalletOwnershipChallenge,
2393
+ CreateWalletOwnershipChallengeParams,
2394
+ WalletsNamespaceImpl,
2395
+ ClientCredentialsOAuth,
2396
+ OAuthRefreshToken,
2397
+ OAuthSession
2398
+ };
2399
+ //# sourceMappingURL=chunk-7CTH4KPU.js.map