@coinlist-co/react 0.11.0 → 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 (34) hide show
  1. package/dist/{chunk-UIIXXLA7.js → chunk-7CTH4KPU.js} +734 -198
  2. package/dist/chunk-7CTH4KPU.js.map +1 -0
  3. package/dist/{chunk-B2HCVPCQ.js → chunk-LSPZETDH.js} +81 -33
  4. package/dist/chunk-LSPZETDH.js.map +1 -0
  5. package/dist/chunk-UZUQALFY.js +279 -0
  6. package/dist/chunk-UZUQALFY.js.map +1 -0
  7. package/dist/client/index.cjs +5415 -2413
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +2439 -1209
  10. package/dist/client/index.d.ts +2439 -1209
  11. package/dist/client/index.js +4457 -2178
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/collections-BBI_XydI.d.cts +116 -0
  14. package/dist/collections-BrX9rRWc.d.ts +116 -0
  15. package/dist/{config-B5mwS_2l.d.cts → config-CMl1bR3F.d.cts} +1183 -150
  16. package/dist/{config-B5mwS_2l.d.ts → config-CMl1bR3F.d.ts} +1183 -150
  17. package/dist/server/index.cjs +1005 -265
  18. package/dist/server/index.cjs.map +1 -1
  19. package/dist/server/index.d.cts +81 -4
  20. package/dist/server/index.d.ts +81 -4
  21. package/dist/server/index.js +120 -51
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/shared/index.cjs +798 -204
  24. package/dist/shared/index.cjs.map +1 -1
  25. package/dist/shared/index.d.cts +98 -16
  26. package/dist/shared/index.d.ts +98 -16
  27. package/dist/shared/index.js +22 -6
  28. package/package.json +3 -2
  29. package/dist/chunk-B2HCVPCQ.js.map +0 -1
  30. package/dist/chunk-KDGNDAHA.js +0 -146
  31. package/dist/chunk-KDGNDAHA.js.map +0 -1
  32. package/dist/chunk-UIIXXLA7.js.map +0 -1
  33. package/dist/collections-BhDkYmzV.d.cts +0 -65
  34. package/dist/collections-CZhHoQHr.d.ts +0 -65
@@ -45,6 +45,7 @@ __export(shared_exports, {
45
45
  Cursor: () => Cursor,
46
46
  DEFAULT_AMOUNT_TO_COMPUTE_PRICE: () => DEFAULT_AMOUNT_TO_COMPUTE_PRICE,
47
47
  DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE: () => DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE,
48
+ DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE: () => DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE,
48
49
  DEFAULT_SLIPPAGE_BPS: () => DEFAULT_SLIPPAGE_BPS,
49
50
  DecimalString: () => DecimalString,
50
51
  DocumentSubmission: () => DocumentSubmission,
@@ -60,12 +61,14 @@ __export(shared_exports, {
60
61
  FormattedPercentUi: () => FormattedPercentUi,
61
62
  HexEncodedTransactionData: () => HexEncodedTransactionData,
62
63
  HttpError: () => HttpError,
64
+ InvariantError: () => InvariantError,
63
65
  Iso2CountryCode: () => Iso2CountryCode,
64
66
  KnownAssetSymbol: () => KnownAssetSymbol,
65
67
  KycToken: () => KycToken,
66
68
  Link: () => Link,
67
69
  MAX_ASSET_DECIMALS: () => MAX_ASSET_DECIMALS,
68
70
  MAX_UINT_256: () => MAX_UINT_256,
71
+ MathError: () => MathError,
69
72
  Milestone: () => Milestone,
70
73
  NA_AMOUNT_ASSET_UI: () => NA_AMOUNT_ASSET_UI,
71
74
  NotAuthenticatedError: () => NotAuthenticatedError,
@@ -74,6 +77,7 @@ __export(shared_exports, {
74
77
  OAuthSession: () => OAuthSession,
75
78
  ONDO_POLL_INTERVAL_MS: () => ONDO_POLL_INTERVAL_MS,
76
79
  ONDO_QUOTE_EXPIRY_THRESHOLD_MS: () => ONDO_QUOTE_EXPIRY_THRESHOLD_MS,
80
+ ONDO_SETTLEMENT_ASSET: () => ONDO_SETTLEMENT_ASSET,
77
81
  ONDO_SUPPORTED_INPUT_ASSETS: () => ONDO_SUPPORTED_INPUT_ASSETS,
78
82
  Offer: () => Offer,
79
83
  OfferDetail: () => OfferDetail,
@@ -86,9 +90,10 @@ __export(shared_exports, {
86
90
  OfferSlug: () => OfferSlug,
87
91
  OfferToken: () => OfferToken,
88
92
  OffersNamespaceImpl: () => OffersNamespaceImpl,
93
+ OndoBuyTransaction: () => OndoBuyTransaction,
89
94
  OndoNamespaceImpl: () => OndoNamespaceImpl,
90
95
  OndoQuote: () => OndoQuote,
91
- OndoSwapTransaction: () => OndoSwapTransaction,
96
+ OndoSellTransaction: () => OndoSellTransaction,
92
97
  OndoTradingStatus: () => OndoTradingStatus,
93
98
  PKCEState: () => PKCEState,
94
99
  PaginatedResponse: () => PaginatedResponse,
@@ -99,6 +104,7 @@ __export(shared_exports, {
99
104
  Pii: () => Pii,
100
105
  PiiAddress: () => PiiAddress,
101
106
  PiiJurisdiction: () => PiiJurisdiction,
107
+ RedactedWalletError: () => RedactedWalletError,
102
108
  RedirectUri: () => RedirectUri,
103
109
  Requirement: () => Requirement,
104
110
  RequirementId: () => RequirementId,
@@ -147,7 +153,8 @@ __export(shared_exports, {
147
153
  assetAmount: () => assetAmount,
148
154
  blockchainAmountFromRawOrThrow: () => blockchainAmountFromRawOrThrow,
149
155
  chainFromId: () => chainFromId,
150
- computeOndoPrice: () => computeOndoPrice,
156
+ computeOndoBuyPrice: () => computeOndoBuyPrice,
157
+ computeOndoSellPrice: () => computeOndoSellPrice,
151
158
  computePrice: () => computePrice,
152
159
  computeSlip: () => computeSlip,
153
160
  decodeSwappedOutputAmount: () => decodeSwappedOutputAmount,
@@ -164,6 +171,7 @@ __export(shared_exports, {
164
171
  isStopped: () => isStopped,
165
172
  ondoSwapContractAddress: () => ondoSwapContractAddress,
166
173
  parseBlockchainAmount: () => parseBlockchainAmount,
174
+ parseUint256: () => parseUint256,
167
175
  shortenAddress: () => shortenAddress,
168
176
  superstateSwapContractAddress: () => superstateSwapContractAddress,
169
177
  txExplorerUrl: () => txExplorerUrl,
@@ -198,6 +206,8 @@ var retryAttempt = (attempt) => ({
198
206
  var renewAttempted = (value) => ({
199
207
  renewAttempted: value
200
208
  });
209
+ var requestId = (id) => ({ requestId: id });
210
+ var getRequestId = (attrs) => attrs?.requestId ?? null;
201
211
  var isProtected = (attrs) => attrs?.protected === true;
202
212
  var needUserAgent = (attrs) => attrs?.userAgent === true;
203
213
  var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
@@ -219,7 +229,9 @@ var Attributes = {
219
229
  renewAttempted,
220
230
  wasRenewAttempted,
221
231
  clientCredentials,
222
- getClientCredentials
232
+ getClientCredentials,
233
+ requestId,
234
+ getRequestId
223
235
  };
224
236
 
225
237
  // src/shared/api/http.ts
@@ -229,6 +241,16 @@ var HttpError = class extends Error {
229
241
  this.name = "HttpError";
230
242
  this.response = response;
231
243
  }
244
+ /**
245
+ * Correlates this failure with the `[HTTP]` log lines for the same request,
246
+ * which carry the method, the URL, the duration and every retry. `null` when
247
+ * the response did not come from an {@link HttpClient}.
248
+ *
249
+ * Worth quoting in a bug report: it is what makes a log excerpt readable.
250
+ */
251
+ get requestId() {
252
+ return this.response.requestId ?? null;
253
+ }
232
254
  };
233
255
  function apiErrorCode(error) {
234
256
  if (!(error instanceof HttpError)) return null;
@@ -419,11 +441,25 @@ var ValidationError = class extends Error {
419
441
  this.name = "ValidationError";
420
442
  }
421
443
  };
444
+ var InvariantError = class extends Error {
445
+ constructor(message) {
446
+ super(message);
447
+ this.name = "InvariantError";
448
+ }
449
+ };
450
+ var MathError = class extends Error {
451
+ constructor(message) {
452
+ super(message);
453
+ this.name = "MathError";
454
+ }
455
+ };
422
456
 
423
457
  // src/shared/types/blockchain/core.ts
424
458
  var ETHEREUM_CHAINS = {
425
459
  ethereum_mainnet: true,
426
- ethereum_sepolia: true
460
+ ethereum_sepolia: true,
461
+ base_mainnet: true,
462
+ base_sepolia: true
427
463
  };
428
464
  var EthereumChain = (value) => {
429
465
  if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {
@@ -466,27 +502,46 @@ var STABLE_DECIMALS = AssetDecimals(6);
466
502
  var DecimalString = (value) => value;
467
503
  var MAX_UINT_256 = 2n ** 256n - 1n;
468
504
  var assertUint256 = (value) => {
469
- if (value < 0n || value > MAX_UINT_256) {
470
- throw new Error(`Value out of uint256 bounds: ${value}`);
471
- }
472
- return value;
505
+ if (isUint256(value)) return value;
506
+ throw new InvariantError(`Value out of uint256 bounds: ${value}`);
507
+ };
508
+ var parseUint256 = (value, label) => {
509
+ if (isUint256(value)) return value;
510
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
473
511
  };
512
+ var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
474
513
  var BlockchainAmount = Object.assign(
475
514
  (value) => value,
476
515
  {
477
516
  add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
478
- sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
517
+ sub: (a, b) => combineAmounts(a, b, (x, y) => x - y),
518
+ mul: multiplyAmounts,
519
+ div: divideAmounts
479
520
  }
480
521
  );
522
+ function multiplyAmounts(a, b) {
523
+ const product = a.raw * b.raw;
524
+ return BlockchainAmount({
525
+ raw: product / 10n ** BigInt(b.decimals),
526
+ decimals: a.decimals
527
+ });
528
+ }
529
+ function divideAmounts(a, b) {
530
+ if (b.raw === 0n) {
531
+ throw new MathError("Cannot divide a BlockchainAmount by zero");
532
+ }
533
+ const scaled = a.raw * 10n ** BigInt(b.decimals);
534
+ return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
535
+ }
481
536
  function combineAmounts(a, b, op) {
482
537
  if (a.decimals !== b.decimals) {
483
- throw new Error(
538
+ throw new InvariantError(
484
539
  `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
485
540
  );
486
541
  }
487
542
  const raw = op(a.raw, b.raw);
488
543
  if (raw < 0n || raw > MAX_UINT_256) {
489
- throw new Error(`BlockchainAmount out of uint256 bounds: ${raw}`);
544
+ throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
490
545
  }
491
546
  return BlockchainAmount({ raw, decimals: a.decimals });
492
547
  }
@@ -512,7 +567,9 @@ var AssetIconUrl = (value) => value;
512
567
  // src/shared/core/blockchain/chain.ts
513
568
  var CHAIN_IDS = {
514
569
  ethereum_mainnet: 1,
515
- ethereum_sepolia: 11155111
570
+ ethereum_sepolia: 11155111,
571
+ base_mainnet: 8453,
572
+ base_sepolia: 84532
516
573
  };
517
574
  function getChainId(chain) {
518
575
  return CHAIN_IDS[chain];
@@ -531,6 +588,10 @@ function getNetworkName(chain) {
531
588
  return "Ethereum";
532
589
  case "ethereum_sepolia":
533
590
  return "Ethereum Sepolia";
591
+ case "base_mainnet":
592
+ return "Base";
593
+ case "base_sepolia":
594
+ return "Base Sepolia";
534
595
  default: {
535
596
  const _exhaustive = chain;
536
597
  return _exhaustive;
@@ -546,6 +607,10 @@ function explorerBaseUrl(chain) {
546
607
  return "https://etherscan.io";
547
608
  case "ethereum_sepolia":
548
609
  return "https://sepolia.etherscan.io";
610
+ case "base_mainnet":
611
+ return "https://basescan.org";
612
+ case "base_sepolia":
613
+ return "https://sepolia-explorer.base.org";
549
614
  default: {
550
615
  const _exhaustive = chain;
551
616
  return _exhaustive;
@@ -661,25 +726,31 @@ var SwapAuthorization = {
661
726
  };
662
727
  var SwapPreview = {
663
728
  fromDto: (dto) => ({
664
- inputAmount: assertUint256(BigInt(dto.pay_input_amount)),
665
- fee: assertUint256(BigInt(dto.fee)),
666
- outputAmount: assertUint256(BigInt(dto.receive_output_amount))
729
+ inputAmount: parseUint256(
730
+ BigInt(dto.pay_input_amount),
731
+ "SwapPreview.pay_input_amount"
732
+ ),
733
+ fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
734
+ outputAmount: parseUint256(
735
+ BigInt(dto.receive_output_amount),
736
+ "SwapPreview.receive_output_amount"
737
+ )
667
738
  })
668
739
  };
669
740
  var SwapStatus = {
670
741
  fromDto: (dto) => ({
671
- stopped: assertUint256(BigInt(dto.stopped)),
672
- swapLevel: assertUint256(BigInt(dto.swap_level))
742
+ stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
743
+ swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
673
744
  })
674
745
  };
675
746
  var TokenAllowance = {
676
747
  fromDto: (dto) => ({
677
- allowance: assertUint256(BigInt(dto.allowance))
748
+ allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
678
749
  })
679
750
  };
680
751
  var TokenBalance = {
681
752
  fromDto: (dto) => ({
682
- balance: assertUint256(BigInt(dto.balance))
753
+ balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
683
754
  })
684
755
  };
685
756
  var AllowWalletResponse = {
@@ -804,18 +875,172 @@ function toErc20Asset(dto) {
804
875
  };
805
876
  }
806
877
 
878
+ // src/shared/core/observability/log-cause.ts
879
+ function classifyLogCause(error) {
880
+ if (error instanceof HttpError) {
881
+ return httpCause(error);
882
+ }
883
+ if (error instanceof ValidationError) {
884
+ return { type: "validation", message: error.message };
885
+ }
886
+ if (error instanceof InvariantError) {
887
+ return { type: "invariant", message: error.message };
888
+ }
889
+ if (error instanceof MathError) {
890
+ return { type: "math", message: error.message };
891
+ }
892
+ if (error instanceof NotAuthenticatedError) {
893
+ return { type: "not-authenticated" };
894
+ }
895
+ if (error instanceof NotImplementedError) {
896
+ return { type: "not-implemented" };
897
+ }
898
+ return { type: "generic-error", name: errorName(error) };
899
+ }
900
+ function describeErrorUnredacted(error) {
901
+ if (error instanceof HttpError) {
902
+ return describeHttpErrorRedacted(error);
903
+ }
904
+ if (error instanceof Error) {
905
+ return `${error.name}: ${error.message}`;
906
+ }
907
+ return `thrown non-error: ${stringifyUnredacted(error)}`;
908
+ }
909
+ function stringifyUnredacted(value) {
910
+ if (value === void 0) return "";
911
+ try {
912
+ return JSON.stringify(
913
+ value,
914
+ (_key, item) => typeof item === "bigint" ? `${item}` : item
915
+ ) ?? String(value);
916
+ } catch (_) {
917
+ return "<unserializable>";
918
+ }
919
+ }
920
+ function describeHttpErrorRedacted(error) {
921
+ const code = apiErrorCode(error);
922
+ const status = error.response.status;
923
+ return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
924
+ }
925
+ function errorName(error) {
926
+ return error instanceof Error ? error.name : `non-error ${typeof error}`;
927
+ }
928
+ function httpCause(error) {
929
+ return {
930
+ type: "http",
931
+ requestId: error.requestId,
932
+ status: error.response.status,
933
+ code: apiErrorCode(error),
934
+ eventId: apiErrorEventId(error)
935
+ };
936
+ }
937
+ function apiErrorEventId(error) {
938
+ const body = error.response.body;
939
+ if (typeof body !== "object" || body === null) return null;
940
+ const eventId = body.event_id;
941
+ return typeof eventId === "string" ? eventId : null;
942
+ }
943
+
944
+ // src/shared/core/observability/internal-logger.ts
945
+ function internalLogger(logger, scope) {
946
+ return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
947
+ }
948
+ var LEVEL_RANK = {
949
+ none: 0,
950
+ error: 1,
951
+ warn: 2,
952
+ info: 3,
953
+ debug: 4
954
+ };
955
+ function scopedLogger(logger, scope, bindings) {
956
+ const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
957
+ const safe = (event) => ({
958
+ msg: event.msg,
959
+ scope,
960
+ bindings,
961
+ fields: event.fields ?? {},
962
+ ...event.cause === void 0 ? {} : { cause: event.cause }
963
+ });
964
+ const unredacted = (event) => ({
965
+ msg: event.msg,
966
+ scope,
967
+ bindings,
968
+ fields: event.fields ?? {}
969
+ });
970
+ const self = {
971
+ child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
972
+ debug: (event) => {
973
+ if (admits("debug")) logger.debug(() => unredacted(event()));
974
+ },
975
+ info: (event) => {
976
+ if (admits("info")) logger.info(() => safe(event()));
977
+ },
978
+ warn: (event) => {
979
+ if (admits("warn")) logger.warn(() => safe(event()));
980
+ },
981
+ error: (event) => {
982
+ if (admits("error")) logger.error(() => safe(event()));
983
+ },
984
+ failure: (event, error) => {
985
+ if (admits("debug"))
986
+ logger.debug(() => unredacted(verbatim(event(), error)));
987
+ if (admits("error")) logger.error(() => safe(classified(event(), error)));
988
+ },
989
+ warning: (event, error) => {
990
+ if (admits("debug"))
991
+ logger.debug(() => unredacted(verbatim(event(), error)));
992
+ if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
993
+ },
994
+ wrap: async (op, params, run) => {
995
+ const opLog = self.child({ op });
996
+ opLog.debug(() => ({ msg: "call", fields: { params } }));
997
+ try {
998
+ return await run();
999
+ } catch (error) {
1000
+ opLog.failure(() => ({ msg: "call failed" }), error);
1001
+ throw error;
1002
+ }
1003
+ }
1004
+ };
1005
+ return self;
1006
+ }
1007
+ function verbatim(event, error) {
1008
+ return {
1009
+ msg: event.msg,
1010
+ fields: { ...event.fields, error: describeErrorUnredacted(error) }
1011
+ };
1012
+ }
1013
+ function classified(event, error) {
1014
+ return { ...event, cause: event.cause ?? classifyLogCause(error) };
1015
+ }
1016
+ var noopInternalLogger = {
1017
+ child: () => noopInternalLogger,
1018
+ debug: () => void 0,
1019
+ info: () => void 0,
1020
+ warn: () => void 0,
1021
+ error: () => void 0,
1022
+ failure: () => void 0,
1023
+ warning: () => void 0,
1024
+ wrap: (_op, _params, run) => run()
1025
+ };
1026
+
807
1027
  // src/shared/core/blockchain/erc20/erc20-namespace.ts
808
1028
  var Erc20NamespaceImpl = class {
809
1029
  constructor(ctx) {
810
1030
  this.ctx = ctx;
1031
+ this.log = internalLogger(ctx.logger, "ERC20");
811
1032
  }
812
1033
  async getAllowance(params) {
813
- await this.ctx.ensureUserAuthenticated();
814
- return getTokenAllowance(this.ctx.api, params);
1034
+ return this.log.wrap("getAllowance", params, async () => {
1035
+ await this.ctx.ensureUserAuthenticated();
1036
+ return getTokenAllowance(this.ctx.api, params);
1037
+ });
815
1038
  }
816
1039
  async getBalance(params) {
817
- await this.ctx.ensureUserAuthenticated();
818
- return getTokenBalance(this.ctx.api, params);
1040
+ return this.log.wrap("getBalance", params, async () => {
1041
+ await this.ctx.ensureUserAuthenticated();
1042
+ return getTokenBalance(this.ctx.api, params);
1043
+ });
819
1044
  }
820
1045
  };
821
1046
 
@@ -989,6 +1214,12 @@ var USDC_ADDRESSES = {
989
1214
  ),
990
1215
  ethereum_sepolia: EvmContractAddress(
991
1216
  "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
1217
+ ),
1218
+ base_mainnet: EvmContractAddress(
1219
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
1220
+ ),
1221
+ base_sepolia: EvmContractAddress(
1222
+ "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
992
1223
  )
993
1224
  };
994
1225
  var USDT_ADDRESSES = {
@@ -997,7 +1228,11 @@ var USDT_ADDRESSES = {
997
1228
  ),
998
1229
  ethereum_sepolia: EvmContractAddress(
999
1230
  "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
1000
- )
1231
+ ),
1232
+ base_mainnet: EvmContractAddress(
1233
+ "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
1234
+ ),
1235
+ base_sepolia: null
1001
1236
  };
1002
1237
  var TOKEN_REGISTRY = {
1003
1238
  erc20: (symbol) => {
@@ -1007,19 +1242,20 @@ var TOKEN_REGISTRY = {
1007
1242
  case "USDT":
1008
1243
  return USDT;
1009
1244
  default:
1010
- throw new Error(`Unknown asset symbol: ${symbol}`);
1245
+ throw new InvariantError(`Unknown asset symbol: ${symbol}`);
1011
1246
  }
1012
1247
  },
1013
- contractAddress: (symbol, chain) => {
1014
- switch (symbol) {
1015
- case "USDC":
1016
- return USDC_ADDRESSES[chain];
1017
- case "USDT":
1018
- return USDT_ADDRESSES[chain];
1019
- default:
1020
- throw new Error(`Unknown asset symbol: ${symbol}`);
1021
- }
1022
- }
1248
+ /**
1249
+ * USDC's contract on `chain`. USDC is deployed on every chain the SDK
1250
+ * models, so the table is total and the answer is never `null`.
1251
+ */
1252
+ usdcAddress: (chain) => USDC_ADDRESSES[chain],
1253
+ /**
1254
+ * USDT's contract on `chain`, or `null` where Tether publishes none —
1255
+ * Base Sepolia today. The honest answer, never a fake address a balance
1256
+ * read would call.
1257
+ */
1258
+ usdtAddress: (chain) => USDT_ADDRESSES[chain]
1023
1259
  };
1024
1260
 
1025
1261
  // src/shared/types/pagination.ts
@@ -1063,15 +1299,30 @@ var Asset = {
1063
1299
  var OfferId = (value) => value;
1064
1300
  var OfferSlug = (value) => value;
1065
1301
  var Offer = {
1302
+ fromDto: (dto) => {
1303
+ if (!Array.isArray(dto.tokens)) {
1304
+ throw new ValidationError(
1305
+ `Offer.tokens: expected an array, got ${typeof dto.tokens}`
1306
+ );
1307
+ }
1308
+ return {
1309
+ id: OfferId(dto.id),
1310
+ slug: OfferSlug(dto.slug),
1311
+ type: dto.type,
1312
+ tagline: dto.tagline,
1313
+ bannerUrl: dto.banner_url,
1314
+ logoUrl: dto.logo_url,
1315
+ startsAt: new Date(dto.starts_at),
1316
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1317
+ tokens: dto.tokens.map(OfferToken.fromDto)
1318
+ };
1319
+ }
1320
+ };
1321
+ var OfferToken = {
1066
1322
  fromDto: (dto) => ({
1067
- id: OfferId(dto.id),
1068
- slug: OfferSlug(dto.slug),
1069
- type: dto.type,
1070
- tagline: dto.tagline,
1071
- bannerUrl: dto.banner_url,
1072
- logoUrl: dto.logo_url,
1073
- startsAt: new Date(dto.starts_at),
1074
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null
1323
+ role: dto.role,
1324
+ chain: Chain(dto.chain),
1325
+ address: EvmContractAddress(dto.address)
1075
1326
  })
1076
1327
  };
1077
1328
 
@@ -1081,25 +1332,39 @@ var OfferOptionSlug = (value) => value;
1081
1332
  var OfferDetail = {
1082
1333
  fromDto: (dto) => {
1083
1334
  if (!Array.isArray(dto.funding_assets)) {
1084
- throw new Error(`funding_assets must be an array`);
1335
+ throw new ValidationError(
1336
+ `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
1337
+ );
1085
1338
  }
1086
1339
  if (!Array.isArray(dto.options)) {
1087
- throw new Error(`options must be an array`);
1340
+ throw new ValidationError(
1341
+ `OfferDetail.options: expected an array, got ${typeof dto.options}`
1342
+ );
1088
1343
  }
1089
1344
  if (!Array.isArray(dto.terms)) {
1090
- throw new Error(`terms must be an array`);
1345
+ throw new ValidationError(
1346
+ `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
1347
+ );
1091
1348
  }
1092
1349
  if (!Array.isArray(dto.links)) {
1093
- throw new Error(`links must be an array`);
1350
+ throw new ValidationError(
1351
+ `OfferDetail.links: expected an array, got ${typeof dto.links}`
1352
+ );
1094
1353
  }
1095
1354
  if (!Array.isArray(dto.faqs)) {
1096
- throw new Error(`faqs must be an array`);
1355
+ throw new ValidationError(
1356
+ `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
1357
+ );
1097
1358
  }
1098
1359
  if (!Array.isArray(dto.milestones)) {
1099
- throw new Error(`milestones must be an array`);
1360
+ throw new ValidationError(
1361
+ `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
1362
+ );
1100
1363
  }
1101
1364
  if (!Array.isArray(dto.tokens)) {
1102
- throw new Error(`tokens must be an array`);
1365
+ throw new ValidationError(
1366
+ `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1367
+ );
1103
1368
  }
1104
1369
  return {
1105
1370
  id: OfferId(dto.id),
@@ -1161,13 +1426,6 @@ var Milestone = {
1161
1426
  status: dto.status
1162
1427
  })
1163
1428
  };
1164
- var OfferToken = {
1165
- fromDto: (dto) => ({
1166
- role: dto.role,
1167
- chain: Chain(dto.chain),
1168
- address: EvmContractAddress(dto.address)
1169
- })
1170
- };
1171
1429
 
1172
1430
  // src/shared/types/providers/coin-list/token-sale.ts
1173
1431
  var ParticipationId = (value) => value;
@@ -1254,29 +1512,38 @@ async function createParticipation(api, params) {
1254
1512
  var CoinListTokenSaleNamespaceImpl = class {
1255
1513
  constructor(ctx) {
1256
1514
  this.ctx = ctx;
1515
+ this.log = internalLogger(ctx.logger, "TOKEN_SALE");
1257
1516
  }
1258
1517
  async list(offerId) {
1259
- await this.ctx.ensureUserAuthenticated();
1260
- return fetchParticipations(this.ctx.api, offerId);
1518
+ return this.log.wrap("list", offerId, async () => {
1519
+ await this.ctx.ensureUserAuthenticated();
1520
+ return fetchParticipations(this.ctx.api, offerId);
1521
+ });
1261
1522
  }
1262
1523
  async listPage(params) {
1263
- await this.ctx.ensureUserAuthenticated();
1264
- return fetchParticipationsPage(this.ctx.api, params);
1524
+ return this.log.wrap("listPage", params, async () => {
1525
+ await this.ctx.ensureUserAuthenticated();
1526
+ return fetchParticipationsPage(this.ctx.api, params);
1527
+ });
1265
1528
  }
1266
1529
  async get(id) {
1267
- await this.ctx.ensureUserAuthenticated();
1268
- return fetchParticipation(this.ctx.api, id);
1530
+ return this.log.wrap("get", id, async () => {
1531
+ await this.ctx.ensureUserAuthenticated();
1532
+ return fetchParticipation(this.ctx.api, id);
1533
+ });
1269
1534
  }
1270
1535
  async createParticipation(params) {
1271
- await this.ctx.ensureUserAuthenticated();
1272
- return createParticipation(this.ctx.api, params);
1536
+ return this.log.wrap("createParticipation", params, async () => {
1537
+ await this.ctx.ensureUserAuthenticated();
1538
+ return createParticipation(this.ctx.api, params);
1539
+ });
1273
1540
  }
1274
1541
  };
1275
1542
 
1276
1543
  // src/shared/core/checkout/ondo/constants.ts
1277
1544
  var ONDO_SWAP_CONTRACT_ADDRESSES = {
1278
1545
  ethereum_sepolia: EvmContractAddress(
1279
- "0xFF9c5Ade32d9B4102469Bd5F3817CB0061b25feC"
1546
+ "0x7014019ed51Edab984a71D30F2707D2dB2316A7A"
1280
1547
  )
1281
1548
  };
1282
1549
  function ondoSwapContractAddress(chain) {
@@ -1285,30 +1552,49 @@ function ondoSwapContractAddress(chain) {
1285
1552
  var ONDO_POLL_INTERVAL_MS = 15e3;
1286
1553
  var ONDO_QUOTE_EXPIRY_THRESHOLD_MS = 5e3;
1287
1554
  var DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString("1000");
1555
+ var ONDO_SETTLEMENT_ASSET = USDC_SYMBOL;
1556
+ var DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE = 1;
1288
1557
  var ONDO_SUPPORTED_INPUT_ASSETS = [
1289
1558
  USDC_SYMBOL
1290
1559
  ];
1291
1560
 
1292
1561
  // src/shared/core/checkout/ondo/math.ts
1293
- function computeOndoPrice(transaction) {
1562
+ function computeOndoBuyPrice(transaction) {
1294
1563
  const { notionalValue, receiveOutputAmount } = transaction;
1295
- if (receiveOutputAmount.raw <= 0n) {
1296
- throw new ValidationError(
1297
- "Ondo price: receiveOutputAmount must be greater than zero"
1298
- );
1564
+ return pricePerShare({
1565
+ usd: notionalValue,
1566
+ shares: receiveOutputAmount
1567
+ });
1568
+ }
1569
+ function computeOndoSellPrice(transaction) {
1570
+ const { expected, spendInputAmount } = transaction;
1571
+ return pricePerShare({
1572
+ usd: grossProceeds(expected),
1573
+ shares: spendInputAmount
1574
+ });
1575
+ }
1576
+ function grossProceeds(expected) {
1577
+ const raw = expected.quantity.raw + expected.fee.raw;
1578
+ if (raw > MAX_UINT_256) {
1579
+ throw new MathError(`Ondo sell proceeds: out of uint256 bounds (${raw})`);
1299
1580
  }
1300
- const scaled = notionalValue.raw * 10n ** BigInt(receiveOutputAmount.decimals);
1301
- const raw = scaled / receiveOutputAmount.raw;
1581
+ return BlockchainAmount.add(expected.quantity, expected.fee);
1582
+ }
1583
+ function pricePerShare({
1584
+ usd,
1585
+ shares
1586
+ }) {
1587
+ const price = BlockchainAmount.div(usd, shares);
1302
1588
  return BlockchainAmount({
1303
- raw: assertPriceFits(raw),
1304
- decimals: notionalValue.decimals
1589
+ raw: assertPriceFits(price.raw),
1590
+ decimals: price.decimals
1305
1591
  });
1306
1592
  }
1307
1593
  function assertPriceFits(raw) {
1308
1594
  try {
1309
1595
  return assertUint256(raw);
1310
1596
  } catch {
1311
- throw new ValidationError(`Ondo price: out of uint256 bounds (${raw})`);
1597
+ throw new MathError(`Ondo price: out of uint256 bounds (${raw})`);
1312
1598
  }
1313
1599
  }
1314
1600
 
@@ -1353,47 +1639,122 @@ var OndoQuote = {
1353
1639
  };
1354
1640
  }
1355
1641
  };
1356
- var OndoSwapTransaction = {
1642
+ var OndoBuyTransaction = {
1357
1643
  fromDto: (dto) => {
1358
- const inputDecimals = AssetDecimals(dto.pay_input_decimals);
1644
+ const spendDecimals = AssetDecimals(dto.spend_input_decimals);
1359
1645
  const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1360
1646
  return {
1361
- tx: {
1362
- to: EvmContractAddress(dto.to),
1363
- data: HexEncodedTransactionData(dto.data)
1364
- },
1365
- expiresAt: parseExpiresAt(dto.expires_at),
1366
- payInputAmount: blockchainAmountFromRawOrThrow({
1367
- label: "pay_input_amount",
1368
- raw: dto.pay_input_amount,
1369
- decimals: inputDecimals
1370
- }),
1647
+ ...parseSwapCore(dto, spendDecimals),
1648
+ side: "buy",
1371
1649
  fee: blockchainAmountFromRawOrThrow({
1372
1650
  label: "fee",
1373
1651
  raw: dto.fee,
1374
- decimals: inputDecimals
1652
+ decimals: spendDecimals
1375
1653
  }),
1376
1654
  notionalValue: blockchainAmountFromRawOrThrow({
1377
1655
  label: "notional_value",
1378
1656
  raw: dto.notional_value,
1379
- decimals: inputDecimals
1657
+ decimals: spendDecimals
1380
1658
  }),
1381
- receiveOutputAmount: parseReceiveOutputAmount(
1382
- dto.receive_output_amount,
1383
- outputDecimals
1384
- )
1659
+ receiveOutputAmount: parsePositiveAmount({
1660
+ label: "receive_output_amount",
1661
+ raw: dto.receive_output_amount,
1662
+ decimals: outputDecimals,
1663
+ // A transaction that yields nothing is not one to sign - the user
1664
+ // would pay the deposit and receive no asset - and frontline refuses
1665
+ // to emit one. A zero here is a changed encoding, not a small order.
1666
+ // Rejecting it at the boundary is also what lets `computeOndoBuyPrice`
1667
+ // divide by it without a fallible result: the failure surfaces as the
1668
+ // data hook's ERROR state rather than as a division during render.
1669
+ reason: "a buy that yields nothing is not fillable"
1670
+ })
1385
1671
  };
1386
1672
  }
1387
1673
  };
1388
- function parseReceiveOutputAmount(raw, decimals) {
1389
- const amount = blockchainAmountFromRawOrThrow({
1390
- label: "receive_output_amount",
1674
+ var OndoSellTransaction = {
1675
+ fromDto: (dto) => {
1676
+ const spendDecimals = AssetDecimals(dto.spend_input_decimals);
1677
+ const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1678
+ const expectedQuantity = parsePositiveAmount({
1679
+ label: "expected_quantity",
1680
+ raw: dto.expected_quantity,
1681
+ decimals: outputDecimals,
1682
+ reason: "a sale that yields nothing is not fillable"
1683
+ });
1684
+ return {
1685
+ ...parseSwapCore(dto, spendDecimals),
1686
+ side: "sell",
1687
+ expected: {
1688
+ quantity: expectedQuantity,
1689
+ fee: blockchainAmountFromRawOrThrow({
1690
+ label: "expected_fee",
1691
+ raw: dto.expected_fee,
1692
+ decimals: outputDecimals
1693
+ })
1694
+ },
1695
+ minimum: {
1696
+ quantity: parseMinimumQuantity(
1697
+ dto.minimum_quantity,
1698
+ outputDecimals,
1699
+ expectedQuantity
1700
+ ),
1701
+ fee: blockchainAmountFromRawOrThrow({
1702
+ label: "minimum_fee",
1703
+ raw: dto.minimum_fee,
1704
+ decimals: outputDecimals
1705
+ })
1706
+ }
1707
+ };
1708
+ }
1709
+ };
1710
+ function parseSwapCore(dto, spendDecimals) {
1711
+ return {
1712
+ tx: {
1713
+ to: EvmContractAddress(dto.to),
1714
+ data: HexEncodedTransactionData(dto.data)
1715
+ },
1716
+ expiresAt: parseExpiresAt(dto.expires_at),
1717
+ spendInputAmount: parsePositiveAmount({
1718
+ label: "spend_input_amount",
1719
+ raw: dto.spend_input_amount,
1720
+ decimals: spendDecimals,
1721
+ // A transaction that takes nothing from the wallet is not one to sign:
1722
+ // it would settle one leg of a trade and skip the other. Frontline
1723
+ // refuses an `amount` of zero whichever way the trade runs, so this is a
1724
+ // changed encoding rather than a small order.
1725
+ //
1726
+ // Guarded on both sides rather than on the sale alone, because which
1727
+ // amount becomes the divisor in the price flips with the direction: a
1728
+ // guard placed by that would be a rule about the arithmetic rather than
1729
+ // about the trade.
1730
+ reason: "a swap that spends nothing is not fillable"
1731
+ })
1732
+ };
1733
+ }
1734
+ function parseMinimumQuantity(raw, decimals, expectedQuantity) {
1735
+ const amount = parsePositiveAmount({
1736
+ label: "minimum_quantity",
1391
1737
  raw,
1392
- decimals
1738
+ decimals,
1739
+ reason: "a floor of zero guarantees nothing"
1393
1740
  });
1741
+ if (amount.raw > expectedQuantity.raw) {
1742
+ throw new ValidationError(
1743
+ `minimum_quantity: must not exceed expected_quantity ("${raw}" > "${expectedQuantity.raw}")`
1744
+ );
1745
+ }
1746
+ return amount;
1747
+ }
1748
+ function parsePositiveAmount({
1749
+ label,
1750
+ raw,
1751
+ decimals,
1752
+ reason
1753
+ }) {
1754
+ const amount = blockchainAmountFromRawOrThrow({ label, raw, decimals });
1394
1755
  if (amount.raw <= 0n) {
1395
1756
  throw new ValidationError(
1396
- `receive_output_amount: must be greater than zero ("${raw}")`
1757
+ `${label}: must be greater than zero ("${raw}") - ${reason}`
1397
1758
  );
1398
1759
  }
1399
1760
  return amount;
@@ -1430,27 +1791,57 @@ async function getOndoQuote(api, params) {
1430
1791
  });
1431
1792
  return OndoQuote.fromDto(dto);
1432
1793
  }
1433
- async function buildOndoSwapTransaction(api, params) {
1794
+ async function buildOndoBuy(api, params) {
1434
1795
  const dto = await api.send({
1435
1796
  method: "POST",
1436
- url: "/v1/ondo/swap/transaction",
1437
- body: {
1438
- symbol: params.symbol,
1439
- chain: params.chain,
1440
- wallet_address: params.walletAddress,
1441
- amount: params.amount.raw.toString()
1442
- },
1797
+ url: "/v1/ondo/swap/buy",
1798
+ body: swapBody(params),
1443
1799
  attributes: Attributes.protected()
1444
1800
  });
1445
- assertFundingScaleAgrees(dto, params);
1446
- return OndoSwapTransaction.fromDto(dto);
1801
+ assertSpendScaleAgrees({
1802
+ published: dto.spend_input_decimals,
1803
+ sized: params.amount,
1804
+ trade: "purchase"
1805
+ });
1806
+ return OndoBuyTransaction.fromDto(dto);
1447
1807
  }
1448
- function assertFundingScaleAgrees(dto, params) {
1449
- if (dto.pay_input_decimals !== params.amount.decimals) {
1450
- throw new ValidationError(
1451
- `pay_input_decimals: the swap was priced in ${dto.pay_input_decimals} decimals but the order was sized in ${params.amount.decimals}`
1452
- );
1453
- }
1808
+ async function buildOndoSell(api, params) {
1809
+ const dto = await api.send({
1810
+ method: "POST",
1811
+ url: "/v1/ondo/swap/sell",
1812
+ body: swapBody(params),
1813
+ attributes: Attributes.protected()
1814
+ });
1815
+ assertSpendScaleAgrees({
1816
+ published: dto.spend_input_decimals,
1817
+ sized: params.amount,
1818
+ trade: "sale",
1819
+ // The two answers come from two chains, so on a testnet they can disagree
1820
+ // for a reason that is neither the caller's nor a corrupt response. Say so,
1821
+ // or a QA run reads as a puzzle rather than a diagnosis.
1822
+ 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"
1823
+ });
1824
+ return OndoSellTransaction.fromDto(dto);
1825
+ }
1826
+ function swapBody(params) {
1827
+ return {
1828
+ symbol: params.symbol,
1829
+ chain: params.chain,
1830
+ wallet_address: params.walletAddress,
1831
+ amount: params.amount.raw.toString()
1832
+ };
1833
+ }
1834
+ function assertSpendScaleAgrees({
1835
+ published,
1836
+ sized,
1837
+ trade,
1838
+ note
1839
+ }) {
1840
+ if (published === sized.decimals) return;
1841
+ const because = note === void 0 ? "" : ` - ${note}`;
1842
+ throw new ValidationError(
1843
+ `spend_input_decimals: the ${trade} was priced in ${published} decimals but the order was sized in ${sized.decimals}${because}`
1844
+ );
1454
1845
  }
1455
1846
  function sizeParam(params) {
1456
1847
  const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
@@ -1475,18 +1866,31 @@ function sizeParam(params) {
1475
1866
  var OndoNamespaceImpl = class {
1476
1867
  constructor(ctx) {
1477
1868
  this.ctx = ctx;
1869
+ this.log = internalLogger(ctx.logger, "ONDO");
1478
1870
  }
1479
1871
  async getTradingStatus(params) {
1480
- await this.ctx.ensureUserAuthenticated();
1481
- return getOndoTradingStatus(this.ctx.api, params);
1872
+ return this.log.wrap("getTradingStatus", params, async () => {
1873
+ await this.ctx.ensureUserAuthenticated();
1874
+ return getOndoTradingStatus(this.ctx.api, params);
1875
+ });
1482
1876
  }
1483
1877
  async getQuote(params) {
1484
- await this.ctx.ensureUserAuthenticated();
1485
- return getOndoQuote(this.ctx.api, params);
1878
+ return this.log.wrap("getQuote", params, async () => {
1879
+ await this.ctx.ensureUserAuthenticated();
1880
+ return getOndoQuote(this.ctx.api, params);
1881
+ });
1486
1882
  }
1487
- async buildSwapTransaction(params) {
1488
- await this.ctx.ensureUserAuthenticated();
1489
- return buildOndoSwapTransaction(this.ctx.api, params);
1883
+ async buildBuyTransaction(params) {
1884
+ return this.log.wrap("buildBuyTransaction", params, async () => {
1885
+ await this.ctx.ensureUserAuthenticated();
1886
+ return buildOndoBuy(this.ctx.api, params);
1887
+ });
1888
+ }
1889
+ async buildSellTransaction(params) {
1890
+ return this.log.wrap("buildSellTransaction", params, async () => {
1891
+ await this.ctx.ensureUserAuthenticated();
1892
+ return buildOndoSell(this.ctx.api, params);
1893
+ });
1490
1894
  }
1491
1895
  };
1492
1896
 
@@ -1800,26 +2204,37 @@ function formattedPricePerShare(quote, locale) {
1800
2204
  var SuperstateSwapNamespaceImpl = class {
1801
2205
  constructor(ctx) {
1802
2206
  this.ctx = ctx;
2207
+ this.log = internalLogger(ctx.logger, "SUPERSTATE");
1803
2208
  }
1804
2209
  async getAuthorization(params) {
1805
- await this.ctx.ensureUserAuthenticated();
1806
- return getSwapAuthorization(this.ctx.api, params);
2210
+ return this.log.wrap("getAuthorization", params, async () => {
2211
+ await this.ctx.ensureUserAuthenticated();
2212
+ return getSwapAuthorization(this.ctx.api, params);
2213
+ });
1807
2214
  }
1808
2215
  async getPreview(params) {
1809
- await this.ctx.ensureUserAuthenticated();
1810
- return getSwapPreview(this.ctx.api, params);
2216
+ return this.log.wrap("getPreview", params, async () => {
2217
+ await this.ctx.ensureUserAuthenticated();
2218
+ return getSwapPreview(this.ctx.api, params);
2219
+ });
1811
2220
  }
1812
2221
  async getStatus(params) {
1813
- await this.ctx.ensureUserAuthenticated();
1814
- return getSwapStatus(this.ctx.api, params);
2222
+ return this.log.wrap("getStatus", params, async () => {
2223
+ await this.ctx.ensureUserAuthenticated();
2224
+ return getSwapStatus(this.ctx.api, params);
2225
+ });
1815
2226
  }
1816
2227
  async getOutputToken(params) {
1817
- await this.ctx.ensureUserAuthenticated();
1818
- return getSwapOutputToken(this.ctx.api, params);
2228
+ return this.log.wrap("getOutputToken", params, async () => {
2229
+ await this.ctx.ensureUserAuthenticated();
2230
+ return getSwapOutputToken(this.ctx.api, params);
2231
+ });
1819
2232
  }
1820
2233
  async allowWallet(params) {
1821
- await this.ctx.ensureUserAuthenticated();
1822
- return allowWallet(this.ctx.api, params);
2234
+ return this.log.wrap("allowWallet", params, async () => {
2235
+ await this.ctx.ensureUserAuthenticated();
2236
+ return allowWallet(this.ctx.api, params);
2237
+ });
1823
2238
  }
1824
2239
  };
1825
2240
 
@@ -1856,18 +2271,25 @@ async function fetchOfferDetails(api, id, clientCreds) {
1856
2271
  var OffersNamespaceImpl = class {
1857
2272
  constructor(ctx) {
1858
2273
  this.ctx = ctx;
2274
+ this.log = internalLogger(ctx.logger, "OFFERS");
1859
2275
  }
1860
2276
  async list() {
1861
- await this.ctx.ensureUserAuthenticated();
1862
- return fetchOffers(this.ctx.api, void 0);
2277
+ return this.log.wrap("list", void 0, async () => {
2278
+ await this.ctx.ensureUserAuthenticated();
2279
+ return fetchOffers(this.ctx.api, void 0);
2280
+ });
1863
2281
  }
1864
2282
  async listPage(params) {
1865
- await this.ctx.ensureUserAuthenticated();
1866
- return fetchOffersPage(this.ctx.api, params, void 0);
2283
+ return this.log.wrap("listPage", params, async () => {
2284
+ await this.ctx.ensureUserAuthenticated();
2285
+ return fetchOffersPage(this.ctx.api, params, void 0);
2286
+ });
1867
2287
  }
1868
2288
  async get(id) {
1869
- await this.ctx.ensureUserAuthenticated();
1870
- return fetchOfferDetails(this.ctx.api, id, void 0);
2289
+ return this.log.wrap("get", id, async () => {
2290
+ await this.ctx.ensureUserAuthenticated();
2291
+ return fetchOfferDetails(this.ctx.api, id, void 0);
2292
+ });
1871
2293
  }
1872
2294
  };
1873
2295
 
@@ -2000,38 +2422,49 @@ async function fetchRequirementStatuses(api, offerId) {
2000
2422
  var RequirementsNamespaceImpl = class {
2001
2423
  constructor(ctx) {
2002
2424
  this.ctx = ctx;
2425
+ this.log = internalLogger(ctx.logger, "REQUIREMENTS");
2003
2426
  }
2004
2427
  async forOffer(offerId) {
2005
- await this.ctx.ensureUserAuthenticated();
2006
- return fetchOfferRequirements(
2007
- this.ctx.api,
2008
- offerId,
2009
- void 0
2010
- );
2428
+ return this.log.wrap("forOffer", offerId, async () => {
2429
+ await this.ctx.ensureUserAuthenticated();
2430
+ return fetchOfferRequirements(
2431
+ this.ctx.api,
2432
+ offerId,
2433
+ void 0
2434
+ );
2435
+ });
2011
2436
  }
2012
2437
  async statuses(offerId) {
2013
- await this.ctx.ensureUserAuthenticated();
2014
- return fetchRequirementStatuses(this.ctx.api, offerId);
2438
+ return this.log.wrap("statuses", offerId, async () => {
2439
+ await this.ctx.ensureUserAuthenticated();
2440
+ return fetchRequirementStatuses(this.ctx.api, offerId);
2441
+ });
2015
2442
  }
2016
2443
  async createKycToken(params) {
2017
- await this.ctx.ensureUserAuthenticated();
2018
- return createKycToken(
2019
- this.ctx.api,
2020
- params?.levelName,
2021
- params?.reset
2022
- );
2444
+ return this.log.wrap("createKycToken", params, async () => {
2445
+ await this.ctx.ensureUserAuthenticated();
2446
+ return createKycToken(
2447
+ this.ctx.api,
2448
+ params?.levelName,
2449
+ params?.reset
2450
+ );
2451
+ });
2023
2452
  }
2024
2453
  async getPii() {
2025
- await this.ctx.ensureUserAuthenticated();
2026
- return fetchPii(this.ctx.api);
2454
+ return this.log.wrap("getPii", void 0, async () => {
2455
+ await this.ctx.ensureUserAuthenticated();
2456
+ return fetchPii(this.ctx.api);
2457
+ });
2027
2458
  }
2028
2459
  async submitDocument(params) {
2029
- await this.ctx.ensureUserAuthenticated();
2030
- return submitDocument(
2031
- this.ctx.api,
2032
- params.documentType,
2033
- params.fields
2034
- );
2460
+ return this.log.wrap("submitDocument", params, async () => {
2461
+ await this.ctx.ensureUserAuthenticated();
2462
+ return submitDocument(
2463
+ this.ctx.api,
2464
+ params.documentType,
2465
+ params.fields
2466
+ );
2467
+ });
2035
2468
  }
2036
2469
  };
2037
2470
 
@@ -2043,9 +2476,11 @@ var HEADER_API_VERSION = "X-API-Version";
2043
2476
 
2044
2477
  // src/shared/api/http-client.ts
2045
2478
  var HttpClient = class {
2046
- constructor(config, middleware = {}) {
2479
+ constructor(config, middleware = {}, logger = null, options = {}) {
2047
2480
  this.config = config;
2048
2481
  this.middleware = middleware;
2482
+ this.log = internalLogger(logger, "HTTP");
2483
+ this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
2049
2484
  }
2050
2485
  async send(request) {
2051
2486
  return this.runRequestWithAfterMiddleware(request);
@@ -2081,7 +2516,13 @@ var HttpClient = class {
2081
2516
  return {
2082
2517
  ...request,
2083
2518
  url,
2084
- headers
2519
+ headers,
2520
+ // Only when absent: a retry or a post-renewal re-send arrives with the
2521
+ // first attempt's id already on it, and keeping it is the whole point.
2522
+ attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
2523
+ request.attributes ?? Attributes.empty,
2524
+ Attributes.requestId(this.makeRequestId())
2525
+ ) : request.attributes
2085
2526
  };
2086
2527
  }
2087
2528
  /**
@@ -2105,10 +2546,89 @@ var HttpClient = class {
2105
2546
  }
2106
2547
  return request;
2107
2548
  }
2108
- executeRequest(request) {
2109
- return makeRequest(request);
2549
+ /**
2550
+ * One physical attempt, logged as one line.
2551
+ *
2552
+ * A non-2xx is a `warn` rather than an `error` because the wire does not
2553
+ * know whether it is a failure: the retry middleware may turn a 503 into a
2554
+ * success, and the token registry reads a 404 as "not listed". The namespace
2555
+ * above decides, and logs the `error` when it does.
2556
+ */
2557
+ async executeRequest(request) {
2558
+ const requestId2 = Attributes.getRequestId(request.attributes);
2559
+ const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
2560
+ const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
2561
+ const startedAt = Date.now();
2562
+ log.debug(() => ({
2563
+ msg: "request sent",
2564
+ fields: describeRequestUnredacted(request)
2565
+ }));
2566
+ try {
2567
+ const response = await makeRequest(request);
2568
+ const elapsed = Date.now() - startedAt;
2569
+ const outcome = () => ({
2570
+ msg: "request completed",
2571
+ fields: {
2572
+ ...identifyRequest(request),
2573
+ "http.response.status_code": response.status,
2574
+ duration_ms: elapsed,
2575
+ attempt
2576
+ }
2577
+ });
2578
+ if (response.status >= 200 && response.status < 300) {
2579
+ log.info(outcome);
2580
+ } else {
2581
+ log.warn(outcome);
2582
+ }
2583
+ log.debug(() => ({
2584
+ msg: "response received",
2585
+ fields: { body: response.body }
2586
+ }));
2587
+ return requestId2 === null ? response : { ...response, requestId: requestId2 };
2588
+ } catch (error) {
2589
+ const elapsed = Date.now() - startedAt;
2590
+ log.warning(
2591
+ () => ({
2592
+ msg: "request threw",
2593
+ fields: {
2594
+ ...identifyRequest(request),
2595
+ duration_ms: elapsed,
2596
+ attempt
2597
+ }
2598
+ }),
2599
+ error
2600
+ );
2601
+ throw error;
2602
+ }
2110
2603
  }
2111
2604
  };
2605
+ function identifyRequest(request) {
2606
+ const { host, path } = splitUrl(request.url);
2607
+ return {
2608
+ "http.request.method": request.method,
2609
+ "server.address": host,
2610
+ "url.path": path
2611
+ };
2612
+ }
2613
+ function splitUrl(url) {
2614
+ try {
2615
+ const parsed = new URL(url);
2616
+ return { host: parsed.host, path: parsed.pathname };
2617
+ } catch (_) {
2618
+ return { host: null, path: url };
2619
+ }
2620
+ }
2621
+ function defaultMakeRequestId() {
2622
+ return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
2623
+ }
2624
+ function describeRequestUnredacted(request) {
2625
+ return {
2626
+ "http.request.method": request.method,
2627
+ "url.full": buildUrlWithQueryParams(request.url, request.queryParams),
2628
+ headers: request.headers,
2629
+ ...request.method === "POST" ? { body: request.body } : {}
2630
+ };
2631
+ }
2112
2632
 
2113
2633
  // src/shared/types/token-metadata.ts
2114
2634
  var TokenLogoUrl = (value) => value;
@@ -2136,27 +2656,47 @@ var TokenMetadata = {
2136
2656
  logoDark: dto.logo_dark === void 0 ? null : TokenLogo.fromDto(dto.logo_dark, baseUrl)
2137
2657
  };
2138
2658
  },
2659
+ /**
2660
+ * Maps the complete registry snapshot to every token it lists across the
2661
+ * chains this SDK models, skipping native coins and chains outside
2662
+ * {@link EthereumChain} (e.g. Solana) rather than failing on them — the
2663
+ * registry may serve chains ahead of the SDK's type surface.
2664
+ */
2665
+ fromRegistryDto: (dto, baseUrl) => {
2666
+ assertSupportedSchemaVersion(dto.schema_version);
2667
+ return dto.chains.flatMap((chainDto) => {
2668
+ let chain;
2669
+ try {
2670
+ chain = EthereumChain(chainDto.chain);
2671
+ } catch {
2672
+ return [];
2673
+ }
2674
+ return tokensOfChain(chain, chainDto.assets, baseUrl);
2675
+ });
2676
+ },
2139
2677
  /**
2140
2678
  * Maps a chain snapshot to the tokens it lists, skipping the chain's native
2141
2679
  * coin (`kind: 'COIN'`, no contract address).
2142
2680
  */
2143
2681
  fromChainAssetsDto: (dto, baseUrl) => {
2144
2682
  assertSupportedSchemaVersion(dto.schema_version);
2145
- const chain = EthereumChain(dto.chain);
2146
- return dto.assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
2147
- identifier: {
2148
- chain,
2149
- // The filter above cannot narrow `address` for the type checker.
2150
- address: EvmContractAddress(asset.address)
2151
- },
2152
- name: asset.name,
2153
- symbol: AssetSymbol(asset.symbol),
2154
- decimals: AssetDecimals(asset.decimals),
2155
- logo: TokenLogo.fromDto(asset.logo, baseUrl),
2156
- logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
2157
- }));
2683
+ return tokensOfChain(EthereumChain(dto.chain), dto.assets, baseUrl);
2158
2684
  }
2159
2685
  };
2686
+ function tokensOfChain(chain, assets, baseUrl) {
2687
+ return assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
2688
+ identifier: {
2689
+ chain,
2690
+ // The filter above cannot narrow `address` for the type checker.
2691
+ address: EvmContractAddress(asset.address)
2692
+ },
2693
+ name: asset.name,
2694
+ symbol: AssetSymbol(asset.symbol),
2695
+ decimals: AssetDecimals(asset.decimals),
2696
+ logo: TokenLogo.fromDto(asset.logo, baseUrl),
2697
+ logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
2698
+ }));
2699
+ }
2160
2700
  function assertSupportedSchemaVersion(version) {
2161
2701
  if (version !== 1) {
2162
2702
  throw new ValidationError(
@@ -2174,8 +2714,8 @@ var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
2174
2714
  );
2175
2715
 
2176
2716
  // src/shared/api/nabu/tokens.ts
2177
- function createNabuApiClient(baseUrl) {
2178
- return new HttpClient({ baseUrl });
2717
+ function createNabuApiClient(baseUrl, logger = null) {
2718
+ return new HttpClient({ baseUrl }, {}, logger);
2179
2719
  }
2180
2720
  async function fetchTokenMetadata(client, token) {
2181
2721
  const address = checksummed(token.address);
@@ -2225,6 +2765,29 @@ async function fetchTokensMetadata(client, chain) {
2225
2765
  }
2226
2766
  return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);
2227
2767
  }
2768
+ async function fetchAllTokensMetadata(client) {
2769
+ let response;
2770
+ try {
2771
+ response = await client.send({
2772
+ method: "GET",
2773
+ url: `/assets.json`
2774
+ });
2775
+ } catch (error) {
2776
+ if (isRegistryHtmlFallback(error)) {
2777
+ throw new ValidationError(
2778
+ "Token registry returned non-JSON for the complete snapshot"
2779
+ );
2780
+ }
2781
+ throw error;
2782
+ }
2783
+ assertOk(response);
2784
+ if (response.body === null) {
2785
+ throw new ValidationError(
2786
+ "Token registry returned an empty complete snapshot"
2787
+ );
2788
+ }
2789
+ return TokenMetadata.fromRegistryDto(response.body, client.config.baseUrl);
2790
+ }
2228
2791
  function isRegistryHtmlFallback(error) {
2229
2792
  return error instanceof HttpError && error.response.status >= 200 && error.response.status < 300;
2230
2793
  }
@@ -2248,14 +2811,23 @@ var TokensNamespaceImpl = class {
2248
2811
  * registry is unauthenticated and on its own host, so the frontline sender
2249
2812
  * and the auth check would both be dead weight here.
2250
2813
  */
2251
- constructor(baseUrl) {
2252
- this.api = createNabuApiClient(baseUrl);
2814
+ constructor(baseUrl, logger = null) {
2815
+ this.api = createNabuApiClient(baseUrl, logger);
2816
+ this.log = internalLogger(logger, "TOKENS");
2253
2817
  }
2254
2818
  get(token) {
2255
- return fetchTokenMetadata(this.api, token);
2819
+ return this.log.wrap(
2820
+ "get",
2821
+ token,
2822
+ () => fetchTokenMetadata(this.api, token)
2823
+ );
2256
2824
  }
2257
2825
  list(chain) {
2258
- return fetchTokensMetadata(this.api, chain);
2826
+ return this.log.wrap(
2827
+ "list",
2828
+ chain,
2829
+ () => chain === void 0 ? fetchAllTokensMetadata(this.api) : fetchTokensMetadata(this.api, chain)
2830
+ );
2259
2831
  }
2260
2832
  };
2261
2833
 
@@ -2361,36 +2933,50 @@ async function removeOptionAddress(api, offerId, addressId) {
2361
2933
  var WalletsNamespaceImpl = class {
2362
2934
  constructor(ctx) {
2363
2935
  this.ctx = ctx;
2936
+ this.log = internalLogger(ctx.logger, "WALLETS");
2364
2937
  }
2365
2938
  async createOwnershipChallenge(params) {
2366
- await this.ctx.ensureUserAuthenticated();
2367
- return createWalletOwnershipChallenge(
2368
- this.ctx.api,
2369
- params
2370
- );
2939
+ return this.log.wrap("createOwnershipChallenge", params, async () => {
2940
+ await this.ctx.ensureUserAuthenticated();
2941
+ return createWalletOwnershipChallenge(
2942
+ this.ctx.api,
2943
+ params
2944
+ );
2945
+ });
2371
2946
  }
2372
2947
  async connectExternal(params) {
2373
- await this.ctx.ensureUserAuthenticated();
2374
- return connectExternalWallet(this.ctx.api, params);
2948
+ return this.log.wrap("connectExternal", params, async () => {
2949
+ await this.ctx.ensureUserAuthenticated();
2950
+ return connectExternalWallet(this.ctx.api, params);
2951
+ });
2375
2952
  }
2376
2953
  async list(params) {
2377
- await this.ctx.ensureUserAuthenticated();
2378
- return listOptionAddresses(
2379
- this.ctx.api,
2380
- params.offerId,
2381
- params.offerOptionId
2382
- );
2954
+ return this.log.wrap("list", params, async () => {
2955
+ await this.ctx.ensureUserAuthenticated();
2956
+ return listOptionAddresses(
2957
+ this.ctx.api,
2958
+ params.offerId,
2959
+ params.offerOptionId
2960
+ );
2961
+ });
2383
2962
  }
2384
2963
  async remove(params) {
2385
- await this.ctx.ensureUserAuthenticated();
2386
- return removeOptionAddress(
2387
- this.ctx.api,
2388
- params.offerId,
2389
- params.addressId
2390
- );
2964
+ return this.log.wrap("remove", params, async () => {
2965
+ await this.ctx.ensureUserAuthenticated();
2966
+ return removeOptionAddress(
2967
+ this.ctx.api,
2968
+ params.offerId,
2969
+ params.addressId
2970
+ );
2971
+ });
2391
2972
  }
2392
2973
  };
2393
2974
 
2975
+ // src/shared/types/blockchain/wallet-error.ts
2976
+ var RedactedWalletError = {
2977
+ fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
2978
+ };
2979
+
2394
2980
  // src/shared/types/oauth-session.ts
2395
2981
  var ClientCredentialsOAuth = (value) => value;
2396
2982
  var OAuthRefreshToken = (value) => value;
@@ -2443,6 +3029,7 @@ var User = {
2443
3029
  Cursor,
2444
3030
  DEFAULT_AMOUNT_TO_COMPUTE_PRICE,
2445
3031
  DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE,
3032
+ DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE,
2446
3033
  DEFAULT_SLIPPAGE_BPS,
2447
3034
  DecimalString,
2448
3035
  DocumentSubmission,
@@ -2458,12 +3045,14 @@ var User = {
2458
3045
  FormattedPercentUi,
2459
3046
  HexEncodedTransactionData,
2460
3047
  HttpError,
3048
+ InvariantError,
2461
3049
  Iso2CountryCode,
2462
3050
  KnownAssetSymbol,
2463
3051
  KycToken,
2464
3052
  Link,
2465
3053
  MAX_ASSET_DECIMALS,
2466
3054
  MAX_UINT_256,
3055
+ MathError,
2467
3056
  Milestone,
2468
3057
  NA_AMOUNT_ASSET_UI,
2469
3058
  NotAuthenticatedError,
@@ -2472,6 +3061,7 @@ var User = {
2472
3061
  OAuthSession,
2473
3062
  ONDO_POLL_INTERVAL_MS,
2474
3063
  ONDO_QUOTE_EXPIRY_THRESHOLD_MS,
3064
+ ONDO_SETTLEMENT_ASSET,
2475
3065
  ONDO_SUPPORTED_INPUT_ASSETS,
2476
3066
  Offer,
2477
3067
  OfferDetail,
@@ -2484,9 +3074,10 @@ var User = {
2484
3074
  OfferSlug,
2485
3075
  OfferToken,
2486
3076
  OffersNamespaceImpl,
3077
+ OndoBuyTransaction,
2487
3078
  OndoNamespaceImpl,
2488
3079
  OndoQuote,
2489
- OndoSwapTransaction,
3080
+ OndoSellTransaction,
2490
3081
  OndoTradingStatus,
2491
3082
  PKCEState,
2492
3083
  PaginatedResponse,
@@ -2497,6 +3088,7 @@ var User = {
2497
3088
  Pii,
2498
3089
  PiiAddress,
2499
3090
  PiiJurisdiction,
3091
+ RedactedWalletError,
2500
3092
  RedirectUri,
2501
3093
  Requirement,
2502
3094
  RequirementId,
@@ -2545,7 +3137,8 @@ var User = {
2545
3137
  assetAmount,
2546
3138
  blockchainAmountFromRawOrThrow,
2547
3139
  chainFromId,
2548
- computeOndoPrice,
3140
+ computeOndoBuyPrice,
3141
+ computeOndoSellPrice,
2549
3142
  computePrice,
2550
3143
  computeSlip,
2551
3144
  decodeSwappedOutputAmount,
@@ -2562,6 +3155,7 @@ var User = {
2562
3155
  isStopped,
2563
3156
  ondoSwapContractAddress,
2564
3157
  parseBlockchainAmount,
3158
+ parseUint256,
2565
3159
  shortenAddress,
2566
3160
  superstateSwapContractAddress,
2567
3161
  txExplorerUrl,