@coinlist-co/react 0.12.1-rc.14ac67e → 0.12.1-rc.73e7e17

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 (33) hide show
  1. package/dist/{chunk-SOMNMOBU.js → chunk-3ZZCK4IT.js} +9 -9
  2. package/dist/chunk-3ZZCK4IT.js.map +1 -0
  3. package/dist/{chunk-3ATIDGVR.js → chunk-D42IQHQZ.js} +661 -638
  4. package/dist/chunk-D42IQHQZ.js.map +1 -0
  5. package/dist/{chunk-2XBPKC4C.js → chunk-ZUVVNZJJ.js} +126 -126
  6. package/dist/chunk-ZUVVNZJJ.js.map +1 -0
  7. package/dist/client/index.cjs +1560 -1405
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +375 -237
  10. package/dist/client/index.d.ts +375 -237
  11. package/dist/client/index.js +850 -723
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/{collections-DVCh4jUp.d.ts → collections-CMoojQ9M.d.ts} +1 -1
  14. package/dist/{collections-DNbBE6Pk.d.cts → collections-koI4cjYa.d.cts} +1 -1
  15. package/dist/{config-DFYAM0GD.d.cts → config-BmK0t-XO.d.cts} +100 -17
  16. package/dist/{config-DFYAM0GD.d.ts → config-BmK0t-XO.d.ts} +100 -17
  17. package/dist/server/index.cjs +259 -238
  18. package/dist/server/index.cjs.map +1 -1
  19. package/dist/server/index.d.cts +4 -4
  20. package/dist/server/index.d.ts +4 -4
  21. package/dist/server/index.js +3 -3
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/{shared → universal}/index.cjs +870 -843
  24. package/dist/universal/index.cjs.map +1 -0
  25. package/dist/{shared → universal}/index.d.cts +557 -557
  26. package/dist/{shared → universal}/index.d.ts +557 -557
  27. package/dist/{shared → universal}/index.js +6 -2
  28. package/package.json +6 -5
  29. package/dist/chunk-2XBPKC4C.js.map +0 -1
  30. package/dist/chunk-3ATIDGVR.js.map +0 -1
  31. package/dist/chunk-SOMNMOBU.js.map +0 -1
  32. package/dist/shared/index.cjs.map +0 -1
  33. /package/dist/{shared → universal}/index.js.map +0 -0
@@ -109,7 +109,9 @@ __export(client_exports, {
109
109
  formatCountdown: () => formatCountdown,
110
110
  formatMonthYear: () => formatMonthYear,
111
111
  formatSaleCardCountdown: () => formatSaleCardCountdown,
112
+ offerAssetIconUrl: () => offerAssetIconUrl,
112
113
  offerIconUrl: () => offerIconUrl,
114
+ offerTokenIdentifier: () => offerTokenIdentifier,
113
115
  ondoLoadErrorReason: () => ondoLoadErrorReason,
114
116
  pinoClientLogger: () => pinoClientLogger,
115
117
  prepareOndoBuy: () => prepareOndoBuy,
@@ -118,6 +120,9 @@ __export(client_exports, {
118
120
  quoteOverAsks: () => quoteOverAsks,
119
121
  stablecoinIconUrl: () => stablecoinIconUrl,
120
122
  submitErc20Approval: () => submitErc20Approval,
123
+ tokenLogoUrl: () => tokenLogoUrl,
124
+ tokenMetadataOf: () => tokenMetadataOf,
125
+ useCheckoutOfferTokenMetadata: () => useCheckoutOfferTokenMetadata,
121
126
  useCoinList: () => useCoinList,
122
127
  useCoinListSignInCardViewModel: () => useCoinListSignInCardViewModel,
123
128
  useCompleteOAuth: () => useCompleteOAuth,
@@ -166,7 +171,7 @@ module.exports = __toCommonJS(client_exports);
166
171
  // src/client/CoinListProvider.tsx
167
172
  var import_react3 = require("react");
168
173
 
169
- // src/shared/core/utils/crypto.ts
174
+ // src/universal/core/shared/utils/crypto.ts
170
175
  async function sha256(data) {
171
176
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
172
177
  const buffer = bytes.buffer.slice(
@@ -227,7 +232,7 @@ function getDeviceId() {
227
232
  return deviceId;
228
233
  }
229
234
 
230
- // src/shared/api/frontline/config.ts
235
+ // src/universal/api/frontline/config.ts
231
236
  var PUBLIC_API_BASE_URL = "https://api.coinlist.co";
232
237
  var HEADER_API_VERSION = "X-API-Version";
233
238
  var HEADER_USER_AGENT = "User-Agent";
@@ -240,7 +245,7 @@ var VERIFY_IDENTITY_PATH = "/verify-identity";
240
245
  var VERIFY_IDENTITY_ACCREDITATION_PATH = "/verify-identity/accreditation_full";
241
246
  var WALLET_PATH = "/wallet";
242
247
 
243
- // src/shared/api/http-attributes.ts
248
+ // src/universal/api/http-attributes.ts
244
249
  var empty = {};
245
250
  var concat = (left, right) => ({
246
251
  ...left,
@@ -319,7 +324,7 @@ function generateUserAgent() {
319
324
  return `${appInfo} (${deviceInfo}; ${devicePlatform}; ${deviceAppId}; ${finalDeviceId})`;
320
325
  }
321
326
 
322
- // src/shared/api/http.ts
327
+ // src/universal/api/http.ts
323
328
  var HttpError = class extends Error {
324
329
  constructor(response) {
325
330
  super(`Request failed with ${response.status} status`);
@@ -443,7 +448,7 @@ var Request = {
443
448
  concatAttributes
444
449
  };
445
450
 
446
- // src/shared/types/errors.ts
451
+ // src/universal/types/errors.ts
447
452
  var NotImplementedError = class extends Error {
448
453
  constructor(message = "Not implemented yet") {
449
454
  super(message);
@@ -475,7 +480,7 @@ var MathError = class extends Error {
475
480
  }
476
481
  };
477
482
 
478
- // src/shared/core/observability/log-cause.ts
483
+ // src/universal/core/shared/observability/log-cause.ts
479
484
  function classifyLogCause(error) {
480
485
  if (error instanceof HttpError) {
481
486
  return httpCause(error);
@@ -541,7 +546,7 @@ function apiErrorEventId(error) {
541
546
  return typeof eventId === "string" ? eventId : null;
542
547
  }
543
548
 
544
- // src/shared/core/observability/internal-logger.ts
549
+ // src/universal/core/shared/observability/internal-logger.ts
545
550
  function internalLogger(logger, scope) {
546
551
  return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
547
552
  }
@@ -624,7 +629,7 @@ var noopInternalLogger = {
624
629
  wrap: (_op, _params, run) => run()
625
630
  };
626
631
 
627
- // src/shared/api/http-client.ts
632
+ // src/universal/api/http-client.ts
628
633
  var HttpClient = class {
629
634
  constructor(config, middleware = {}, logger = null, options = {}) {
630
635
  this.config = config;
@@ -780,7 +785,7 @@ function describeRequestUnredacted(request) {
780
785
  };
781
786
  }
782
787
 
783
- // src/shared/api/middleware/attach-session-middleware.ts
788
+ // src/universal/api/middleware/attach-session-middleware.ts
784
789
  function attachSessionMiddleware(fetchAccessToken) {
785
790
  return async (request) => {
786
791
  if (!Attributes.isProtected(request.attributes)) {
@@ -806,7 +811,7 @@ function attachSessionMiddleware(fetchAccessToken) {
806
811
  };
807
812
  }
808
813
 
809
- // src/shared/api/middleware/idempotency-key.ts
814
+ // src/universal/api/middleware/idempotency-key.ts
810
815
  var idempotencyKeyMiddleware = async (request) => {
811
816
  if (!Attributes.isIdempotent(request.attributes)) {
812
817
  return request;
@@ -824,7 +829,7 @@ var idempotencyKeyMiddleware = async (request) => {
824
829
  };
825
830
  };
826
831
 
827
- // src/shared/api/middleware/request-retry.ts
832
+ // src/universal/api/middleware/request-retry.ts
828
833
  var MAX_ATTEMPTS = 3;
829
834
  var INITIAL_DELAY_MS = 300;
830
835
  var MAX_DELAY_MS = 2e3;
@@ -859,7 +864,7 @@ function defaultDelay(ms) {
859
864
  }
860
865
  var requestRetryMiddleware = createRequestRetryMiddleware();
861
866
 
862
- // src/shared/api/middleware/session-renewal.ts
867
+ // src/universal/api/middleware/session-renewal.ts
863
868
  function renewSessionMiddleware(fetchAccessToken) {
864
869
  return async ({ request, response, retry }) => {
865
870
  if (response.status !== 401) {
@@ -884,7 +889,7 @@ function renewSessionMiddleware(fetchAccessToken) {
884
889
  };
885
890
  }
886
891
 
887
- // src/shared/api/authenticated-api-client.ts
892
+ // src/universal/api/authenticated-api-client.ts
888
893
  var AuthenticatedApiClient = class {
889
894
  constructor(config, fetchAccessToken, additionalBeforeRequest = [], logger = null) {
890
895
  this.httpClient = new HttpClient(
@@ -928,13 +933,13 @@ var ApiClient = class {
928
933
  }
929
934
  };
930
935
 
931
- // src/shared/types/oauth.ts
936
+ // src/universal/types/oauth.ts
932
937
  var AuthorizationCode = (value) => value;
933
938
  var CodeVerifier = (value) => value;
934
939
  var CodeChallenge = (value) => value;
935
940
  var PKCEState = (value) => value;
936
941
 
937
- // src/shared/core/auth/pkce.ts
942
+ // src/universal/core/auth/pkce.ts
938
943
  async function generatePKCEParams(config) {
939
944
  const state = generateSecureRandomBase64Url(32);
940
945
  const codeVerifier = generateSecureRandomBase64Url(32);
@@ -1039,7 +1044,7 @@ var ClientAuthNamespaceImpl = class {
1039
1044
  }
1040
1045
  };
1041
1046
 
1042
- // src/client/core/blockchain/wallet-error.ts
1047
+ // src/client/core/shared/blockchain/wallet-error.ts
1043
1048
  var import_viem = require("viem");
1044
1049
  function classifyWalletError(error, ctx) {
1045
1050
  if (causeOf(error, import_viem.UserRejectedRequestError)) {
@@ -1068,7 +1073,7 @@ function revertReason(error) {
1068
1073
  return error.reason ?? error.data?.errorName ?? error.signature ?? null;
1069
1074
  }
1070
1075
 
1071
- // src/shared/core/blockchain/erc20/abi.ts
1076
+ // src/universal/core/shared/blockchain/erc20/abi.ts
1072
1077
  var ERC20_ABI = [
1073
1078
  {
1074
1079
  type: "function",
@@ -1168,7 +1173,7 @@ var ERC20_ABI = [
1168
1173
  }
1169
1174
  ];
1170
1175
 
1171
- // src/client/core/blockchain/erc20/approval.ts
1176
+ // src/client/core/shared/blockchain/erc20/approval.ts
1172
1177
  async function ensureErc20Allowance({
1173
1178
  erc20,
1174
1179
  chain,
@@ -1266,7 +1271,7 @@ async function submitErc20Approval(args) {
1266
1271
  return { type: "ok", txHash: hash };
1267
1272
  }
1268
1273
 
1269
- // src/shared/api/pagination.ts
1274
+ // src/universal/api/pagination.ts
1270
1275
  async function fetchAllPages(fetchPage, baseParams) {
1271
1276
  const items = [];
1272
1277
  let cursor = null;
@@ -1282,7 +1287,44 @@ async function fetchAllPages(fetchPage, baseParams) {
1282
1287
  return items;
1283
1288
  }
1284
1289
 
1285
- // src/shared/types/blockchain/core.ts
1290
+ // src/universal/types/pagination.ts
1291
+ var Cursor = (value) => value;
1292
+ var PaginatedResponse = {
1293
+ fromDto: (dto, itemMapper) => ({
1294
+ data: dto.data.map(itemMapper),
1295
+ startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
1296
+ startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
1297
+ })
1298
+ };
1299
+ var PaginationParams = {
1300
+ toQueryParams: (params) => {
1301
+ const queryParams = {};
1302
+ if (params.after) {
1303
+ queryParams.starting_after = params.after;
1304
+ }
1305
+ if (params.before) {
1306
+ queryParams.starting_before = params.before;
1307
+ }
1308
+ if (params.limit) {
1309
+ queryParams.limit = params.limit;
1310
+ }
1311
+ return queryParams;
1312
+ }
1313
+ };
1314
+
1315
+ // src/universal/types/asset.ts
1316
+ var AssetId = (value) => value;
1317
+ var AssetCode = (value) => value;
1318
+ var Asset = {
1319
+ fromDto: (dto) => ({
1320
+ id: AssetId(dto.id),
1321
+ code: AssetCode(dto.code),
1322
+ name: dto.name,
1323
+ fractionalDigits: dto.fractional_digits
1324
+ })
1325
+ };
1326
+
1327
+ // src/universal/types/blockchain/core.ts
1286
1328
  var ETHEREUM_CHAINS = {
1287
1329
  ethereum_mainnet: true,
1288
1330
  ethereum_sepolia: true,
@@ -1299,8 +1341,9 @@ var SOLANA_CHAINS = {
1299
1341
  solana_mainnet: true,
1300
1342
  solana_devnet: true
1301
1343
  };
1344
+ var isChain = (value) => Object.keys(ETHEREUM_CHAINS).includes(value) || Object.keys(SOLANA_CHAINS).includes(value);
1302
1345
  var Chain = (value) => {
1303
- if (!Object.keys(ETHEREUM_CHAINS).includes(value) && !Object.keys(SOLANA_CHAINS).includes(value)) {
1346
+ if (!isChain(value)) {
1304
1347
  throw new ValidationError(`Unsupported chain: "${value}"`);
1305
1348
  }
1306
1349
  return value;
@@ -1371,256 +1414,418 @@ var AssetSymbol = (value) => value;
1371
1414
  var StablecoinSymbol = (value) => value;
1372
1415
  var Bps = (value) => value;
1373
1416
 
1374
- // src/shared/core/blockchain/bps.ts
1375
- var BPS_DENOM = Bps(10000n);
1376
- function applyBps(amount, bps) {
1377
- return assertUint256(amount * bps / BPS_DENOM);
1378
- }
1417
+ // src/universal/types/offer.ts
1418
+ var OfferId = (value) => value;
1419
+ var OfferSlug = (value) => value;
1420
+ var Offer = {
1421
+ fromDto: (dto) => {
1422
+ if (!Array.isArray(dto.tokens)) {
1423
+ throw new ValidationError(
1424
+ `Offer.tokens: expected an array, got ${typeof dto.tokens}`
1425
+ );
1426
+ }
1427
+ return {
1428
+ id: OfferId(dto.id),
1429
+ slug: OfferSlug(dto.slug),
1430
+ type: dto.type,
1431
+ tagline: dto.tagline,
1432
+ bannerUrl: dto.banner_url,
1433
+ logoUrl: dto.logo_url,
1434
+ startsAt: new Date(dto.starts_at),
1435
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1436
+ tokens: OfferToken.listFromDto(dto.tokens)
1437
+ };
1438
+ }
1439
+ };
1440
+ var OfferToken = {
1441
+ fromDto: (dto) => ({
1442
+ role: dto.role,
1443
+ chain: Chain(dto.chain),
1444
+ address: EvmContractAddress(dto.address)
1445
+ }),
1446
+ /**
1447
+ * Maps an offer's token list, dropping every token on a chain this SDK does
1448
+ * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
1449
+ * plain `.map` would throw out of `Offer.fromDto` and, through
1450
+ * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
1451
+ * one Base token blanked production's offers list. Dropping costs that
1452
+ * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
1453
+ * so nobody could have looked it up anyway.
1454
+ *
1455
+ * Same shape as `TokenMetadata.fromRegistryDto`.
1456
+ */
1457
+ listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
1458
+ };
1379
1459
 
1380
- // src/shared/types/blockchain/ui.ts
1381
- var FormattedAmountUi = (value) => value;
1382
- var FormattedPercentUi = (value) => value;
1383
- var TxExplorerUrl = (value) => value;
1384
- var ShortenedWalletAddress = (value) => value;
1385
- var FormattedAmountAssetUi = (value) => value;
1386
- var AssetIconUrl = (value) => value;
1460
+ // src/universal/types/trading.ts
1461
+ var Ticker = (value) => value;
1462
+ var Isin = (value) => value;
1387
1463
 
1388
- // src/shared/core/blockchain/chain.ts
1389
- var CHAIN_IDS = {
1390
- ethereum_mainnet: 1,
1391
- ethereum_sepolia: 11155111,
1392
- base_mainnet: 8453,
1393
- base_sepolia: 84532
1464
+ // src/universal/types/offer-detail.ts
1465
+ var OfferOptionId = (value) => value;
1466
+ var OfferOptionSlug = (value) => value;
1467
+ var OfferSwapContract = {
1468
+ fromDto: (dto) => ({
1469
+ chain: Chain(dto.chain),
1470
+ address: EvmContractAddress(dto.address)
1471
+ })
1394
1472
  };
1395
- function chainFromId(chainId) {
1396
- const chains = Object.keys(CHAIN_IDS);
1397
- const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);
1398
- if (!chain) {
1399
- throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
1400
- }
1401
- return chain;
1402
- }
1403
- function getNetworkName(chain) {
1404
- switch (chain) {
1405
- case "ethereum_mainnet":
1406
- return "Ethereum";
1407
- case "ethereum_sepolia":
1408
- return "Ethereum Sepolia";
1409
- case "base_mainnet":
1410
- return "Base";
1411
- case "base_sepolia":
1412
- return "Base Sepolia";
1413
- default: {
1414
- const _exhaustive = chain;
1415
- return _exhaustive;
1473
+ var OfferDetail = {
1474
+ fromDto: (dto) => {
1475
+ if (!Array.isArray(dto.funding_assets)) {
1476
+ throw new ValidationError(
1477
+ `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
1478
+ );
1416
1479
  }
1417
- }
1418
- }
1419
- function txExplorerUrl(chain, txHash) {
1420
- return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);
1421
- }
1422
- function explorerBaseUrl(chain) {
1423
- switch (chain) {
1424
- case "ethereum_mainnet":
1425
- return "https://etherscan.io";
1426
- case "ethereum_sepolia":
1427
- return "https://sepolia.etherscan.io";
1428
- case "base_mainnet":
1429
- return "https://basescan.org";
1430
- case "base_sepolia":
1431
- return "https://sepolia-explorer.base.org";
1432
- default: {
1433
- const _exhaustive = chain;
1434
- return _exhaustive;
1480
+ if (!Array.isArray(dto.options)) {
1481
+ throw new ValidationError(
1482
+ `OfferDetail.options: expected an array, got ${typeof dto.options}`
1483
+ );
1484
+ }
1485
+ if (!Array.isArray(dto.terms)) {
1486
+ throw new ValidationError(
1487
+ `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
1488
+ );
1489
+ }
1490
+ if (!Array.isArray(dto.links)) {
1491
+ throw new ValidationError(
1492
+ `OfferDetail.links: expected an array, got ${typeof dto.links}`
1493
+ );
1494
+ }
1495
+ if (!Array.isArray(dto.faqs)) {
1496
+ throw new ValidationError(
1497
+ `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
1498
+ );
1499
+ }
1500
+ if (!Array.isArray(dto.milestones)) {
1501
+ throw new ValidationError(
1502
+ `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
1503
+ );
1504
+ }
1505
+ if (!Array.isArray(dto.tokens)) {
1506
+ throw new ValidationError(
1507
+ `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1508
+ );
1509
+ }
1510
+ const swapContracts = dto.swap_contracts === void 0 ? [] : dto.swap_contracts;
1511
+ if (!Array.isArray(swapContracts)) {
1512
+ throw new ValidationError(
1513
+ `OfferDetail.swap_contracts: expected an array, got ${typeof swapContracts}`
1514
+ );
1435
1515
  }
1516
+ const isin = notBlankStringOrNull(dto.isin);
1517
+ const ticker = notBlankStringOrNull(dto.ticker);
1518
+ return {
1519
+ id: OfferId(dto.id),
1520
+ slug: OfferSlug(dto.slug),
1521
+ type: dto.type,
1522
+ name: dto.name,
1523
+ asset: Asset.fromDto(dto.asset),
1524
+ fundingAssets: dto.funding_assets.map(Asset.fromDto),
1525
+ tokens: OfferToken.listFromDto(dto.tokens),
1526
+ swapContracts: swapContracts.map(OfferSwapContract.fromDto),
1527
+ about: notBlankStringOrNull(dto.about),
1528
+ tagline: dto.tagline,
1529
+ bannerUrl: dto.banner_url,
1530
+ logoUrl: dto.logo_url,
1531
+ category: dto.category,
1532
+ issuer: notBlankStringOrNull(dto.issuer),
1533
+ isin: isin === null ? null : Isin(isin),
1534
+ ticker: ticker === null ? null : Ticker(ticker),
1535
+ instrumentType: notBlankStringOrNull(dto.instrument_type),
1536
+ listingVenue: notBlankStringOrNull(dto.listing_venue),
1537
+ startsAt: new Date(dto.starts_at),
1538
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1539
+ faqs: dto.faqs.map(FaqItem.fromDto),
1540
+ links: dto.links.map(Link.fromDto),
1541
+ milestones: dto.milestones.map(Milestone.fromDto),
1542
+ options: dto.options.map(OfferOption.fromDto),
1543
+ terms: dto.terms.map(TermItem.fromDto)
1544
+ };
1436
1545
  }
1437
- }
1438
-
1439
- // src/shared/types/providers/superstate/swap.ts
1440
- var SwapAuthorization = {
1546
+ };
1547
+ var OfferOption = {
1441
1548
  fromDto: (dto) => ({
1442
- authorized: dto.authorized
1549
+ id: OfferOptionId(dto.id),
1550
+ slug: OfferOptionSlug(dto.slug),
1551
+ bidIncrement: dto.bid_increment,
1552
+ floorPriceUsd: dto.floor_price_usd,
1553
+ minimumPurchaseUsd: dto.minimum_purchase_usd,
1554
+ priceUsd: dto.price_usd,
1555
+ saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),
1556
+ totalTokenSupply: dto.total_token_supply
1443
1557
  })
1444
1558
  };
1445
- var SwapPreview = {
1559
+ var FaqItem = {
1446
1560
  fromDto: (dto) => ({
1447
- inputAmount: parseUint256(
1448
- BigInt(dto.pay_input_amount),
1449
- "SwapPreview.pay_input_amount"
1450
- ),
1451
- fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
1452
- outputAmount: parseUint256(
1453
- BigInt(dto.receive_output_amount),
1454
- "SwapPreview.receive_output_amount"
1455
- )
1561
+ question: notBlankStringOrNull(dto.question),
1562
+ answer: notBlankStringOrNull(dto.answer)
1456
1563
  })
1457
1564
  };
1458
- var SwapStatus = {
1565
+ var Link = {
1459
1566
  fromDto: (dto) => ({
1460
- stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
1461
- swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
1567
+ label: notBlankStringOrNull(dto.label),
1568
+ url: notBlankStringOrNull(dto.url)
1462
1569
  })
1463
1570
  };
1464
- var TokenAllowance = {
1571
+ var TermItem = {
1465
1572
  fromDto: (dto) => ({
1466
- allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
1573
+ key: notBlankStringOrNull(dto.key),
1574
+ value: notBlankStringOrNull(dto.value)
1467
1575
  })
1468
1576
  };
1469
- var TokenBalance = {
1577
+ var Milestone = {
1470
1578
  fromDto: (dto) => ({
1471
- balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
1579
+ name: notBlankStringOrNull(dto.name),
1580
+ schedule: notBlankStringOrNull(dto.schedule),
1581
+ status: dto.status
1472
1582
  })
1473
1583
  };
1474
- var AllowWalletResponse = {
1475
- fromDto: (dto) => {
1476
- switch (dto.action) {
1477
- case "broadcast_transaction":
1478
- return {
1479
- action: "broadcast_transaction",
1480
- to: EvmContractAddress(dto.to),
1481
- data: HexEncodedTransactionData(dto.data)
1482
- };
1483
- case "none":
1484
- return {
1485
- action: "none",
1486
- alreadyAllowed: dto.already_allowed
1487
- };
1488
- default: {
1489
- const _exhaustive = dto;
1490
- return _exhaustive;
1491
- }
1492
- }
1493
- }
1494
- };
1495
1584
 
1496
- // src/shared/api/frontline/providers/superstate/swap.ts
1497
- async function getSwapAuthorization(api, params) {
1498
- const dto = await api.send({
1499
- method: "GET",
1500
- url: "/v1/wallet/authorized",
1501
- queryParams: {
1502
- chain: params.chain,
1503
- contract_address: params.contractAddress,
1504
- wallet_address: params.walletAddress
1505
- },
1506
- attributes: Attributes.protected()
1507
- });
1508
- return SwapAuthorization.fromDto(dto);
1509
- }
1510
- async function getSwapOutputToken(api, params) {
1511
- const dto = await api.send({
1512
- method: "GET",
1513
- url: "/v1/swap/output-token",
1514
- queryParams: {
1515
- chain: params.chain,
1516
- contract_address: params.contractAddress
1517
- },
1518
- attributes: Attributes.protected()
1519
- });
1520
- return toErc20Asset(dto);
1521
- }
1522
- async function getSwapPreview(api, params) {
1523
- const dto = await api.send({
1524
- method: "GET",
1525
- url: "/v1/swap/preview",
1526
- queryParams: {
1527
- chain: params.chain,
1528
- contract_address: params.contractAddress,
1529
- input_token: params.inputToken,
1530
- amount: params.amount.toString()
1531
- },
1532
- attributes: Attributes.protected()
1533
- });
1534
- return SwapPreview.fromDto(dto);
1535
- }
1536
- async function getSwapStatus(api, params) {
1537
- const dto = await api.send({
1538
- method: "GET",
1539
- url: "/v1/swap/status",
1540
- queryParams: {
1541
- chain: params.chain,
1542
- contract_address: params.contractAddress
1543
- },
1544
- attributes: Attributes.protected()
1545
- });
1546
- return SwapStatus.fromDto(dto);
1585
+ // src/universal/types/providers/coin-list/token-sale.ts
1586
+ var ParticipationId = (value) => value;
1587
+ var Blockchain = (value) => value;
1588
+ var WalletAddress = (value) => value;
1589
+ var ParticipationsPaginationParams = {
1590
+ toQueryParams: (params) => {
1591
+ const queryParams = PaginationParams.toQueryParams(params);
1592
+ if (params.offerId) {
1593
+ queryParams["filters[0][field]"] = "offer_id";
1594
+ queryParams["filters[0][op]"] = "==";
1595
+ queryParams["filters[0][value]"] = params.offerId;
1596
+ }
1597
+ return queryParams;
1598
+ }
1599
+ };
1600
+ var Participation = {
1601
+ /** Maps API DTO shape into the SDK participation domain model. */
1602
+ fromDto: (dto) => {
1603
+ const walletAddress = notBlankStringOrNull(dto.wallet_address);
1604
+ return {
1605
+ id: ParticipationId(dto.id),
1606
+ offerId: OfferId(dto.offer_id),
1607
+ offerOptionId: OfferOptionId(dto.offer_option_id),
1608
+ status: dto.status,
1609
+ amount: dto.amount,
1610
+ displayAmount: dto.amount_string,
1611
+ asset: Asset.fromDto(dto.asset),
1612
+ chain: Blockchain(dto.chain),
1613
+ insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
1614
+ updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
1615
+ walletAddress: walletAddress ? WalletAddress(walletAddress) : null
1616
+ };
1617
+ }
1618
+ };
1619
+ var CreateParticipationParams = {
1620
+ /** Maps participation creation params into API DTO payload. */
1621
+ toDto: (params) => ({
1622
+ offer_id: params.offerId,
1623
+ offer_option_id: params.offerOptionId,
1624
+ chain: params.chain,
1625
+ wallet_address: params.walletAddress,
1626
+ amount: params.amount,
1627
+ asset_id: params.assetId,
1628
+ approval_transaction_hash: params.approvalTransactionHash
1629
+ })
1630
+ };
1631
+
1632
+ // src/universal/api/frontline/providers/coin-list/token-sale.ts
1633
+ async function fetchParticipations(api, offerId) {
1634
+ return fetchAllPages(
1635
+ (params) => fetchParticipationsPage(api, params),
1636
+ { offerId }
1637
+ );
1547
1638
  }
1548
- async function getTokenAllowance(api, params) {
1549
- const dto = await api.send({
1639
+ async function fetchParticipationsPage(api, params) {
1640
+ const pageDto = await api.send({
1550
1641
  method: "GET",
1551
- url: "/v1/token/allowance",
1552
- queryParams: {
1553
- chain: params.chain,
1554
- token_address: params.tokenAddress,
1555
- owner: params.owner,
1556
- spender: params.spender
1557
- },
1642
+ url: "/v1/participations",
1643
+ queryParams: ParticipationsPaginationParams.toQueryParams(params),
1558
1644
  attributes: Attributes.protected()
1559
1645
  });
1560
- return TokenAllowance.fromDto(dto);
1646
+ return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
1561
1647
  }
1562
- async function getTokenBalance(api, params) {
1648
+ async function fetchParticipation(api, id) {
1563
1649
  const dto = await api.send({
1564
1650
  method: "GET",
1565
- url: "/v1/token/balance",
1566
- queryParams: {
1567
- chain: params.chain,
1568
- token_address: params.tokenAddress,
1569
- owner: params.owner
1570
- },
1651
+ url: `/v1/participations/${id}`,
1571
1652
  attributes: Attributes.protected()
1572
1653
  });
1573
- return TokenBalance.fromDto(dto);
1654
+ return Participation.fromDto(dto);
1574
1655
  }
1575
- async function allowWallet(api, params) {
1656
+ async function createParticipation(api, params) {
1576
1657
  const dto = await api.send({
1577
1658
  method: "POST",
1578
- url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
1579
- body: {
1580
- wallet_address: params.walletAddress,
1581
- chain: params.chain,
1582
- signature: params.signature
1583
- },
1659
+ url: "/v1/participations",
1660
+ body: CreateParticipationParams.toDto(params),
1584
1661
  attributes: Attributes.protected()
1585
1662
  });
1586
- return AllowWalletResponse.fromDto(dto);
1587
- }
1588
- function toErc20Asset(dto) {
1589
- return {
1590
- name: dto.name,
1591
- symbol: AssetSymbol(dto.symbol),
1592
- decimals: AssetDecimals(dto.decimals)
1593
- };
1663
+ return Participation.fromDto(dto);
1594
1664
  }
1595
1665
 
1596
- // src/shared/core/blockchain/erc20/erc20-namespace.ts
1597
- var Erc20NamespaceImpl = class {
1666
+ // src/universal/core/checkout/coin-list/token-sale-namespace.ts
1667
+ var CoinListTokenSaleNamespaceImpl = class {
1598
1668
  constructor(ctx) {
1599
1669
  this.ctx = ctx;
1600
- this.log = internalLogger(ctx.logger, "ERC20");
1670
+ this.log = internalLogger(ctx.logger, "TOKEN_SALE");
1601
1671
  }
1602
- async getAllowance(params) {
1603
- return this.log.wrap("getAllowance", params, async () => {
1672
+ async list(offerId) {
1673
+ return this.log.wrap("list", offerId, async () => {
1604
1674
  await this.ctx.ensureUserAuthenticated();
1605
- return getTokenAllowance(this.ctx.api, params);
1675
+ return fetchParticipations(this.ctx.api, offerId);
1606
1676
  });
1607
1677
  }
1608
- async getBalance(params) {
1609
- return this.log.wrap("getBalance", params, async () => {
1678
+ async listPage(params) {
1679
+ return this.log.wrap("listPage", params, async () => {
1610
1680
  await this.ctx.ensureUserAuthenticated();
1611
- return getTokenBalance(this.ctx.api, params);
1681
+ return fetchParticipationsPage(this.ctx.api, params);
1682
+ });
1683
+ }
1684
+ async get(id) {
1685
+ return this.log.wrap("get", id, async () => {
1686
+ await this.ctx.ensureUserAuthenticated();
1687
+ return fetchParticipation(this.ctx.api, id);
1688
+ });
1689
+ }
1690
+ async createParticipation(params) {
1691
+ return this.log.wrap("createParticipation", params, async () => {
1692
+ await this.ctx.ensureUserAuthenticated();
1693
+ return createParticipation(this.ctx.api, params);
1612
1694
  });
1613
1695
  }
1614
1696
  };
1615
1697
 
1616
- // src/shared/core/blockchain/formatters.ts
1617
- var import_viem2 = require("viem");
1618
- function shortenAddress(address) {
1619
- const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
1620
- return ShortenedWalletAddress(short);
1698
+ // src/universal/core/shared/blockchain/token-registry.ts
1699
+ var USDC_SYMBOL = StablecoinSymbol("USDC");
1700
+ var USDC = {
1701
+ name: "USD Coin",
1702
+ symbol: USDC_SYMBOL,
1703
+ decimals: AssetDecimals(6)
1704
+ };
1705
+ var USDT_SYMBOL = StablecoinSymbol("USDT");
1706
+ var USDT = {
1707
+ name: "Tether USD",
1708
+ symbol: USDT_SYMBOL,
1709
+ decimals: AssetDecimals(6)
1710
+ };
1711
+ var USDC_ADDRESSES = {
1712
+ ethereum_mainnet: EvmContractAddress(
1713
+ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
1714
+ ),
1715
+ ethereum_sepolia: EvmContractAddress(
1716
+ "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
1717
+ ),
1718
+ base_mainnet: EvmContractAddress(
1719
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
1720
+ ),
1721
+ base_sepolia: EvmContractAddress(
1722
+ "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
1723
+ )
1724
+ };
1725
+ var USDT_ADDRESSES = {
1726
+ ethereum_mainnet: EvmContractAddress(
1727
+ "0xdac17f958d2ee523a2206206994597c13d831ec7"
1728
+ ),
1729
+ ethereum_sepolia: EvmContractAddress(
1730
+ "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
1731
+ ),
1732
+ base_mainnet: EvmContractAddress(
1733
+ "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
1734
+ ),
1735
+ base_sepolia: null
1736
+ };
1737
+ var TOKEN_REGISTRY = {
1738
+ erc20: (symbol) => {
1739
+ switch (symbol) {
1740
+ case "USDC":
1741
+ return USDC;
1742
+ case "USDT":
1743
+ return USDT;
1744
+ default:
1745
+ throw new InvariantError(`Unknown asset symbol: ${symbol}`);
1746
+ }
1747
+ },
1748
+ /**
1749
+ * USDC's contract on `chain`. USDC is deployed on every chain the SDK
1750
+ * models, so the table is total and the answer is never `null`.
1751
+ */
1752
+ usdcAddress: (chain) => USDC_ADDRESSES[chain],
1753
+ /**
1754
+ * USDT's contract on `chain`, or `null` where Tether publishes none —
1755
+ * Base Sepolia today. The honest answer, never a fake address a balance
1756
+ * read would call.
1757
+ */
1758
+ usdtAddress: (chain) => USDT_ADDRESSES[chain]
1759
+ };
1760
+
1761
+ // src/universal/core/checkout/ondo/constants.ts
1762
+ var ONDO_POLL_INTERVAL_MS = 15e3;
1763
+ var ONDO_QUOTE_EXPIRY_THRESHOLD_MS = 5e3;
1764
+ var DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString("1000");
1765
+ var ONDO_SETTLEMENT_ASSET = USDC_SYMBOL;
1766
+ var DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE = 1;
1767
+ var ONDO_SUPPORTED_INPUT_ASSETS = [
1768
+ USDC_SYMBOL
1769
+ ];
1770
+
1771
+ // src/universal/core/checkout/ondo/math.ts
1772
+ function computeOndoBuyPrice(transaction) {
1773
+ const { notionalValue, receiveOutputAmount } = transaction;
1774
+ return pricePerShare({
1775
+ usd: notionalValue,
1776
+ shares: receiveOutputAmount
1777
+ });
1621
1778
  }
1622
- function formatAmount(amount, locale, options) {
1623
- const decimal = formatRawAmount(amount);
1779
+ function computeOndoSellPrice(transaction) {
1780
+ const { expected, spendInputAmount } = transaction;
1781
+ return pricePerShare({
1782
+ usd: grossProceeds(expected),
1783
+ shares: spendInputAmount
1784
+ });
1785
+ }
1786
+ function grossProceeds(expected) {
1787
+ const raw = expected.quantity.raw + expected.fee.raw;
1788
+ if (raw > MAX_UINT_256) {
1789
+ throw new MathError(`Ondo sell proceeds: out of uint256 bounds (${raw})`);
1790
+ }
1791
+ return BlockchainAmount.add(expected.quantity, expected.fee);
1792
+ }
1793
+ function pricePerShare({
1794
+ usd,
1795
+ shares
1796
+ }) {
1797
+ const price = BlockchainAmount.div(usd, shares);
1798
+ return BlockchainAmount({
1799
+ raw: assertPriceFits(price.raw),
1800
+ decimals: price.decimals
1801
+ });
1802
+ }
1803
+ function assertPriceFits(raw) {
1804
+ try {
1805
+ return assertUint256(raw);
1806
+ } catch {
1807
+ throw new MathError(`Ondo price: out of uint256 bounds (${raw})`);
1808
+ }
1809
+ }
1810
+
1811
+ // src/universal/core/shared/blockchain/formatters.ts
1812
+ var import_viem2 = require("viem");
1813
+
1814
+ // src/universal/types/blockchain/ui.ts
1815
+ var FormattedAmountUi = (value) => value;
1816
+ var FormattedPercentUi = (value) => value;
1817
+ var TxExplorerUrl = (value) => value;
1818
+ var ShortenedWalletAddress = (value) => value;
1819
+ var FormattedAmountAssetUi = (value) => value;
1820
+ var AssetIconUrl = (value) => value;
1821
+
1822
+ // src/universal/core/shared/blockchain/formatters.ts
1823
+ function shortenAddress(address) {
1824
+ const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
1825
+ return ShortenedWalletAddress(short);
1826
+ }
1827
+ function formatAmount(amount, locale, options) {
1828
+ const decimal = formatRawAmount(amount);
1624
1829
  let [integerPart, fractionPart = ""] = decimal.split(".");
1625
1830
  const maxFractionDigits = options?.maxFractionDigits;
1626
1831
  const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
@@ -1700,474 +1905,114 @@ function formattedUsdPrice(amount, locale) {
1700
1905
  );
1701
1906
  }
1702
1907
 
1703
- // src/shared/core/blockchain/math.ts
1704
- var import_viem3 = require("viem");
1705
- function blockchainAmountFromRawOrThrow({
1706
- label,
1707
- raw,
1708
- decimals
1709
- }) {
1710
- const trimmed = raw.trim();
1711
- if (trimmed === "") {
1712
- throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1713
- }
1714
- let value;
1715
- try {
1716
- value = BigInt(trimmed);
1717
- } catch {
1718
- throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1719
- }
1720
- try {
1721
- return BlockchainAmount({ raw: assertUint256(value), decimals });
1722
- } catch {
1723
- throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
1724
- }
1725
- }
1726
- function parseBlockchainAmount(amount, decimals) {
1727
- const trimmed = amount.trim();
1728
- if (trimmed === "") return { valid: false, reason: { type: "empty" } };
1729
- if (trimmed.startsWith("-")) {
1730
- return { valid: false, reason: { type: "negative" } };
1731
- }
1732
- if (/[eE]/.test(trimmed)) {
1733
- return { valid: false, reason: { type: "invalid-format" } };
1734
- }
1735
- if (!/^\d+(\.\d+)?$/.test(trimmed)) {
1736
- return { valid: false, reason: { type: "invalid-format" } };
1737
- }
1738
- const [, fraction = ""] = trimmed.split(".");
1739
- if (fraction.length > decimals) {
1740
- return {
1741
- valid: false,
1742
- reason: { type: "too-many-decimals", maxDecimals: decimals }
1743
- };
1744
- }
1745
- try {
1746
- const raw = (0, import_viem3.parseUnits)(trimmed, decimals);
1747
- if (raw > MAX_UINT_256) {
1748
- return { valid: false, reason: { type: "overflow" } };
1749
- }
1750
- return {
1751
- valid: true,
1752
- amount: BlockchainAmount({ raw, decimals })
1753
- };
1754
- } catch {
1755
- return { valid: false, reason: { type: "invalid-format" } };
1756
- }
1757
- }
1758
-
1759
- // src/shared/core/blockchain/token-registry.ts
1760
- var USDC_SYMBOL = StablecoinSymbol("USDC");
1761
- var USDC = {
1762
- name: "USD Coin",
1763
- symbol: USDC_SYMBOL,
1764
- decimals: AssetDecimals(6)
1765
- };
1766
- var USDT_SYMBOL = StablecoinSymbol("USDT");
1767
- var USDT = {
1768
- name: "Tether USD",
1769
- symbol: USDT_SYMBOL,
1770
- decimals: AssetDecimals(6)
1771
- };
1772
- var USDC_ADDRESSES = {
1773
- ethereum_mainnet: EvmContractAddress(
1774
- "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
1775
- ),
1776
- ethereum_sepolia: EvmContractAddress(
1777
- "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
1778
- ),
1779
- base_mainnet: EvmContractAddress(
1780
- "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
1781
- ),
1782
- base_sepolia: EvmContractAddress(
1783
- "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
1784
- )
1785
- };
1786
- var USDT_ADDRESSES = {
1787
- ethereum_mainnet: EvmContractAddress(
1788
- "0xdac17f958d2ee523a2206206994597c13d831ec7"
1789
- ),
1790
- ethereum_sepolia: EvmContractAddress(
1791
- "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
1792
- ),
1793
- base_mainnet: EvmContractAddress(
1794
- "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
1795
- ),
1796
- base_sepolia: null
1797
- };
1798
- var TOKEN_REGISTRY = {
1799
- erc20: (symbol) => {
1800
- switch (symbol) {
1801
- case "USDC":
1802
- return USDC;
1803
- case "USDT":
1804
- return USDT;
1805
- default:
1806
- throw new InvariantError(`Unknown asset symbol: ${symbol}`);
1807
- }
1808
- },
1809
- /**
1810
- * USDC's contract on `chain`. USDC is deployed on every chain the SDK
1811
- * models, so the table is total and the answer is never `null`.
1812
- */
1813
- usdcAddress: (chain) => USDC_ADDRESSES[chain],
1814
- /**
1815
- * USDT's contract on `chain`, or `null` where Tether publishes none —
1816
- * Base Sepolia today. The honest answer, never a fake address a balance
1817
- * read would call.
1818
- */
1819
- usdtAddress: (chain) => USDT_ADDRESSES[chain]
1820
- };
1821
-
1822
- // src/shared/types/pagination.ts
1823
- var Cursor = (value) => value;
1824
- var PaginatedResponse = {
1825
- fromDto: (dto, itemMapper) => ({
1826
- data: dto.data.map(itemMapper),
1827
- startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
1828
- startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
1829
- })
1830
- };
1831
- var PaginationParams = {
1832
- toQueryParams: (params) => {
1833
- const queryParams = {};
1834
- if (params.after) {
1835
- queryParams.starting_after = params.after;
1836
- }
1837
- if (params.before) {
1838
- queryParams.starting_before = params.before;
1839
- }
1840
- if (params.limit) {
1841
- queryParams.limit = params.limit;
1842
- }
1843
- return queryParams;
1844
- }
1845
- };
1846
-
1847
- // src/shared/types/asset.ts
1848
- var AssetId = (value) => value;
1849
- var AssetCode = (value) => value;
1850
- var Asset = {
1851
- fromDto: (dto) => ({
1852
- id: AssetId(dto.id),
1853
- code: AssetCode(dto.code),
1854
- name: dto.name,
1855
- fractionalDigits: dto.fractional_digits
1856
- })
1857
- };
1858
-
1859
- // src/shared/types/offer.ts
1860
- var OfferId = (value) => value;
1861
- var OfferSlug = (value) => value;
1862
- var Offer = {
1863
- fromDto: (dto) => {
1864
- if (!Array.isArray(dto.tokens)) {
1865
- throw new ValidationError(
1866
- `Offer.tokens: expected an array, got ${typeof dto.tokens}`
1867
- );
1868
- }
1869
- return {
1870
- id: OfferId(dto.id),
1871
- slug: OfferSlug(dto.slug),
1872
- type: dto.type,
1873
- tagline: dto.tagline,
1874
- bannerUrl: dto.banner_url,
1875
- logoUrl: dto.logo_url,
1876
- startsAt: new Date(dto.starts_at),
1877
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1878
- tokens: dto.tokens.map(OfferToken.fromDto)
1879
- };
1880
- }
1881
- };
1882
- var OfferToken = {
1883
- fromDto: (dto) => ({
1884
- role: dto.role,
1885
- chain: Chain(dto.chain),
1886
- address: EvmContractAddress(dto.address)
1887
- })
1888
- };
1889
-
1890
- // src/shared/types/offer-detail.ts
1891
- var OfferOptionId = (value) => value;
1892
- var OfferOptionSlug = (value) => value;
1893
- var OfferSwapContract = {
1894
- fromDto: (dto) => ({
1895
- chain: Chain(dto.chain),
1896
- address: EvmContractAddress(dto.address)
1897
- })
1898
- };
1899
- var OfferDetail = {
1900
- fromDto: (dto) => {
1901
- if (!Array.isArray(dto.funding_assets)) {
1902
- throw new ValidationError(
1903
- `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
1904
- );
1905
- }
1906
- if (!Array.isArray(dto.options)) {
1907
- throw new ValidationError(
1908
- `OfferDetail.options: expected an array, got ${typeof dto.options}`
1909
- );
1910
- }
1911
- if (!Array.isArray(dto.terms)) {
1912
- throw new ValidationError(
1913
- `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
1914
- );
1915
- }
1916
- if (!Array.isArray(dto.links)) {
1917
- throw new ValidationError(
1918
- `OfferDetail.links: expected an array, got ${typeof dto.links}`
1919
- );
1920
- }
1921
- if (!Array.isArray(dto.faqs)) {
1922
- throw new ValidationError(
1923
- `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
1924
- );
1925
- }
1926
- if (!Array.isArray(dto.milestones)) {
1927
- throw new ValidationError(
1928
- `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
1929
- );
1930
- }
1931
- if (!Array.isArray(dto.tokens)) {
1932
- throw new ValidationError(
1933
- `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1934
- );
1935
- }
1936
- const swapContracts = dto.swap_contracts === void 0 ? [] : dto.swap_contracts;
1937
- if (!Array.isArray(swapContracts)) {
1938
- throw new ValidationError(
1939
- `OfferDetail.swap_contracts: expected an array, got ${typeof swapContracts}`
1940
- );
1941
- }
1942
- return {
1943
- id: OfferId(dto.id),
1944
- slug: OfferSlug(dto.slug),
1945
- type: dto.type,
1946
- name: dto.name,
1947
- asset: Asset.fromDto(dto.asset),
1948
- fundingAssets: dto.funding_assets.map(Asset.fromDto),
1949
- tokens: dto.tokens.map(OfferToken.fromDto),
1950
- swapContracts: swapContracts.map(OfferSwapContract.fromDto),
1951
- about: notBlankStringOrNull(dto.about),
1952
- tagline: dto.tagline,
1953
- bannerUrl: dto.banner_url,
1954
- logoUrl: dto.logo_url,
1955
- category: dto.category,
1956
- startsAt: new Date(dto.starts_at),
1957
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1958
- faqs: dto.faqs.map(FaqItem.fromDto),
1959
- links: dto.links.map(Link.fromDto),
1960
- milestones: dto.milestones.map(Milestone.fromDto),
1961
- options: dto.options.map(OfferOption.fromDto),
1962
- terms: dto.terms.map(TermItem.fromDto)
1963
- };
1964
- }
1965
- };
1966
- var OfferOption = {
1967
- fromDto: (dto) => ({
1968
- id: OfferOptionId(dto.id),
1969
- slug: OfferOptionSlug(dto.slug),
1970
- bidIncrement: dto.bid_increment,
1971
- floorPriceUsd: dto.floor_price_usd,
1972
- minimumPurchaseUsd: dto.minimum_purchase_usd,
1973
- priceUsd: dto.price_usd,
1974
- saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),
1975
- totalTokenSupply: dto.total_token_supply
1976
- })
1977
- };
1978
- var FaqItem = {
1979
- fromDto: (dto) => ({
1980
- question: notBlankStringOrNull(dto.question),
1981
- answer: notBlankStringOrNull(dto.answer)
1982
- })
1983
- };
1984
- var Link = {
1985
- fromDto: (dto) => ({
1986
- label: notBlankStringOrNull(dto.label),
1987
- url: notBlankStringOrNull(dto.url)
1988
- })
1989
- };
1990
- var TermItem = {
1991
- fromDto: (dto) => ({
1992
- key: notBlankStringOrNull(dto.key),
1993
- value: notBlankStringOrNull(dto.value)
1994
- })
1995
- };
1996
- var Milestone = {
1997
- fromDto: (dto) => ({
1998
- name: notBlankStringOrNull(dto.name),
1999
- schedule: notBlankStringOrNull(dto.schedule),
2000
- status: dto.status
2001
- })
2002
- };
2003
-
2004
- // src/shared/types/providers/coin-list/token-sale.ts
2005
- var ParticipationId = (value) => value;
2006
- var Blockchain = (value) => value;
2007
- var WalletAddress = (value) => value;
2008
- var ParticipationsPaginationParams = {
2009
- toQueryParams: (params) => {
2010
- const queryParams = PaginationParams.toQueryParams(params);
2011
- if (params.offerId) {
2012
- queryParams["filters[0][field]"] = "offer_id";
2013
- queryParams["filters[0][op]"] = "==";
2014
- queryParams["filters[0][value]"] = params.offerId;
2015
- }
2016
- return queryParams;
2017
- }
1908
+ // src/universal/core/shared/blockchain/chain.ts
1909
+ var CHAIN_IDS = {
1910
+ ethereum_mainnet: 1,
1911
+ ethereum_sepolia: 11155111,
1912
+ base_mainnet: 8453,
1913
+ base_sepolia: 84532
2018
1914
  };
2019
- var Participation = {
2020
- /** Maps API DTO shape into the SDK participation domain model. */
2021
- fromDto: (dto) => {
2022
- const walletAddress = notBlankStringOrNull(dto.wallet_address);
2023
- return {
2024
- id: ParticipationId(dto.id),
2025
- offerId: OfferId(dto.offer_id),
2026
- offerOptionId: OfferOptionId(dto.offer_option_id),
2027
- status: dto.status,
2028
- amount: dto.amount,
2029
- displayAmount: dto.amount_string,
2030
- asset: Asset.fromDto(dto.asset),
2031
- chain: Blockchain(dto.chain),
2032
- insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
2033
- updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
2034
- walletAddress: walletAddress ? WalletAddress(walletAddress) : null
2035
- };
1915
+ function chainFromId(chainId) {
1916
+ const chains = Object.keys(CHAIN_IDS);
1917
+ const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);
1918
+ if (!chain) {
1919
+ throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
2036
1920
  }
2037
- };
2038
- var CreateParticipationParams = {
2039
- /** Maps participation creation params into API DTO payload. */
2040
- toDto: (params) => ({
2041
- offer_id: params.offerId,
2042
- offer_option_id: params.offerOptionId,
2043
- chain: params.chain,
2044
- wallet_address: params.walletAddress,
2045
- amount: params.amount,
2046
- asset_id: params.assetId,
2047
- approval_transaction_hash: params.approvalTransactionHash
2048
- })
2049
- };
2050
-
2051
- // src/shared/api/frontline/providers/coin-list/token-sale.ts
2052
- async function fetchParticipations(api, offerId) {
2053
- return fetchAllPages(
2054
- (params) => fetchParticipationsPage(api, params),
2055
- { offerId }
2056
- );
1921
+ return chain;
2057
1922
  }
2058
- async function fetchParticipationsPage(api, params) {
2059
- const pageDto = await api.send({
2060
- method: "GET",
2061
- url: "/v1/participations",
2062
- queryParams: ParticipationsPaginationParams.toQueryParams(params),
2063
- attributes: Attributes.protected()
2064
- });
2065
- return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
1923
+ function getNetworkName(chain) {
1924
+ switch (chain) {
1925
+ case "ethereum_mainnet":
1926
+ return "Ethereum";
1927
+ case "ethereum_sepolia":
1928
+ return "Ethereum Sepolia";
1929
+ case "base_mainnet":
1930
+ return "Base";
1931
+ case "base_sepolia":
1932
+ return "Base Sepolia";
1933
+ default: {
1934
+ const _exhaustive = chain;
1935
+ return _exhaustive;
1936
+ }
1937
+ }
2066
1938
  }
2067
- async function fetchParticipation(api, id) {
2068
- const dto = await api.send({
2069
- method: "GET",
2070
- url: `/v1/participations/${id}`,
2071
- attributes: Attributes.protected()
2072
- });
2073
- return Participation.fromDto(dto);
1939
+ function txExplorerUrl(chain, txHash) {
1940
+ return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);
2074
1941
  }
2075
- async function createParticipation(api, params) {
2076
- const dto = await api.send({
2077
- method: "POST",
2078
- url: "/v1/participations",
2079
- body: CreateParticipationParams.toDto(params),
2080
- attributes: Attributes.protected()
2081
- });
2082
- return Participation.fromDto(dto);
1942
+ function explorerBaseUrl(chain) {
1943
+ switch (chain) {
1944
+ case "ethereum_mainnet":
1945
+ return "https://etherscan.io";
1946
+ case "ethereum_sepolia":
1947
+ return "https://sepolia.etherscan.io";
1948
+ case "base_mainnet":
1949
+ return "https://basescan.org";
1950
+ case "base_sepolia":
1951
+ return "https://sepolia-explorer.base.org";
1952
+ default: {
1953
+ const _exhaustive = chain;
1954
+ return _exhaustive;
1955
+ }
1956
+ }
2083
1957
  }
2084
1958
 
2085
- // src/shared/core/checkout/coin-list/token-sale-namespace.ts
2086
- var CoinListTokenSaleNamespaceImpl = class {
2087
- constructor(ctx) {
2088
- this.ctx = ctx;
2089
- this.log = internalLogger(ctx.logger, "TOKEN_SALE");
1959
+ // src/universal/core/shared/blockchain/math.ts
1960
+ var import_viem3 = require("viem");
1961
+ function blockchainAmountFromRawOrThrow({
1962
+ label,
1963
+ raw,
1964
+ decimals
1965
+ }) {
1966
+ const trimmed = raw.trim();
1967
+ if (trimmed === "") {
1968
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
2090
1969
  }
2091
- async list(offerId) {
2092
- return this.log.wrap("list", offerId, async () => {
2093
- await this.ctx.ensureUserAuthenticated();
2094
- return fetchParticipations(this.ctx.api, offerId);
2095
- });
1970
+ let value;
1971
+ try {
1972
+ value = BigInt(trimmed);
1973
+ } catch {
1974
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
2096
1975
  }
2097
- async listPage(params) {
2098
- return this.log.wrap("listPage", params, async () => {
2099
- await this.ctx.ensureUserAuthenticated();
2100
- return fetchParticipationsPage(this.ctx.api, params);
2101
- });
1976
+ try {
1977
+ return BlockchainAmount({ raw: assertUint256(value), decimals });
1978
+ } catch {
1979
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
2102
1980
  }
2103
- async get(id) {
2104
- return this.log.wrap("get", id, async () => {
2105
- await this.ctx.ensureUserAuthenticated();
2106
- return fetchParticipation(this.ctx.api, id);
2107
- });
1981
+ }
1982
+ function parseBlockchainAmount(amount, decimals) {
1983
+ const trimmed = amount.trim();
1984
+ if (trimmed === "") return { valid: false, reason: { type: "empty" } };
1985
+ if (trimmed.startsWith("-")) {
1986
+ return { valid: false, reason: { type: "negative" } };
2108
1987
  }
2109
- async createParticipation(params) {
2110
- return this.log.wrap("createParticipation", params, async () => {
2111
- await this.ctx.ensureUserAuthenticated();
2112
- return createParticipation(this.ctx.api, params);
2113
- });
1988
+ if (/[eE]/.test(trimmed)) {
1989
+ return { valid: false, reason: { type: "invalid-format" } };
2114
1990
  }
2115
- };
2116
-
2117
- // src/shared/core/checkout/ondo/constants.ts
2118
- var ONDO_POLL_INTERVAL_MS = 15e3;
2119
- var ONDO_QUOTE_EXPIRY_THRESHOLD_MS = 5e3;
2120
- var DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString("1000");
2121
- var ONDO_SETTLEMENT_ASSET = USDC_SYMBOL;
2122
- var DEFAULT_ONDO_SELL_TOKENS_TO_COMPUTE_PRICE = 1;
2123
- var ONDO_SUPPORTED_INPUT_ASSETS = [
2124
- USDC_SYMBOL
2125
- ];
2126
-
2127
- // src/shared/core/checkout/ondo/math.ts
2128
- function computeOndoBuyPrice(transaction) {
2129
- const { notionalValue, receiveOutputAmount } = transaction;
2130
- return pricePerShare({
2131
- usd: notionalValue,
2132
- shares: receiveOutputAmount
2133
- });
2134
- }
2135
- function computeOndoSellPrice(transaction) {
2136
- const { expected, spendInputAmount } = transaction;
2137
- return pricePerShare({
2138
- usd: grossProceeds(expected),
2139
- shares: spendInputAmount
2140
- });
2141
- }
2142
- function grossProceeds(expected) {
2143
- const raw = expected.quantity.raw + expected.fee.raw;
2144
- if (raw > MAX_UINT_256) {
2145
- throw new MathError(`Ondo sell proceeds: out of uint256 bounds (${raw})`);
1991
+ if (!/^\d+(\.\d+)?$/.test(trimmed)) {
1992
+ return { valid: false, reason: { type: "invalid-format" } };
1993
+ }
1994
+ const [, fraction = ""] = trimmed.split(".");
1995
+ if (fraction.length > decimals) {
1996
+ return {
1997
+ valid: false,
1998
+ reason: { type: "too-many-decimals", maxDecimals: decimals }
1999
+ };
2146
2000
  }
2147
- return BlockchainAmount.add(expected.quantity, expected.fee);
2148
- }
2149
- function pricePerShare({
2150
- usd,
2151
- shares
2152
- }) {
2153
- const price = BlockchainAmount.div(usd, shares);
2154
- return BlockchainAmount({
2155
- raw: assertPriceFits(price.raw),
2156
- decimals: price.decimals
2157
- });
2158
- }
2159
- function assertPriceFits(raw) {
2160
2001
  try {
2161
- return assertUint256(raw);
2002
+ const raw = (0, import_viem3.parseUnits)(trimmed, decimals);
2003
+ if (raw > MAX_UINT_256) {
2004
+ return { valid: false, reason: { type: "overflow" } };
2005
+ }
2006
+ return {
2007
+ valid: true,
2008
+ amount: BlockchainAmount({ raw, decimals })
2009
+ };
2162
2010
  } catch {
2163
- throw new MathError(`Ondo price: out of uint256 bounds (${raw})`);
2011
+ return { valid: false, reason: { type: "invalid-format" } };
2164
2012
  }
2165
2013
  }
2166
2014
 
2167
- // src/shared/types/trading.ts
2168
- var Ticker = (value) => value;
2169
-
2170
- // src/shared/types/providers/ondo/ondo.ts
2015
+ // src/universal/types/providers/ondo/ondo.ts
2171
2016
  var OndoTradingStatus = {
2172
2017
  fromDto: (dto) => {
2173
2018
  if (!dto.tradable) return { type: "not-tradable", side: dto.side };
@@ -2333,7 +2178,7 @@ function parseExpiresAt(value) {
2333
2178
  return date;
2334
2179
  }
2335
2180
 
2336
- // src/shared/api/frontline/providers/ondo/ondo.ts
2181
+ // src/universal/api/frontline/providers/ondo/ondo.ts
2337
2182
  async function getOndoTradingStatus(api, params) {
2338
2183
  const dto = await api.send({
2339
2184
  method: "GET",
@@ -2428,7 +2273,7 @@ function sizeParam(params) {
2428
2273
  return { notional_value: notionalValue };
2429
2274
  }
2430
2275
 
2431
- // src/shared/core/checkout/ondo/ondo-namespace.ts
2276
+ // src/universal/core/checkout/ondo/ondo-namespace.ts
2432
2277
  var OndoNamespaceImpl = class {
2433
2278
  constructor(ctx) {
2434
2279
  this.ctx = ctx;
@@ -2460,7 +2305,7 @@ var OndoNamespaceImpl = class {
2460
2305
  }
2461
2306
  };
2462
2307
 
2463
- // src/shared/core/checkout/superstate/blockchain/abi.ts
2308
+ // src/universal/core/checkout/superstate/blockchain/abi.ts
2464
2309
  var SUPERSTATE_SWAP_ABI = [
2465
2310
  {
2466
2311
  type: "function",
@@ -2682,7 +2527,13 @@ var SUPERSTATE_SWAP_ABI = [
2682
2527
  }
2683
2528
  ];
2684
2529
 
2685
- // src/shared/core/checkout/superstate/blockchain/math.ts
2530
+ // src/universal/core/shared/blockchain/bps.ts
2531
+ var BPS_DENOM = Bps(10000n);
2532
+ function applyBps(amount, bps) {
2533
+ return assertUint256(amount * bps / BPS_DENOM);
2534
+ }
2535
+
2536
+ // src/universal/core/checkout/superstate/blockchain/math.ts
2686
2537
  function computePrice({
2687
2538
  inputTokenAmount,
2688
2539
  outputTokenAmount
@@ -2700,7 +2551,7 @@ function computeSlip(amount, slippage) {
2700
2551
  return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
2701
2552
  }
2702
2553
 
2703
- // src/shared/core/checkout/superstate/blockchain/quote.ts
2554
+ // src/universal/core/checkout/superstate/blockchain/quote.ts
2704
2555
  var SwapQuote = {
2705
2556
  /**
2706
2557
  * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
@@ -2720,53 +2571,210 @@ var SwapQuote = {
2720
2571
  })
2721
2572
  };
2722
2573
 
2723
- // src/shared/core/checkout/superstate/blockchain/status.ts
2724
- function isStopped(status) {
2725
- return (status.stopped & status.swapLevel) !== 0n;
2574
+ // src/universal/core/checkout/superstate/blockchain/status.ts
2575
+ function isStopped(status) {
2576
+ return (status.stopped & status.swapLevel) !== 0n;
2577
+ }
2578
+
2579
+ // src/universal/core/checkout/superstate/blockchain/swapped-event.ts
2580
+ var import_viem4 = require("viem");
2581
+ function decodeSwappedOutputAmount(receipt, outputDecimals) {
2582
+ try {
2583
+ const [swapped] = (0, import_viem4.parseEventLogs)({
2584
+ abi: SUPERSTATE_SWAP_ABI,
2585
+ eventName: "Swapped",
2586
+ logs: receipt.logs
2587
+ });
2588
+ if (!swapped) return null;
2589
+ const raw = swapped.args.outputAmount;
2590
+ if (raw < 0n || raw > MAX_UINT_256) return null;
2591
+ return BlockchainAmount({ raw, decimals: outputDecimals });
2592
+ } catch {
2593
+ return null;
2594
+ }
2595
+ }
2596
+
2597
+ // src/universal/core/checkout/superstate/constants.ts
2598
+ var SUPERSTATE_ISSUER_NAME = "Superstate";
2599
+ var SUPERSTATE_SUPPORTED_INPUT_ASSETS = [USDC_SYMBOL];
2600
+ var SWAP_POLL_INTERVAL_MS = 15e3;
2601
+ var DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1000000n;
2602
+ var SLIPPAGE_OPTIONS_BPS = [25n, 50n, 100n, 200n, 500n].map(
2603
+ (n) => Bps(n)
2604
+ );
2605
+ var DEFAULT_SLIPPAGE_BPS = Bps(50n);
2606
+ var SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA = EvmContractAddress("0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557");
2607
+ var SUPERSTATE_SWAP_CONTRACT_ADDRESSES = {
2608
+ ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA
2609
+ };
2610
+ function superstateSwapContractAddress(chain) {
2611
+ return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
2612
+ }
2613
+
2614
+ // src/universal/core/checkout/superstate/formatters.ts
2615
+ function formattedPricePerShare(quote, locale) {
2616
+ if (!quote) return NA_AMOUNT_ASSET_UI;
2617
+ return formattedUsdPrice(computePrice(quote), locale);
2618
+ }
2619
+
2620
+ // src/universal/types/providers/superstate/swap.ts
2621
+ var SwapAuthorization = {
2622
+ fromDto: (dto) => ({
2623
+ authorized: dto.authorized
2624
+ })
2625
+ };
2626
+ var SwapPreview = {
2627
+ fromDto: (dto) => ({
2628
+ inputAmount: parseUint256(
2629
+ BigInt(dto.pay_input_amount),
2630
+ "SwapPreview.pay_input_amount"
2631
+ ),
2632
+ fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
2633
+ outputAmount: parseUint256(
2634
+ BigInt(dto.receive_output_amount),
2635
+ "SwapPreview.receive_output_amount"
2636
+ )
2637
+ })
2638
+ };
2639
+ var SwapStatus = {
2640
+ fromDto: (dto) => ({
2641
+ stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
2642
+ swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
2643
+ })
2644
+ };
2645
+ var TokenAllowance = {
2646
+ fromDto: (dto) => ({
2647
+ allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
2648
+ })
2649
+ };
2650
+ var TokenBalance = {
2651
+ fromDto: (dto) => ({
2652
+ balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
2653
+ })
2654
+ };
2655
+ var AllowWalletResponse = {
2656
+ fromDto: (dto) => {
2657
+ switch (dto.action) {
2658
+ case "broadcast_transaction":
2659
+ return {
2660
+ action: "broadcast_transaction",
2661
+ to: EvmContractAddress(dto.to),
2662
+ data: HexEncodedTransactionData(dto.data)
2663
+ };
2664
+ case "none":
2665
+ return {
2666
+ action: "none",
2667
+ alreadyAllowed: dto.already_allowed
2668
+ };
2669
+ default: {
2670
+ const _exhaustive = dto;
2671
+ return _exhaustive;
2672
+ }
2673
+ }
2674
+ }
2675
+ };
2676
+
2677
+ // src/universal/api/frontline/providers/superstate/swap.ts
2678
+ async function getSwapAuthorization(api, params) {
2679
+ const dto = await api.send({
2680
+ method: "GET",
2681
+ url: "/v1/wallet/authorized",
2682
+ queryParams: {
2683
+ chain: params.chain,
2684
+ contract_address: params.contractAddress,
2685
+ wallet_address: params.walletAddress
2686
+ },
2687
+ attributes: Attributes.protected()
2688
+ });
2689
+ return SwapAuthorization.fromDto(dto);
2726
2690
  }
2727
-
2728
- // src/shared/core/checkout/superstate/blockchain/swapped-event.ts
2729
- var import_viem4 = require("viem");
2730
- function decodeSwappedOutputAmount(receipt, outputDecimals) {
2731
- try {
2732
- const [swapped] = (0, import_viem4.parseEventLogs)({
2733
- abi: SUPERSTATE_SWAP_ABI,
2734
- eventName: "Swapped",
2735
- logs: receipt.logs
2736
- });
2737
- if (!swapped) return null;
2738
- const raw = swapped.args.outputAmount;
2739
- if (raw < 0n || raw > MAX_UINT_256) return null;
2740
- return BlockchainAmount({ raw, decimals: outputDecimals });
2741
- } catch {
2742
- return null;
2743
- }
2691
+ async function getSwapOutputToken(api, params) {
2692
+ const dto = await api.send({
2693
+ method: "GET",
2694
+ url: "/v1/swap/output-token",
2695
+ queryParams: {
2696
+ chain: params.chain,
2697
+ contract_address: params.contractAddress
2698
+ },
2699
+ attributes: Attributes.protected()
2700
+ });
2701
+ return toErc20Asset(dto);
2744
2702
  }
2745
-
2746
- // src/shared/core/checkout/superstate/constants.ts
2747
- var SUPERSTATE_ISSUER_NAME = "Superstate";
2748
- var SUPERSTATE_SUPPORTED_INPUT_ASSETS = [USDC_SYMBOL];
2749
- var SWAP_POLL_INTERVAL_MS = 15e3;
2750
- var DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1000000n;
2751
- var SLIPPAGE_OPTIONS_BPS = [25n, 50n, 100n, 200n, 500n].map(
2752
- (n) => Bps(n)
2753
- );
2754
- var DEFAULT_SLIPPAGE_BPS = Bps(50n);
2755
- var SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA = EvmContractAddress("0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557");
2756
- var SUPERSTATE_SWAP_CONTRACT_ADDRESSES = {
2757
- ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA
2758
- };
2759
- function superstateSwapContractAddress(chain) {
2760
- return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
2703
+ async function getSwapPreview(api, params) {
2704
+ const dto = await api.send({
2705
+ method: "GET",
2706
+ url: "/v1/swap/preview",
2707
+ queryParams: {
2708
+ chain: params.chain,
2709
+ contract_address: params.contractAddress,
2710
+ input_token: params.inputToken,
2711
+ amount: params.amount.toString()
2712
+ },
2713
+ attributes: Attributes.protected()
2714
+ });
2715
+ return SwapPreview.fromDto(dto);
2761
2716
  }
2762
-
2763
- // src/shared/core/checkout/superstate/formatters.ts
2764
- function formattedPricePerShare(quote, locale) {
2765
- if (!quote) return NA_AMOUNT_ASSET_UI;
2766
- return formattedUsdPrice(computePrice(quote), locale);
2717
+ async function getSwapStatus(api, params) {
2718
+ const dto = await api.send({
2719
+ method: "GET",
2720
+ url: "/v1/swap/status",
2721
+ queryParams: {
2722
+ chain: params.chain,
2723
+ contract_address: params.contractAddress
2724
+ },
2725
+ attributes: Attributes.protected()
2726
+ });
2727
+ return SwapStatus.fromDto(dto);
2728
+ }
2729
+ async function getTokenAllowance(api, params) {
2730
+ const dto = await api.send({
2731
+ method: "GET",
2732
+ url: "/v1/token/allowance",
2733
+ queryParams: {
2734
+ chain: params.chain,
2735
+ token_address: params.tokenAddress,
2736
+ owner: params.owner,
2737
+ spender: params.spender
2738
+ },
2739
+ attributes: Attributes.protected()
2740
+ });
2741
+ return TokenAllowance.fromDto(dto);
2742
+ }
2743
+ async function getTokenBalance(api, params) {
2744
+ const dto = await api.send({
2745
+ method: "GET",
2746
+ url: "/v1/token/balance",
2747
+ queryParams: {
2748
+ chain: params.chain,
2749
+ token_address: params.tokenAddress,
2750
+ owner: params.owner
2751
+ },
2752
+ attributes: Attributes.protected()
2753
+ });
2754
+ return TokenBalance.fromDto(dto);
2755
+ }
2756
+ async function allowWallet(api, params) {
2757
+ const dto = await api.send({
2758
+ method: "POST",
2759
+ url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
2760
+ body: {
2761
+ wallet_address: params.walletAddress,
2762
+ chain: params.chain,
2763
+ signature: params.signature
2764
+ },
2765
+ attributes: Attributes.protected()
2766
+ });
2767
+ return AllowWalletResponse.fromDto(dto);
2768
+ }
2769
+ function toErc20Asset(dto) {
2770
+ return {
2771
+ name: dto.name,
2772
+ symbol: AssetSymbol(dto.symbol),
2773
+ decimals: AssetDecimals(dto.decimals)
2774
+ };
2767
2775
  }
2768
2776
 
2769
- // src/shared/core/checkout/superstate/swap-namespace.ts
2777
+ // src/universal/core/checkout/superstate/swap-namespace.ts
2770
2778
  var SuperstateSwapNamespaceImpl = class {
2771
2779
  constructor(ctx) {
2772
2780
  this.ctx = ctx;
@@ -2804,7 +2812,7 @@ var SuperstateSwapNamespaceImpl = class {
2804
2812
  }
2805
2813
  };
2806
2814
 
2807
- // src/shared/api/frontline/offers.ts
2815
+ // src/universal/api/frontline/offers.ts
2808
2816
  async function fetchOffers(api, clientCreds) {
2809
2817
  return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
2810
2818
  }
@@ -2833,7 +2841,7 @@ async function fetchOfferDetails(api, id, clientCreds) {
2833
2841
  return OfferDetail.fromDto(dto);
2834
2842
  }
2835
2843
 
2836
- // src/shared/core/offers/offers-namespace.ts
2844
+ // src/universal/core/offers/offers-namespace.ts
2837
2845
  var OffersNamespaceImpl = class {
2838
2846
  constructor(ctx) {
2839
2847
  this.ctx = ctx;
@@ -2859,12 +2867,12 @@ var OffersNamespaceImpl = class {
2859
2867
  }
2860
2868
  };
2861
2869
 
2862
- // src/shared/core/offers/swap-contracts.ts
2870
+ // src/universal/core/offers/swap-contracts.ts
2863
2871
  function swapSpender(swapContracts, chain) {
2864
2872
  return swapContracts.find((contract) => contract.chain === chain)?.address ?? null;
2865
2873
  }
2866
2874
 
2867
- // src/shared/types/document-submission.ts
2875
+ // src/universal/types/document-submission.ts
2868
2876
  var DocumentSubmission = {
2869
2877
  fromDto: (dto) => ({
2870
2878
  status: dto.status,
@@ -2872,7 +2880,7 @@ var DocumentSubmission = {
2872
2880
  })
2873
2881
  };
2874
2882
 
2875
- // src/shared/api/frontline/documents.ts
2883
+ // src/universal/api/frontline/documents.ts
2876
2884
  async function submitDocument(api, documentType, fields) {
2877
2885
  const dto = await api.send({
2878
2886
  method: "POST",
@@ -2883,14 +2891,14 @@ async function submitDocument(api, documentType, fields) {
2883
2891
  return DocumentSubmission.fromDto(dto);
2884
2892
  }
2885
2893
 
2886
- // src/shared/types/kyc.ts
2894
+ // src/universal/types/kyc.ts
2887
2895
  var KycToken = {
2888
2896
  fromDto: (dto) => ({
2889
2897
  token: dto.token
2890
2898
  })
2891
2899
  };
2892
2900
 
2893
- // src/shared/api/frontline/kyc.ts
2901
+ // src/universal/api/frontline/kyc.ts
2894
2902
  async function createKycToken(api, levelName, reset) {
2895
2903
  const dto = await api.send({
2896
2904
  method: "POST",
@@ -2904,7 +2912,7 @@ async function createKycToken(api, levelName, reset) {
2904
2912
  return KycToken.fromDto(dto);
2905
2913
  }
2906
2914
 
2907
- // src/shared/types/pii.ts
2915
+ // src/universal/types/pii.ts
2908
2916
  var Iso2CountryCode = (value) => value;
2909
2917
  var PiiJurisdiction = {
2910
2918
  fromDto: (dto) => ({
@@ -2932,7 +2940,7 @@ var Pii = {
2932
2940
  })
2933
2941
  };
2934
2942
 
2935
- // src/shared/api/frontline/pii.ts
2943
+ // src/universal/api/frontline/pii.ts
2936
2944
  async function fetchPii(api) {
2937
2945
  const dto = await api.send({
2938
2946
  method: "GET",
@@ -2942,7 +2950,7 @@ async function fetchPii(api) {
2942
2950
  return Pii.fromDto(dto);
2943
2951
  }
2944
2952
 
2945
- // src/shared/types/requirement.ts
2953
+ // src/universal/types/requirement.ts
2946
2954
  var RequirementId = (value) => value;
2947
2955
  var Requirement = {
2948
2956
  fromDto: (dto) => ({
@@ -2963,7 +2971,7 @@ var RequirementStatusInfo = {
2963
2971
  )
2964
2972
  };
2965
2973
 
2966
- // src/shared/api/frontline/requirements.ts
2974
+ // src/universal/api/frontline/requirements.ts
2967
2975
  async function fetchOfferRequirements(api, offerId, clientCreds) {
2968
2976
  const response = await api.send({
2969
2977
  method: "GET",
@@ -2989,7 +2997,7 @@ async function fetchRequirementStatuses(api, offerId) {
2989
2997
  return RequirementStatusInfo.fromStatusesDto(response);
2990
2998
  }
2991
2999
 
2992
- // src/shared/core/requirements/requirements-namespace.ts
3000
+ // src/universal/core/requirements/requirements-namespace.ts
2993
3001
  var RequirementsNamespaceImpl = class {
2994
3002
  constructor(ctx) {
2995
3003
  this.ctx = ctx;
@@ -3039,10 +3047,30 @@ var RequirementsNamespaceImpl = class {
3039
3047
  }
3040
3048
  };
3041
3049
 
3042
- // src/shared/api/nabu/tokens.ts
3050
+ // src/universal/core/shared/blockchain/erc20/erc20-namespace.ts
3051
+ var Erc20NamespaceImpl = class {
3052
+ constructor(ctx) {
3053
+ this.ctx = ctx;
3054
+ this.log = internalLogger(ctx.logger, "ERC20");
3055
+ }
3056
+ async getAllowance(params) {
3057
+ return this.log.wrap("getAllowance", params, async () => {
3058
+ await this.ctx.ensureUserAuthenticated();
3059
+ return getTokenAllowance(this.ctx.api, params);
3060
+ });
3061
+ }
3062
+ async getBalance(params) {
3063
+ return this.log.wrap("getBalance", params, async () => {
3064
+ await this.ctx.ensureUserAuthenticated();
3065
+ return getTokenBalance(this.ctx.api, params);
3066
+ });
3067
+ }
3068
+ };
3069
+
3070
+ // src/universal/api/nabu/tokens.ts
3043
3071
  var import_viem5 = require("viem");
3044
3072
 
3045
- // src/shared/types/token-metadata.ts
3073
+ // src/universal/types/token-metadata.ts
3046
3074
  var TokenLogoUrl = (value) => value;
3047
3075
  var TokenLogo = {
3048
3076
  /** `baseUrl` is the registry origin; registry URLs are root-relative. */
@@ -3125,7 +3153,7 @@ var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
3125
3153
  url.startsWith("http") ? url : `${baseUrl.replace(/\/$/, "")}${url}`
3126
3154
  );
3127
3155
 
3128
- // src/shared/api/nabu/tokens.ts
3156
+ // src/universal/api/nabu/tokens.ts
3129
3157
  function createNabuApiClient(baseUrl, logger = null) {
3130
3158
  return new HttpClient({ baseUrl }, {}, logger);
3131
3159
  }
@@ -3216,10 +3244,10 @@ function checksummed(address) {
3216
3244
  }
3217
3245
  }
3218
3246
 
3219
- // src/shared/core/tokens/tokens-namespace.ts
3247
+ // src/universal/core/tokens/tokens-namespace.ts
3220
3248
  var TokensNamespaceImpl = class {
3221
3249
  /**
3222
- * Takes the registry origin rather than a `SharedNamespaceContext`: the
3250
+ * Takes the registry origin rather than a `UniversalNamespaceContext`: the
3223
3251
  * registry is unauthenticated and on its own host, so the frontline sender
3224
3252
  * and the auth check would both be dead weight here.
3225
3253
  */
@@ -3243,7 +3271,7 @@ var TokensNamespaceImpl = class {
3243
3271
  }
3244
3272
  };
3245
3273
 
3246
- // src/shared/types/offer-option-address.ts
3274
+ // src/universal/types/offer-option-address.ts
3247
3275
  var OfferOptionAddressId = (value) => value;
3248
3276
  var OfferOptionAddress = {
3249
3277
  /** Maps the API DTO into the SDK offer-option-address domain model. */
@@ -3265,7 +3293,7 @@ var ConnectExternalWalletParams = {
3265
3293
  })
3266
3294
  };
3267
3295
 
3268
- // src/shared/types/wallet-ownership-challenge.ts
3296
+ // src/universal/types/wallet-ownership-challenge.ts
3269
3297
  var WalletOwnershipChallenge = {
3270
3298
  /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
3271
3299
  fromDto: (dto) => ({
@@ -3304,7 +3332,7 @@ var CreateWalletOwnershipChallengeParams = {
3304
3332
  }
3305
3333
  };
3306
3334
 
3307
- // src/shared/api/frontline/wallet-connect.ts
3335
+ // src/universal/api/frontline/wallet-connect.ts
3308
3336
  async function createWalletOwnershipChallenge(api, params) {
3309
3337
  const dto = await api.send({
3310
3338
  method: "POST",
@@ -3341,7 +3369,7 @@ async function removeOptionAddress(api, offerId, addressId) {
3341
3369
  return OfferOptionAddress.fromDto(dto);
3342
3370
  }
3343
3371
 
3344
- // src/shared/core/wallets/wallets-namespace.ts
3372
+ // src/universal/core/wallets/wallets-namespace.ts
3345
3373
  var WalletsNamespaceImpl = class {
3346
3374
  constructor(ctx) {
3347
3375
  this.ctx = ctx;
@@ -3384,7 +3412,7 @@ var WalletsNamespaceImpl = class {
3384
3412
  }
3385
3413
  };
3386
3414
 
3387
- // src/shared/types/blockchain/wallet-error.ts
3415
+ // src/universal/types/blockchain/wallet-error.ts
3388
3416
  var RedactedWalletError = {
3389
3417
  fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
3390
3418
  };
@@ -3468,7 +3496,7 @@ async function executeTokenSale(params) {
3468
3496
  return { type: "success", participation, approvalTxHash };
3469
3497
  }
3470
3498
 
3471
- // src/client/core/observability/flow-logging.ts
3499
+ // src/client/core/shared/observability/flow-logging.ts
3472
3500
  async function withFlowLogging(log, flow, fields, onProgress, run) {
3473
3501
  const flowLog = log.child({ flow });
3474
3502
  flowLog.info(() => ({ msg: "flow started", fields }));
@@ -3918,7 +3946,7 @@ var ClientSuperstateSwapNamespaceImpl = class extends SuperstateSwapNamespaceImp
3918
3946
  }
3919
3947
  };
3920
3948
 
3921
- // src/client/core/utils/open-in-new-tab.ts
3949
+ // src/client/core/shared/utils/open-in-new-tab.ts
3922
3950
  function openInNewTab(url) {
3923
3951
  window.open(url, "_blank", "noopener,noreferrer");
3924
3952
  }
@@ -3976,7 +4004,7 @@ var ClientSupportNamespaceImpl = class {
3976
4004
  }
3977
4005
  };
3978
4006
 
3979
- // src/shared/api/nabu/config.ts
4007
+ // src/universal/api/nabu/config.ts
3980
4008
  var NABU_BASE_URL = "https://asset.coinlist.co";
3981
4009
 
3982
4010
  // src/client/core/coinlist-client.ts
@@ -4647,7 +4675,7 @@ function CoinListSignInCardContainer({
4647
4675
  }
4648
4676
 
4649
4677
  // src/client/components/checkout/CheckoutContainer.tsx
4650
- var import_react34 = require("react");
4678
+ var import_react35 = require("react");
4651
4679
 
4652
4680
  // src/client/components/checkout/shared/amount/CheckoutAmountInput.tsx
4653
4681
  var import_react8 = require("react");
@@ -6111,6 +6139,7 @@ var ISSUER_LABEL = "Issuer";
6111
6139
  var TICKER_SYMBOL_LABEL = "Ticker symbol";
6112
6140
  var ISIN_LABEL = "ISIN";
6113
6141
  var ASSET_TYPE_LABEL = "Asset type";
6142
+ var LISTING_VENUE_LABEL = "Listing venue";
6114
6143
  var NETWORK_LABEL = "Network";
6115
6144
  var PRICE_UNAVAILABLE = "-";
6116
6145
  function OndoSidebarView({
@@ -6142,6 +6171,7 @@ function detailRows2(state) {
6142
6171
  { label: TICKER_SYMBOL_LABEL, value: state.tickerSymbol },
6143
6172
  { label: ISIN_LABEL, value: state.isin },
6144
6173
  { label: ASSET_TYPE_LABEL, value: state.assetType },
6174
+ { label: LISTING_VENUE_LABEL, value: state.listingVenue },
6145
6175
  { label: NETWORK_LABEL, value: state.networkName }
6146
6176
  ];
6147
6177
  }
@@ -8445,7 +8475,7 @@ function ErrorView4({
8445
8475
  }
8446
8476
 
8447
8477
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
8448
- var import_react22 = require("react");
8478
+ var import_react23 = require("react");
8449
8479
 
8450
8480
  // src/client/hooks/checkout/ondo/buy/amount/useOndoBuyAmountViewModel.ts
8451
8481
  var import_react15 = require("react");
@@ -8472,6 +8502,26 @@ function stablecoinIconUrl(symbol) {
8472
8502
  function offerIconUrl(offer) {
8473
8503
  return offer.logoUrl === "" ? null : AssetIconUrl(offer.logoUrl);
8474
8504
  }
8505
+ function tokenLogoUrl(logo, minWidth = 40) {
8506
+ switch (logo.kind) {
8507
+ case "VECTOR":
8508
+ return AssetIconUrl(logo.url);
8509
+ case "RASTER": {
8510
+ const chosen = logo.variants.reduce(
8511
+ (smallest, variant) => variant.width >= minWidth && (smallest === null || variant.width < smallest.width) ? variant : smallest,
8512
+ null
8513
+ );
8514
+ return AssetIconUrl((chosen ?? logo.original).url);
8515
+ }
8516
+ default: {
8517
+ const exhaustive = logo;
8518
+ return exhaustive;
8519
+ }
8520
+ }
8521
+ }
8522
+ function offerAssetIconUrl(offer, tokenMetadata) {
8523
+ return (tokenMetadata ? tokenLogoUrl(tokenMetadata.logo) : null) ?? offerIconUrl(offer);
8524
+ }
8475
8525
 
8476
8526
  // src/client/hooks/checkout/shared/checkout-ui.types.ts
8477
8527
  var CheckoutAssetUi = {
@@ -8480,10 +8530,10 @@ var CheckoutAssetUi = {
8480
8530
  * name and symbol, the caller supplies the chain it is being traded on and
8481
8531
  * whatever icon it has for it.
8482
8532
  *
8483
- * `iconUrl` is a caller's parameter rather than the token's own because a
8484
- * token does not carry one - the SDK ships no icon registry, and the only
8485
- * source is the offer being bought. Which is also why it defaults to `null`:
8486
- * the input asset a user pays with has no offer behind it.
8533
+ * `iconUrl` is a caller's parameter rather than the token's own because an
8534
+ * `Erc20Asset` does not carry one, and which source supplies it is the
8535
+ * caller's to decide. Which is also why it defaults to `null`: the input
8536
+ * asset a user pays with has no offer behind it.
8487
8537
  *
8488
8538
  * An asset sourced from the offer rather than from a token has its own
8489
8539
  * companion, {@link fromOffer}. One companion per source, not one per call
@@ -8500,7 +8550,7 @@ var CheckoutAssetUi = {
8500
8550
  }),
8501
8551
  /**
8502
8552
  * The view of the asset an offer sells: the offer supplies its name and the
8503
- * only icon the SDK has, the caller supplies the symbol and the chain.
8553
+ * fallback artwork, the caller supplies the symbol and the chain.
8504
8554
  *
8505
8555
  * `symbol` is a parameter rather than `offer.asset.code` because the symbol a
8506
8556
  * provider trades under is the provider's, not the catalogue's - Ondo's
@@ -8508,14 +8558,26 @@ var CheckoutAssetUi = {
8508
8558
  * asset stands in. Keeping it out here is what lets one companion serve every
8509
8559
  * provider instead of forking per provider.
8510
8560
  *
8561
+ * The icon is resolved from the public token registry when `tokenMetadata`
8562
+ * carries a listed token — `useCheckoutOfferTokenMetadata` fetches it,
8563
+ * keyed by the token `OfferDetail.tokens` lists for this chain — and falls
8564
+ * back to the offer's own logo otherwise. `null` covers every way the
8565
+ * registry answer can be absent (unlisted, not settled, lookup failed);
8566
+ * which one it is stays the concern of the hook's state machine, not of
8567
+ * this model, because the icon is the same either way.
8568
+ *
8511
8569
  * Deliberately no decimals. An offer names an asset; it does not answer for
8512
8570
  * the scale of any particular quantity, and every amount a checkout renders
8513
8571
  * arrives as a `BlockchainAmount` carrying its own.
8514
8572
  */
8515
- fromOffer: (offer, { symbol, networkName }) => ({
8573
+ fromOffer: (offer, {
8574
+ symbol,
8575
+ networkName,
8576
+ tokenMetadata
8577
+ }) => ({
8516
8578
  name: offer.name,
8517
8579
  symbol,
8518
- iconUrl: offerIconUrl(offer),
8580
+ iconUrl: offerAssetIconUrl(offer, tokenMetadata),
8519
8581
  network: { name: networkName, iconUrl: null }
8520
8582
  })
8521
8583
  };
@@ -9036,6 +9098,7 @@ function useOndoBuyReviewViewModel({
9036
9098
  ondoSymbol,
9037
9099
  chain,
9038
9100
  offer,
9101
+ outputTokenMetadata,
9039
9102
  enabled = true,
9040
9103
  onComplete
9041
9104
  }) {
@@ -9088,7 +9151,8 @@ function useOndoBuyReviewViewModel({
9088
9151
  type: "active",
9089
9152
  outputAsset: CheckoutAssetUi.fromOffer(offer, {
9090
9153
  symbol: ondoSymbol,
9091
- networkName: getNetworkName(chain)
9154
+ networkName: getNetworkName(chain),
9155
+ tokenMetadata: outputTokenMetadata
9092
9156
  }),
9093
9157
  outputAmount: assetAmount(
9094
9158
  formatAmount(built.receiveOutputAmount, locale),
@@ -9419,6 +9483,7 @@ function useOndoSidebarViewModel({
9419
9483
  offer,
9420
9484
  ondoSymbol,
9421
9485
  chain,
9486
+ tokenMetadata,
9422
9487
  priceState,
9423
9488
  tradingStatusState
9424
9489
  }) {
@@ -9426,14 +9491,17 @@ function useOndoSidebarViewModel({
9426
9491
  const state = {
9427
9492
  asset: CheckoutAssetUi.fromOffer(offer, {
9428
9493
  symbol: ondoSymbol,
9429
- networkName: getNetworkName(chain)
9494
+ networkName: getNetworkName(chain),
9495
+ tokenMetadata
9430
9496
  }),
9431
- // No frontline endpoint carries any of these today, and the detail list
9432
- // drops a null row rather than dashing it.
9433
- issuer: null,
9434
- tickerSymbol: null,
9435
- isin: null,
9436
- assetType: null,
9497
+ // Reference data for the security the token tracks. Each is null on an
9498
+ // offer that tokenizes none, and the detail list drops a null row rather
9499
+ // than dashing it.
9500
+ issuer: offer.issuer,
9501
+ tickerSymbol: offer.ticker,
9502
+ isin: offer.isin,
9503
+ assetType: offer.instrumentType,
9504
+ listingVenue: offer.listingVenue,
9437
9505
  networkName: getNetworkName(chain),
9438
9506
  price: toPriceUi(priceState, tradingStatusState, locale)
9439
9507
  };
@@ -9616,6 +9684,99 @@ function toConfirmedWalletUi(wallets, wallet) {
9616
9684
  };
9617
9685
  }
9618
9686
 
9687
+ // src/client/hooks/shared/useTokenMetadata.ts
9688
+ var import_react22 = require("react");
9689
+ var DISABLED_STATE = { type: "DISABLED" };
9690
+ var LOADING_STATE = { type: "LOADING" };
9691
+ function useTokenMetadata(options) {
9692
+ const { chain, address, data, enabled = true } = options;
9693
+ const { coinlist, isReady } = useCoinList();
9694
+ const log = useLogger("useTokenMetadata");
9695
+ const [state, setState] = (0, import_react22.useState)(
9696
+ () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE
9697
+ );
9698
+ const [refetchCount, setRefetchCount] = (0, import_react22.useState)(0);
9699
+ const refetch = (0, import_react22.useCallback)(() => {
9700
+ setRefetchCount((count) => count + 1);
9701
+ }, []);
9702
+ (0, import_react22.useEffect)(() => {
9703
+ let isCancelled = false;
9704
+ const seedActive = data !== void 0 && refetchCount === 0;
9705
+ if (!isReady || !enabled || seedActive) {
9706
+ return () => {
9707
+ isCancelled = true;
9708
+ };
9709
+ }
9710
+ setState(LOADING_STATE);
9711
+ coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
9712
+ if (!isCancelled) {
9713
+ log.debug(() => ({
9714
+ msg: "settled",
9715
+ fields: {
9716
+ state: "CONTENT",
9717
+ listed: tokenMetadata !== null,
9718
+ symbol: tokenMetadata?.symbol ?? null
9719
+ }
9720
+ }));
9721
+ setState({ type: "CONTENT", tokenMetadata });
9722
+ }
9723
+ }).catch((error) => {
9724
+ if (!isCancelled) {
9725
+ log.failure(
9726
+ () => ({
9727
+ msg: "settled",
9728
+ fields: { state: "ERROR", reason: "generic-error" }
9729
+ }),
9730
+ error
9731
+ );
9732
+ setState({ type: "ERROR", reason: "generic-error" });
9733
+ }
9734
+ });
9735
+ return () => {
9736
+ isCancelled = true;
9737
+ };
9738
+ }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
9739
+ return {
9740
+ // LOADING would be a lie while disabled: nothing is in flight and nothing
9741
+ // will replace it. Settled states (a seed, a previous answer) survive.
9742
+ state: !enabled && state.type === "LOADING" ? DISABLED_STATE : state,
9743
+ refetch
9744
+ };
9745
+ }
9746
+
9747
+ // src/client/hooks/checkout/shared/data/useCheckoutOfferTokenMetadata.ts
9748
+ var NO_TOKEN_ADDRESS = EvmContractAddress(
9749
+ "0x0000000000000000000000000000000000000000"
9750
+ );
9751
+ function offerTokenIdentifier(offer, chain) {
9752
+ const byChain = offer.tokens.filter((token) => token.chain === chain);
9753
+ const asset = byChain.find((token) => token.role === "swap") ?? byChain.find((token) => token.role === "distribution");
9754
+ return asset === void 0 ? null : { chain, address: asset.address };
9755
+ }
9756
+ function tokenMetadataOf(state) {
9757
+ return state.type === "CONTENT" ? state.tokenMetadata : null;
9758
+ }
9759
+ function useCheckoutOfferTokenMetadata({
9760
+ offer,
9761
+ chain,
9762
+ data,
9763
+ enabled = true
9764
+ }) {
9765
+ const identifier = offerTokenIdentifier(offer, chain);
9766
+ const { state } = useTokenMetadata({
9767
+ // Primitive keys, not the identifier object: the underlying hook re-fetches
9768
+ // only when `(chain, address)` changes, so a host that rebuilds the offer
9769
+ // object per render does not refetch the registry per render.
9770
+ chain: identifier?.chain ?? chain,
9771
+ address: identifier?.address ?? NO_TOKEN_ADDRESS,
9772
+ // Nothing to look up when the offer lists no token here: seed "not
9773
+ // listed" and never fire a request against the placeholder address.
9774
+ enabled: enabled && identifier !== null,
9775
+ data: data !== void 0 ? data : identifier === null ? null : void 0
9776
+ });
9777
+ return { state };
9778
+ }
9779
+
9619
9780
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
9620
9781
  function useOndoBuyCheckoutViewModel({
9621
9782
  offer,
@@ -9626,8 +9787,8 @@ function useOndoBuyCheckoutViewModel({
9626
9787
  onOrderConfirmed
9627
9788
  }) {
9628
9789
  const locale = useLocale();
9629
- const [step, setStep] = (0, import_react22.useState)({ type: "wallet" });
9630
- const [orderConfirmed, setOrderConfirmed] = (0, import_react22.useState)({ type: "hidden" });
9790
+ const [step, setStep] = (0, import_react23.useState)({ type: "wallet" });
9791
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react23.useState)(null);
9631
9792
  const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
9632
9793
  const live = enabled && swappableHere;
9633
9794
  const { state: priceState } = useOndoPrice({
@@ -9643,6 +9804,20 @@ function useOndoBuyCheckoutViewModel({
9643
9804
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
9644
9805
  enabled: live
9645
9806
  });
9807
+ const { state: outputTokenMetadataState } = useCheckoutOfferTokenMetadata({
9808
+ offer,
9809
+ chain,
9810
+ enabled: live
9811
+ });
9812
+ const outputTokenMetadata = tokenMetadataOf(outputTokenMetadataState);
9813
+ const orderConfirmedUi = (order) => order === null ? { type: "hidden" } : toOrderConfirmedUi({
9814
+ order,
9815
+ chain,
9816
+ locale,
9817
+ offer,
9818
+ ondoSymbol,
9819
+ outputTokenMetadata
9820
+ });
9646
9821
  const { state: walletState, onEvent: onWalletEvent } = useOndoWalletSelectViewModel({
9647
9822
  stepInput: walletStepInput(step),
9648
9823
  wallets,
@@ -9689,11 +9864,10 @@ function useOndoBuyCheckoutViewModel({
9689
9864
  ondoSymbol,
9690
9865
  chain,
9691
9866
  offer,
9867
+ outputTokenMetadata,
9692
9868
  enabled: live,
9693
9869
  onComplete: (order) => {
9694
- setOrderConfirmed(
9695
- toOrderConfirmedUi({ order, chain, locale, offer, ondoSymbol })
9696
- );
9870
+ setOrderConfirmed(order);
9697
9871
  setStep({ type: "wallet" });
9698
9872
  onOrderConfirmed?.(order);
9699
9873
  }
@@ -9702,6 +9876,7 @@ function useOndoBuyCheckoutViewModel({
9702
9876
  offer,
9703
9877
  ondoSymbol,
9704
9878
  chain,
9879
+ tokenMetadata: outputTokenMetadata,
9705
9880
  priceState,
9706
9881
  tradingStatusState
9707
9882
  });
@@ -9711,7 +9886,7 @@ function useOndoBuyCheckoutViewModel({
9711
9886
  amount: amountState,
9712
9887
  review: reviewState,
9713
9888
  sidebar: sidebarState,
9714
- orderConfirmed
9889
+ orderConfirmed: orderConfirmedUi(orderConfirmed)
9715
9890
  };
9716
9891
  const onEvent = (event) => {
9717
9892
  switch (event.type) {
@@ -9735,7 +9910,7 @@ function useOndoBuyCheckoutViewModel({
9735
9910
  onReviewEvent(event);
9736
9911
  return;
9737
9912
  case "ON_CLOSE_ORDER_CONFIRMED":
9738
- setOrderConfirmed({ type: "hidden" });
9913
+ setOrderConfirmed(null);
9739
9914
  return;
9740
9915
  default: {
9741
9916
  const exhaustive = event;
@@ -9789,14 +9964,16 @@ function toOrderConfirmedUi({
9789
9964
  chain,
9790
9965
  locale,
9791
9966
  offer,
9792
- ondoSymbol
9967
+ ondoSymbol,
9968
+ outputTokenMetadata
9793
9969
  }) {
9794
9970
  const inputSymbol = TOKEN_REGISTRY.erc20(order.inputAsset).symbol;
9795
9971
  return {
9796
9972
  type: "visible",
9797
9973
  outputAsset: CheckoutAssetUi.fromOffer(offer, {
9798
9974
  symbol: ondoSymbol,
9799
- networkName: getNetworkName(chain)
9975
+ networkName: getNetworkName(chain),
9976
+ tokenMetadata: outputTokenMetadata
9800
9977
  }),
9801
9978
  outputAmount: assetAmount(
9802
9979
  formatAmount(order.transaction.receiveOutputAmount, locale),
@@ -9816,13 +9993,13 @@ function toOrderConfirmedUi({
9816
9993
  }
9817
9994
 
9818
9995
  // src/client/hooks/checkout/ondo/sell/useOndoSellCheckoutViewModel.ts
9819
- var import_react27 = require("react");
9996
+ var import_react28 = require("react");
9820
9997
 
9821
9998
  // src/client/hooks/checkout/ondo/sell/amount/useOndoSellAmountViewModel.ts
9822
- var import_react24 = require("react");
9999
+ var import_react25 = require("react");
9823
10000
 
9824
10001
  // src/client/hooks/shared/erc20/useErc20Balance.ts
9825
- var import_react23 = require("react");
10002
+ var import_react24 = require("react");
9826
10003
  function useErc20Balance(options) {
9827
10004
  const {
9828
10005
  tokenAddress,
@@ -9833,12 +10010,12 @@ function useErc20Balance(options) {
9833
10010
  } = options;
9834
10011
  const { coinlist, isReady } = useCoinList();
9835
10012
  const log = useLogger("useErc20Balance");
9836
- const [balance, setBalance] = (0, import_react23.useState)(null);
9837
- const [isLoading, setIsLoading] = (0, import_react23.useState)(true);
9838
- const fetchIdRef = (0, import_react23.useRef)(0);
9839
- const isFetchingRef = (0, import_react23.useRef)(false);
9840
- const hasReadRef = (0, import_react23.useRef)(false);
9841
- (0, import_react23.useEffect)(() => {
10013
+ const [balance, setBalance] = (0, import_react24.useState)(null);
10014
+ const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
10015
+ const fetchIdRef = (0, import_react24.useRef)(0);
10016
+ const isFetchingRef = (0, import_react24.useRef)(false);
10017
+ const hasReadRef = (0, import_react24.useRef)(false);
10018
+ (0, import_react24.useEffect)(() => {
9842
10019
  if (!isReady) return;
9843
10020
  setBalance(null);
9844
10021
  hasReadRef.current = false;
@@ -9915,16 +10092,17 @@ function useOndoSellAmountViewModel({
9915
10092
  ondoSymbol,
9916
10093
  chain,
9917
10094
  offer,
10095
+ inputTokenMetadata,
9918
10096
  enabled = true,
9919
10097
  onComplete,
9920
10098
  onEdit
9921
10099
  }) {
9922
10100
  const { coinlist } = useCoinList();
9923
10101
  const locale = useLocale();
9924
- const [amountInput, setAmountInput] = (0, import_react24.useState)("");
9925
- const [error, setError] = (0, import_react24.useState)(null);
9926
- const [phase, setPhase] = (0, import_react24.useState)(null);
9927
- const preparationIdRef = (0, import_react24.useRef)(0);
10102
+ const [amountInput, setAmountInput] = (0, import_react25.useState)("");
10103
+ const [error, setError] = (0, import_react25.useState)(null);
10104
+ const [phase, setPhase] = (0, import_react25.useState)(null);
10105
+ const preparationIdRef = (0, import_react25.useRef)(0);
9928
10106
  const isActive = stepInput.type === "active";
9929
10107
  const networkName = getNetworkName(chain);
9930
10108
  const sellAsset2 = isActive ? stepInput.sellAsset : null;
@@ -9935,7 +10113,7 @@ function useOndoSellAmountViewModel({
9935
10113
  chain,
9936
10114
  enabled: enabled && isActive && sellAsset2 !== null
9937
10115
  });
9938
- (0, import_react24.useEffect)(() => {
10116
+ (0, import_react25.useEffect)(() => {
9939
10117
  if (stepInput.type === "incomplete") {
9940
10118
  ++preparationIdRef.current;
9941
10119
  setAmountInput("");
@@ -9961,7 +10139,8 @@ function useOndoSellAmountViewModel({
9961
10139
  type: "complete",
9962
10140
  asset: CheckoutAssetUi.fromOffer(offer, {
9963
10141
  symbol: stepInput.inputAsset,
9964
- networkName
10142
+ networkName,
10143
+ tokenMetadata: inputTokenMetadata
9965
10144
  }),
9966
10145
  amountFormatted: assetAmount(
9967
10146
  formatAmount(stepInput.amount, locale),
@@ -9983,7 +10162,8 @@ function useOndoSellAmountViewModel({
9983
10162
  return {
9984
10163
  asset: CheckoutAssetUi.fromOffer(offer, {
9985
10164
  symbol: ondoSymbol,
9986
- networkName
10165
+ networkName,
10166
+ tokenMetadata: inputTokenMetadata
9987
10167
  }),
9988
10168
  balance: assetAmount(formatAmount(amount, locale), ondoSymbol),
9989
10169
  rawBalance: balance
@@ -10170,15 +10350,15 @@ function preparationErrorMessage2(error) {
10170
10350
  }
10171
10351
 
10172
10352
  // src/client/hooks/checkout/ondo/sell/review/useOndoSellReviewViewModel.ts
10173
- var import_react26 = require("react");
10353
+ var import_react27 = require("react");
10174
10354
 
10175
10355
  // src/client/hooks/checkout/ondo/sell/data/useOndoSellTransaction.ts
10176
- var import_react25 = require("react");
10356
+ var import_react26 = require("react");
10177
10357
  function useOndoSellTransaction(options) {
10178
10358
  const { request, data, enabled } = options;
10179
10359
  const { coinlist, isReady } = useCoinList();
10180
10360
  const log = useLogger("useOndoSellTransaction");
10181
- const [state, setState] = (0, import_react25.useState)(
10361
+ const [state, setState] = (0, import_react26.useState)(
10182
10362
  () => data === void 0 ? { type: "LOADING" } : {
10183
10363
  type: "CONTENT",
10184
10364
  transaction: data,
@@ -10186,12 +10366,12 @@ function useOndoSellTransaction(options) {
10186
10366
  refreshError: null
10187
10367
  }
10188
10368
  );
10189
- const fetchIdRef = (0, import_react25.useRef)(0);
10190
- const isFetchingRef = (0, import_react25.useRef)(false);
10369
+ const fetchIdRef = (0, import_react26.useRef)(0);
10370
+ const isFetchingRef = (0, import_react26.useRef)(false);
10191
10371
  const requestKey = request === null ? null : stableKey2(request);
10192
- const requestRef = (0, import_react25.useRef)(request);
10372
+ const requestRef = (0, import_react26.useRef)(request);
10193
10373
  requestRef.current = request;
10194
- const build = (0, import_react25.useCallback)(async () => {
10374
+ const build = (0, import_react26.useCallback)(async () => {
10195
10375
  const params = requestRef.current;
10196
10376
  if (!isReady || !enabled || params === null) return;
10197
10377
  if (isFetchingRef.current) return;
@@ -10227,7 +10407,7 @@ function useOndoSellTransaction(options) {
10227
10407
  isFetchingRef.current = false;
10228
10408
  }
10229
10409
  }, [coinlist, isReady, enabled, log]);
10230
- (0, import_react25.useEffect)(() => {
10410
+ (0, import_react26.useEffect)(() => {
10231
10411
  if (data === void 0) return;
10232
10412
  ++fetchIdRef.current;
10233
10413
  setState({
@@ -10238,14 +10418,14 @@ function useOndoSellTransaction(options) {
10238
10418
  });
10239
10419
  }, [data]);
10240
10420
  const hasSeed = data !== void 0;
10241
- (0, import_react25.useEffect)(() => {
10421
+ (0, import_react26.useEffect)(() => {
10242
10422
  if (hasSeed || requestKey === null) return;
10243
10423
  build();
10244
10424
  return () => {
10245
10425
  ++fetchIdRef.current;
10246
10426
  };
10247
10427
  }, [build, requestKey, hasSeed]);
10248
- const refetch = (0, import_react25.useCallback)(() => {
10428
+ const refetch = (0, import_react26.useCallback)(() => {
10249
10429
  build();
10250
10430
  }, [build]);
10251
10431
  return { state, refetch };
@@ -10270,8 +10450,8 @@ function useOndoSellReviewViewModel({
10270
10450
  }) {
10271
10451
  const { coinlist } = useCoinList();
10272
10452
  const locale = useLocale();
10273
- const [phase, setPhase] = (0, import_react26.useState)(null);
10274
- const [error, setError] = (0, import_react26.useState)(null);
10453
+ const [phase, setPhase] = (0, import_react27.useState)(null);
10454
+ const [error, setError] = (0, import_react27.useState)(null);
10275
10455
  const isActive = stepInput.type === "active";
10276
10456
  const { state: transactionState, refetch } = useOndoSellTransaction({
10277
10457
  request: isActive ? {
@@ -10283,8 +10463,8 @@ function useOndoSellReviewViewModel({
10283
10463
  data: isActive ? stepInput.transaction : void 0,
10284
10464
  enabled: enabled && isActive
10285
10465
  });
10286
- const executionIdRef = (0, import_react26.useRef)(0);
10287
- (0, import_react26.useEffect)(() => {
10466
+ const executionIdRef = (0, import_react27.useRef)(0);
10467
+ (0, import_react27.useEffect)(() => {
10288
10468
  if (stepInput.type === "incomplete") {
10289
10469
  ++executionIdRef.current;
10290
10470
  setError(null);
@@ -10494,12 +10674,12 @@ function useOndoSellCheckoutViewModel({
10494
10674
  onOrderConfirmed
10495
10675
  }) {
10496
10676
  const locale = useLocale();
10497
- const [initialStep] = (0, import_react27.useState)(
10677
+ const [initialStep] = (0, import_react28.useState)(
10498
10678
  () => wallets.preselected === null ? { type: "wallet" } : { type: "amount", wallet: wallets.preselected }
10499
10679
  );
10500
- const [step, setStep] = (0, import_react27.useState)(initialStep);
10680
+ const [step, setStep] = (0, import_react28.useState)(initialStep);
10501
10681
  const hasWalletStep = initialStep.type === "wallet";
10502
- const [orderConfirmed, setOrderConfirmed] = (0, import_react27.useState)({ type: "hidden" });
10682
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react28.useState)(null);
10503
10683
  const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
10504
10684
  const live = enabled && swappableHere;
10505
10685
  const { state: priceState } = useOndoPrice({
@@ -10515,6 +10695,20 @@ function useOndoSellCheckoutViewModel({
10515
10695
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
10516
10696
  enabled: live
10517
10697
  });
10698
+ const { state: inputTokenMetadataState } = useCheckoutOfferTokenMetadata({
10699
+ offer,
10700
+ chain,
10701
+ enabled: live
10702
+ });
10703
+ const inputTokenMetadata = tokenMetadataOf(inputTokenMetadataState);
10704
+ const orderConfirmedUi = (order) => order === null ? { type: "hidden" } : toOrderConfirmedUi2({
10705
+ order,
10706
+ chain,
10707
+ locale,
10708
+ offer,
10709
+ ondoSymbol,
10710
+ inputTokenMetadata
10711
+ });
10518
10712
  const { state: walletState, onEvent: onWalletEvent } = useOndoWalletSelectViewModel({
10519
10713
  stepInput: walletStepInput2(step),
10520
10714
  wallets,
@@ -10531,6 +10725,7 @@ function useOndoSellCheckoutViewModel({
10531
10725
  ondoSymbol,
10532
10726
  chain,
10533
10727
  offer,
10728
+ inputTokenMetadata,
10534
10729
  enabled: live,
10535
10730
  // Both transitions read the step through the updater rather than the one
10536
10731
  // this render closed over. Preparing an amount takes an approval to mine,
@@ -10563,9 +10758,7 @@ function useOndoSellCheckoutViewModel({
10563
10758
  chain,
10564
10759
  enabled: live,
10565
10760
  onComplete: (order) => {
10566
- setOrderConfirmed(
10567
- toOrderConfirmedUi2({ order, chain, locale, offer, ondoSymbol })
10568
- );
10761
+ setOrderConfirmed(order);
10569
10762
  setStep(initialStep);
10570
10763
  onOrderConfirmed?.(order);
10571
10764
  }
@@ -10574,6 +10767,7 @@ function useOndoSellCheckoutViewModel({
10574
10767
  offer,
10575
10768
  ondoSymbol,
10576
10769
  chain,
10770
+ tokenMetadata: inputTokenMetadata,
10577
10771
  priceState,
10578
10772
  tradingStatusState
10579
10773
  });
@@ -10583,7 +10777,7 @@ function useOndoSellCheckoutViewModel({
10583
10777
  amount: amountState,
10584
10778
  review: reviewState,
10585
10779
  sidebar: sidebarState,
10586
- orderConfirmed
10780
+ orderConfirmed: orderConfirmedUi(orderConfirmed)
10587
10781
  };
10588
10782
  const onEvent = (event) => {
10589
10783
  switch (event.type) {
@@ -10607,7 +10801,7 @@ function useOndoSellCheckoutViewModel({
10607
10801
  onReviewEvent(event);
10608
10802
  return;
10609
10803
  case "ON_CLOSE_SELL_ORDER_CONFIRMED":
10610
- setOrderConfirmed({ type: "hidden" });
10804
+ setOrderConfirmed(null);
10611
10805
  return;
10612
10806
  default: {
10613
10807
  const exhaustive = event;
@@ -10675,14 +10869,16 @@ function toOrderConfirmedUi2({
10675
10869
  chain,
10676
10870
  locale,
10677
10871
  offer,
10678
- ondoSymbol
10872
+ ondoSymbol,
10873
+ inputTokenMetadata
10679
10874
  }) {
10680
10875
  const settlementSymbol = TOKEN_REGISTRY.erc20(ONDO_SETTLEMENT_ASSET).symbol;
10681
10876
  return {
10682
10877
  type: "visible",
10683
10878
  soldAsset: CheckoutAssetUi.fromOffer(offer, {
10684
10879
  symbol: ondoSymbol,
10685
- networkName: getNetworkName(chain)
10880
+ networkName: getNetworkName(chain),
10881
+ tokenMetadata: inputTokenMetadata
10686
10882
  }),
10687
10883
  soldAmount: assetAmount(
10688
10884
  formatAmount(order.transaction.spendInputAmount, locale),
@@ -10706,10 +10902,10 @@ function toOrderConfirmedUi2({
10706
10902
  }
10707
10903
 
10708
10904
  // src/client/hooks/checkout/superstate/swap/useSuperstateSwapCheckoutViewModel.ts
10709
- var import_react33 = require("react");
10905
+ var import_react34 = require("react");
10710
10906
 
10711
10907
  // src/client/hooks/checkout/superstate/swap/amount/useSuperstateAmountViewModel.ts
10712
- var import_react28 = require("react");
10908
+ var import_react29 = require("react");
10713
10909
  var NO_WALLET3 = EvmWalletAddress(
10714
10910
  "0x0000000000000000000000000000000000000000"
10715
10911
  );
@@ -10723,11 +10919,11 @@ function useSuperstateAmountViewModel({
10723
10919
  enabled = true
10724
10920
  }) {
10725
10921
  const locale = useLocale();
10726
- const [amountInput, setAmountInput] = (0, import_react28.useState)("");
10727
- const [selectedAsset, setSelectedAsset] = (0, import_react28.useState)(
10922
+ const [amountInput, setAmountInput] = (0, import_react29.useState)("");
10923
+ const [selectedAsset, setSelectedAsset] = (0, import_react29.useState)(
10728
10924
  SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]
10729
10925
  );
10730
- const [error, setError] = (0, import_react28.useState)(null);
10926
+ const [error, setError] = (0, import_react29.useState)(null);
10731
10927
  const isActive = stepInput.type === "active";
10732
10928
  const networkName = getNetworkName(chain);
10733
10929
  const { balances, isLoading: balancesLoading } = useErc20TokenBalances({
@@ -10740,7 +10936,7 @@ function useSuperstateAmountViewModel({
10740
10936
  // on this step satisfies the first and not the second.
10741
10937
  enabled: enabled && isActive
10742
10938
  });
10743
- (0, import_react28.useEffect)(() => {
10939
+ (0, import_react29.useEffect)(() => {
10744
10940
  if (stepInput.type === "incomplete") {
10745
10941
  setAmountInput("");
10746
10942
  setSelectedAsset(SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]);
@@ -10911,20 +11107,20 @@ function toInputAssetUi2({
10911
11107
  }
10912
11108
 
10913
11109
  // src/client/hooks/checkout/superstate/swap/data/useSwapOutputToken.ts
10914
- var import_react29 = require("react");
10915
- var LOADING_STATE = { type: "LOADING" };
11110
+ var import_react30 = require("react");
11111
+ var LOADING_STATE2 = { type: "LOADING" };
10916
11112
  function useSwapOutputToken(options) {
10917
11113
  const { contractAddress, chain, enabled } = options;
10918
11114
  const { coinlist, isReady } = useCoinList();
10919
11115
  const log = useLogger("useSwapOutputToken");
10920
- const [outputTokenState, setOutputTokenState] = (0, import_react29.useState)(LOADING_STATE);
10921
- const [retryCount, setRetryCount] = (0, import_react29.useState)(0);
10922
- const fetchIdRef = (0, import_react29.useRef)(0);
10923
- const refetch = (0, import_react29.useCallback)(() => {
10924
- setOutputTokenState(LOADING_STATE);
11116
+ const [outputTokenState, setOutputTokenState] = (0, import_react30.useState)(LOADING_STATE2);
11117
+ const [retryCount, setRetryCount] = (0, import_react30.useState)(0);
11118
+ const fetchIdRef = (0, import_react30.useRef)(0);
11119
+ const refetch = (0, import_react30.useCallback)(() => {
11120
+ setOutputTokenState(LOADING_STATE2);
10925
11121
  setRetryCount((count) => count + 1);
10926
11122
  }, []);
10927
- (0, import_react29.useEffect)(() => {
11123
+ (0, import_react30.useEffect)(() => {
10928
11124
  if (!enabled || !isReady) return;
10929
11125
  const currentFetchId = ++fetchIdRef.current;
10930
11126
  const load = async () => {
@@ -10957,7 +11153,7 @@ function useSwapOutputToken(options) {
10957
11153
  }
10958
11154
 
10959
11155
  // src/client/hooks/checkout/superstate/swap/data/useSwapQuote.ts
10960
- var import_react30 = require("react");
11156
+ var import_react31 = require("react");
10961
11157
  function useSwapQuote(options) {
10962
11158
  const {
10963
11159
  contractAddress,
@@ -10970,13 +11166,13 @@ function useSwapQuote(options) {
10970
11166
  } = options;
10971
11167
  const { coinlist, isReady } = useCoinList();
10972
11168
  const log = useLogger("useSwapQuote");
10973
- const [quote, setQuote] = (0, import_react30.useState)(null);
10974
- const [isLoading, setIsLoading] = (0, import_react30.useState)(true);
10975
- const [isRefreshing, setIsRefreshing] = (0, import_react30.useState)(false);
10976
- const isFetchingRef = (0, import_react30.useRef)(false);
10977
- const hasQuoteRef = (0, import_react30.useRef)(false);
10978
- const fetchIdRef = (0, import_react30.useRef)(0);
10979
- (0, import_react30.useEffect)(() => {
11169
+ const [quote, setQuote] = (0, import_react31.useState)(null);
11170
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
11171
+ const [isRefreshing, setIsRefreshing] = (0, import_react31.useState)(false);
11172
+ const isFetchingRef = (0, import_react31.useRef)(false);
11173
+ const hasQuoteRef = (0, import_react31.useRef)(false);
11174
+ const fetchIdRef = (0, import_react31.useRef)(0);
11175
+ (0, import_react31.useEffect)(() => {
10980
11176
  if (!isReady) return;
10981
11177
  if (!enabled) {
10982
11178
  setIsLoading(false);
@@ -11046,7 +11242,7 @@ function useSwapQuote(options) {
11046
11242
  }
11047
11243
 
11048
11244
  // src/client/hooks/checkout/superstate/swap/review/useSuperstateReviewViewModel.ts
11049
- var import_react31 = require("react");
11245
+ var import_react32 = require("react");
11050
11246
  function useSuperstateReviewViewModel({
11051
11247
  stepInput,
11052
11248
  contractAddress,
@@ -11056,11 +11252,11 @@ function useSuperstateReviewViewModel({
11056
11252
  }) {
11057
11253
  const { coinlist, isReady } = useCoinList();
11058
11254
  const locale = useLocale();
11059
- const [slippageBps, setSlippageBps] = (0, import_react31.useState)(DEFAULT_SLIPPAGE_BPS);
11060
- const [slippageExpanded, setSlippageExpanded] = (0, import_react31.useState)(false);
11061
- const [phase, setPhase] = (0, import_react31.useState)(null);
11062
- const [error, setError] = (0, import_react31.useState)(null);
11063
- (0, import_react31.useEffect)(() => {
11255
+ const [slippageBps, setSlippageBps] = (0, import_react32.useState)(DEFAULT_SLIPPAGE_BPS);
11256
+ const [slippageExpanded, setSlippageExpanded] = (0, import_react32.useState)(false);
11257
+ const [phase, setPhase] = (0, import_react32.useState)(null);
11258
+ const [error, setError] = (0, import_react32.useState)(null);
11259
+ (0, import_react32.useEffect)(() => {
11064
11260
  if (stepInput.type === "incomplete") {
11065
11261
  setSlippageBps(DEFAULT_SLIPPAGE_BPS);
11066
11262
  setSlippageExpanded(false);
@@ -11389,7 +11585,7 @@ function priceUi(quote, outputToken, locale) {
11389
11585
  }
11390
11586
 
11391
11587
  // src/client/hooks/checkout/superstate/swap/wallet/useSuperstateWalletViewModel.ts
11392
- var import_react32 = require("react");
11588
+ var import_react33 = require("react");
11393
11589
  var CONNECT_FAILED2 = "Could not connect that wallet. Please try again.";
11394
11590
  function useSuperstateWalletViewModel({
11395
11591
  stepInput,
@@ -11402,12 +11598,12 @@ function useSuperstateWalletViewModel({
11402
11598
  }) {
11403
11599
  const { coinlist, isReady } = useCoinList();
11404
11600
  const log = useLogger("useSuperstateWalletViewModel");
11405
- const [selected, setSelected] = (0, import_react32.useState)(null);
11406
- const [phase, setPhase] = (0, import_react32.useState)(null);
11407
- const [error, setError] = (0, import_react32.useState)(null);
11601
+ const [selected, setSelected] = (0, import_react33.useState)(null);
11602
+ const [phase, setPhase] = (0, import_react33.useState)(null);
11603
+ const [error, setError] = (0, import_react33.useState)(null);
11408
11604
  const networkName = getNetworkName(chain);
11409
11605
  const selectedWallet = resolveWallet2(wallets, selected);
11410
- (0, import_react32.useEffect)(() => {
11606
+ (0, import_react33.useEffect)(() => {
11411
11607
  if (stepInput.type === "completed") {
11412
11608
  setPhase(null);
11413
11609
  setError(null);
@@ -11626,12 +11822,20 @@ function useSuperstateSwapCheckoutViewModel({
11626
11822
  }) {
11627
11823
  const locale = useLocale();
11628
11824
  const contractAddress = superstateSwapContractAddress(chain);
11629
- const assetIconUrl = offerIconUrl(offer);
11630
- const [step, setStep] = (0, import_react33.useState)({ type: "wallet" });
11631
- const [orderConfirmed, setOrderConfirmed] = (0, import_react33.useState)({ type: "hidden" });
11825
+ const [step, setStep] = (0, import_react34.useState)({ type: "wallet" });
11826
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react34.useState)(null);
11632
11827
  const { inputAmount, inputTokenAddress } = quoteInput(step, chain);
11633
11828
  const live = enabled && contractAddress !== null;
11634
11829
  const contract = contractAddress ?? NO_CONTRACT;
11830
+ const { state: offerTokenMetadataState } = useCheckoutOfferTokenMetadata({
11831
+ offer,
11832
+ chain,
11833
+ enabled: live
11834
+ });
11835
+ const assetIconUrl = offerAssetIconUrl(
11836
+ offer,
11837
+ tokenMetadataOf(offerTokenMetadataState)
11838
+ );
11635
11839
  const { outputTokenState, refetch: refetchOutputToken } = useSwapOutputToken({
11636
11840
  contractAddress: contract,
11637
11841
  chain,
@@ -11688,9 +11892,7 @@ function useSuperstateSwapCheckoutViewModel({
11688
11892
  chain,
11689
11893
  assetIconUrl,
11690
11894
  onComplete: (order) => {
11691
- setOrderConfirmed(
11692
- toOrderConfirmedUi3({ order, chain, locale, assetIconUrl })
11693
- );
11895
+ setOrderConfirmed(order);
11694
11896
  setStep({ type: "wallet" });
11695
11897
  onOrderConfirmed?.(order);
11696
11898
  }
@@ -11716,7 +11918,15 @@ function useSuperstateSwapCheckoutViewModel({
11716
11918
  amount: amountState,
11717
11919
  review: reviewState,
11718
11920
  sidebar: sidebarState,
11719
- orderConfirmed
11921
+ // Derived here rather than in the review completion callback, so a
11922
+ // registry lookup that settles while the order is being placed still
11923
+ // reaches the dialog instead of the fallback icon that closure captured.
11924
+ orderConfirmed: orderConfirmed === null ? { type: "hidden" } : toOrderConfirmedUi3({
11925
+ order: orderConfirmed,
11926
+ chain,
11927
+ locale,
11928
+ assetIconUrl
11929
+ })
11720
11930
  };
11721
11931
  };
11722
11932
  const onEvent = (event) => {
@@ -11741,7 +11951,7 @@ function useSuperstateSwapCheckoutViewModel({
11741
11951
  onReviewEvent(event);
11742
11952
  return;
11743
11953
  case "ON_CLOSE_ORDER_CONFIRMED":
11744
- setOrderConfirmed({ type: "hidden" });
11954
+ setOrderConfirmed(null);
11745
11955
  return;
11746
11956
  case "ON_RETRY_LOAD":
11747
11957
  refetchOutputToken();
@@ -11856,7 +12066,7 @@ function CheckoutContainer({
11856
12066
  enabled = true,
11857
12067
  className
11858
12068
  }) {
11859
- const [side] = (0, import_react34.useState)(() => config["ondo::swap"].side());
12069
+ const [side] = (0, import_react35.useState)(() => config["ondo::swap"].side());
11860
12070
  const isOndo = offer.type === "ondo::swap";
11861
12071
  const ondoSymbol = config["ondo::swap"].symbol(offer);
11862
12072
  const ondoBuy = useOndoBuyCheckoutViewModel({
@@ -12429,23 +12639,23 @@ function EmptyState() {
12429
12639
  }
12430
12640
 
12431
12641
  // src/client/hooks/offers/grid/useOffersGridViewModel.ts
12432
- var import_react36 = require("react");
12642
+ var import_react37 = require("react");
12433
12643
 
12434
12644
  // src/client/hooks/offers/data/useOffers.ts
12435
- var import_react35 = require("react");
12436
- var LOADING_STATE2 = { type: "LOADING" };
12645
+ var import_react36 = require("react");
12646
+ var LOADING_STATE3 = { type: "LOADING" };
12437
12647
  function useOffers(options = {}) {
12438
12648
  const { coinlist, isReady } = useCoinList();
12439
12649
  const log = useLogger("useOffers");
12440
12650
  const { data: serverOffers } = options;
12441
- const [offersState, setOffersState] = (0, import_react35.useState)(
12442
- serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE2
12651
+ const [offersState, setOffersState] = (0, import_react36.useState)(
12652
+ serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE3
12443
12653
  );
12444
- (0, import_react35.useEffect)(() => {
12654
+ (0, import_react36.useEffect)(() => {
12445
12655
  let isCancelled = false;
12446
12656
  if (!isReady) {
12447
12657
  if (serverOffers === void 0) {
12448
- setOffersState(LOADING_STATE2);
12658
+ setOffersState(LOADING_STATE3);
12449
12659
  }
12450
12660
  return () => {
12451
12661
  isCancelled = true;
@@ -12456,7 +12666,7 @@ function useOffers(options = {}) {
12456
12666
  isCancelled = true;
12457
12667
  };
12458
12668
  }
12459
- setOffersState(LOADING_STATE2);
12669
+ setOffersState(LOADING_STATE3);
12460
12670
  coinlist.offers.list().then((offers) => {
12461
12671
  if (!isCancelled) {
12462
12672
  log.debug(() => ({
@@ -12507,11 +12717,11 @@ var GENERIC_ERROR_MESSAGE = "Unable to load offers right now. Please try again."
12507
12717
  function useOffersGridViewModel(options = {}) {
12508
12718
  const { data, onOfferClick } = options;
12509
12719
  const { offersState } = useOffers({ data });
12510
- const state = (0, import_react36.useMemo)(
12720
+ const state = (0, import_react37.useMemo)(
12511
12721
  () => toUiState(offersState, onOfferClick !== void 0),
12512
12722
  [offersState, onOfferClick]
12513
12723
  );
12514
- const onEvent = (0, import_react36.useCallback)(
12724
+ const onEvent = (0, import_react37.useCallback)(
12515
12725
  (event) => {
12516
12726
  switch (event.type) {
12517
12727
  case "ON_OFFER_CLICK": {
@@ -12571,14 +12781,14 @@ function OffersGridContainer({
12571
12781
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(OffersGridView, { state, onEvent, ...viewProps });
12572
12782
  }
12573
12783
 
12574
- // src/client/components/requirements/checklist/ConnectedWalletList.tsx
12575
- var import_react37 = require("react");
12784
+ // src/client/components/requirements/ConnectedWalletList.tsx
12785
+ var import_react38 = require("react");
12576
12786
  var import_jsx_runtime56 = require("react/jsx-runtime");
12577
12787
  function ConnectedWalletRow({
12578
12788
  wallet,
12579
12789
  onRemove
12580
12790
  }) {
12581
- const [state, setState] = (0, import_react37.useState)("idle");
12791
+ const [state, setState] = (0, import_react38.useState)("idle");
12582
12792
  const remove = async () => {
12583
12793
  if (!onRemove) return;
12584
12794
  setState("removing");
@@ -12687,12 +12897,228 @@ function ConnectedWalletListBody({
12687
12897
  );
12688
12898
  }
12689
12899
 
12690
- // src/client/components/requirements/checklist/RequirementItem.tsx
12900
+ // src/client/components/requirements/identity-verification/IdentityVerificationView.tsx
12901
+ var import_websdk_react = __toESM(require("@sumsub/websdk-react"), 1);
12902
+ var import_jsx_runtime57 = require("react/jsx-runtime");
12903
+ function IdentityVerificationView(props) {
12904
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IdentityVerificationViewBody, { ...props }) });
12905
+ }
12906
+ function IdentityVerificationViewBody({
12907
+ state,
12908
+ onEvent,
12909
+ className
12910
+ }) {
12911
+ switch (state.type) {
12912
+ case "loading":
12913
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
12914
+ "output",
12915
+ {
12916
+ "aria-live": "polite",
12917
+ className: cn(
12918
+ "clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center",
12919
+ className
12920
+ ),
12921
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading identity verification..." })
12922
+ }
12923
+ );
12924
+ case "error":
12925
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
12926
+ "div",
12927
+ {
12928
+ className: cn(
12929
+ "clcosdk:flex clcosdk:flex-col clcosdk:gap-4",
12930
+ className
12931
+ ),
12932
+ children: [
12933
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AlertBanner, { variant: "error", icon: true, content: state.message }),
12934
+ state.retryable && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ClButton, { size: "sm", onClick: () => onEvent({ type: "ON_RETRY" }), children: "Try again" })
12935
+ ]
12936
+ }
12937
+ );
12938
+ case "ready":
12939
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: cn("clcosdk:w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
12940
+ import_websdk_react.default,
12941
+ {
12942
+ accessToken: state.accessToken,
12943
+ expirationHandler: state.refreshToken,
12944
+ config: state.locale === void 0 ? {} : { lang: state.locale },
12945
+ options: { addViewportTag: false, adaptIframeHeight: true },
12946
+ onMessage: (type, payload) => {
12947
+ onSumsubMessage(type, payload, onEvent);
12948
+ },
12949
+ onError: (error) => {
12950
+ onEvent({ type: "ON_ERROR", error: toError(error) });
12951
+ }
12952
+ }
12953
+ ) });
12954
+ default: {
12955
+ const exhaustive = state;
12956
+ return exhaustive;
12957
+ }
12958
+ }
12959
+ }
12960
+ function onSumsubMessage(type, payload, onEvent) {
12961
+ switch (type) {
12962
+ case "idCheck.onApplicantSubmitted":
12963
+ onEvent({ type: "ON_SUBMITTED" });
12964
+ return;
12965
+ case "idCheck.onError": {
12966
+ const message = payload?.message ?? "Verification error";
12967
+ onEvent({ type: "ON_ERROR", error: new Error(message) });
12968
+ return;
12969
+ }
12970
+ default:
12971
+ return;
12972
+ }
12973
+ }
12974
+ function toError(error) {
12975
+ return error instanceof Error ? error : new Error("Verification error");
12976
+ }
12977
+
12978
+ // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
12979
+ var import_react40 = require("react");
12980
+
12981
+ // src/client/hooks/requirements/data/useKycToken.ts
12982
+ var import_react39 = require("react");
12983
+ var IDLE_STATE = { type: "IDLE" };
12984
+ var LOADING_STATE4 = { type: "LOADING" };
12985
+ function useKycToken(levelName, reset) {
12986
+ const { coinlist } = useCoinList();
12987
+ const log = useLogger("useKycToken");
12988
+ const [kycTokenState, setKycTokenState] = (0, import_react39.useState)(IDLE_STATE);
12989
+ const resetPendingRef = (0, import_react39.useRef)(reset === true);
12990
+ const tokenIssuedRef = (0, import_react39.useRef)(false);
12991
+ (0, import_react39.useEffect)(() => {
12992
+ if (!tokenIssuedRef.current) {
12993
+ resetPendingRef.current = reset === true;
12994
+ }
12995
+ }, [reset]);
12996
+ const fetchToken = (0, import_react39.useCallback)(async () => {
12997
+ setKycTokenState(LOADING_STATE4);
12998
+ try {
12999
+ const kycToken = await coinlist.requirements.createKycToken({
13000
+ levelName,
13001
+ reset: resetPendingRef.current
13002
+ });
13003
+ resetPendingRef.current = false;
13004
+ tokenIssuedRef.current = true;
13005
+ log.debug(() => ({
13006
+ msg: "settled",
13007
+ fields: { state: "CONTENT" }
13008
+ }));
13009
+ setKycTokenState({ type: "CONTENT", token: kycToken.token });
13010
+ return kycToken.token;
13011
+ } catch (error) {
13012
+ const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
13013
+ log.failure(
13014
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
13015
+ error
13016
+ );
13017
+ setKycTokenState({ type: "ERROR", reason });
13018
+ throw error;
13019
+ }
13020
+ }, [coinlist, levelName, log]);
13021
+ return { kycTokenState, fetchToken };
13022
+ }
13023
+
13024
+ // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
13025
+ var NOT_AUTHENTICATED_MESSAGE2 = "Sign in to verify your identity.";
13026
+ var GENERIC_ERROR_MESSAGE2 = "Unable to start identity verification right now. Please try again.";
13027
+ function useIdentityVerificationViewModel(options = {}) {
13028
+ const { levelName, reset, locale, onSubmitted, onError } = options;
13029
+ const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
13030
+ const fetchedRef = (0, import_react40.useRef)(false);
13031
+ (0, import_react40.useEffect)(() => {
13032
+ if (fetchedRef.current) {
13033
+ return;
13034
+ }
13035
+ fetchedRef.current = true;
13036
+ fetchToken().catch(() => {
13037
+ });
13038
+ }, [fetchToken]);
13039
+ const state = (0, import_react40.useMemo)(() => {
13040
+ switch (kycTokenState.type) {
13041
+ case "IDLE":
13042
+ case "LOADING":
13043
+ return { type: "loading" };
13044
+ case "ERROR": {
13045
+ const notAuthenticated = kycTokenState.reason === "not-authenticated";
13046
+ return {
13047
+ type: "error",
13048
+ message: notAuthenticated ? NOT_AUTHENTICATED_MESSAGE2 : GENERIC_ERROR_MESSAGE2,
13049
+ retryable: !notAuthenticated
13050
+ };
13051
+ }
13052
+ case "CONTENT":
13053
+ return {
13054
+ type: "ready",
13055
+ accessToken: kycTokenState.token,
13056
+ locale,
13057
+ refreshToken: fetchToken
13058
+ };
13059
+ default: {
13060
+ const exhaustive = kycTokenState;
13061
+ return exhaustive;
13062
+ }
13063
+ }
13064
+ }, [kycTokenState, locale, fetchToken]);
13065
+ const onEvent = (0, import_react40.useCallback)(
13066
+ (event) => {
13067
+ switch (event.type) {
13068
+ case "ON_RETRY":
13069
+ fetchToken().catch(() => {
13070
+ });
13071
+ return;
13072
+ case "ON_SUBMITTED":
13073
+ onSubmitted?.();
13074
+ return;
13075
+ case "ON_ERROR":
13076
+ onError?.(event.error);
13077
+ return;
13078
+ default: {
13079
+ const exhaustive = event;
13080
+ return exhaustive;
13081
+ }
13082
+ }
13083
+ },
13084
+ [fetchToken, onSubmitted, onError]
13085
+ );
13086
+ return { state, onEvent };
13087
+ }
13088
+
13089
+ // src/client/components/requirements/identity-verification/IdentityVerificationContainer.tsx
13090
+ var import_jsx_runtime58 = require("react/jsx-runtime");
13091
+ function IdentityVerificationContainer({
13092
+ levelName,
13093
+ reset,
13094
+ locale,
13095
+ onSubmitted,
13096
+ onError,
13097
+ className
13098
+ }) {
13099
+ const { state, onEvent } = useIdentityVerificationViewModel({
13100
+ levelName,
13101
+ reset,
13102
+ locale,
13103
+ onSubmitted,
13104
+ onError
13105
+ });
13106
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13107
+ IdentityVerificationView,
13108
+ {
13109
+ state,
13110
+ onEvent,
13111
+ className
13112
+ }
13113
+ );
13114
+ }
13115
+
13116
+ // src/client/components/requirements/RequirementItem.tsx
12691
13117
  var import_lucide_react15 = require("lucide-react");
12692
13118
 
12693
13119
  // src/client/components/design-system/StepStatusIcon.tsx
12694
13120
  var import_lucide_react14 = require("lucide-react");
12695
- var import_jsx_runtime57 = require("react/jsx-runtime");
13121
+ var import_jsx_runtime59 = require("react/jsx-runtime");
12696
13122
  var statusConfig = {
12697
13123
  required: {
12698
13124
  Icon: import_lucide_react14.Info,
@@ -12717,7 +13143,7 @@ var statusConfig = {
12717
13143
  };
12718
13144
  function StepStatusIcon({ status, className }) {
12719
13145
  const { Icon, colorClass, fillClass } = statusConfig[status];
12720
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13146
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
12721
13147
  Icon,
12722
13148
  {
12723
13149
  className: cn(
@@ -12731,8 +13157,8 @@ function StepStatusIcon({ status, className }) {
12731
13157
  );
12732
13158
  }
12733
13159
 
12734
- // src/client/components/requirements/checklist/RequirementItem.tsx
12735
- var import_jsx_runtime58 = require("react/jsx-runtime");
13160
+ // src/client/components/requirements/RequirementItem.tsx
13161
+ var import_jsx_runtime60 = require("react/jsx-runtime");
12736
13162
  function VerificationActionZone({
12737
13163
  status,
12738
13164
  onAction,
@@ -12741,9 +13167,9 @@ function VerificationActionZone({
12741
13167
  switch (status) {
12742
13168
  case "required":
12743
13169
  if (onAction === null) return null;
12744
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Continue" });
13170
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Continue" });
12745
13171
  case "pending":
12746
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13172
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12747
13173
  AlertBanner,
12748
13174
  {
12749
13175
  variant: "warning",
@@ -12751,16 +13177,16 @@ function VerificationActionZone({
12751
13177
  }
12752
13178
  );
12753
13179
  case "completed":
12754
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(AlertBanner, { variant: "success", content: "Identity verified." });
13180
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(AlertBanner, { variant: "success", content: "Identity verified." });
12755
13181
  case "rejected":
12756
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13182
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12757
13183
  AlertBanner,
12758
13184
  {
12759
13185
  variant: "error",
12760
- content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
13186
+ content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
12761
13187
  "Verification rejected.",
12762
13188
  " ",
12763
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13189
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12764
13190
  "button",
12765
13191
  {
12766
13192
  type: "button",
@@ -12784,8 +13210,8 @@ function WalletActionZone({
12784
13210
  onRemoveWallet
12785
13211
  }) {
12786
13212
  if (multiWallet) {
12787
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
12788
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13213
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
13214
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12789
13215
  ConnectedWalletList,
12790
13216
  {
12791
13217
  wallets: connectedWallets,
@@ -12794,7 +13220,7 @@ function WalletActionZone({
12794
13220
  status: walletsStatus
12795
13221
  }
12796
13222
  ),
12797
- status === "rejected" && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13223
+ status === "rejected" && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12798
13224
  AlertBanner,
12799
13225
  {
12800
13226
  variant: "error",
@@ -12805,21 +13231,21 @@ function WalletActionZone({
12805
13231
  }
12806
13232
  if (status === "completed") {
12807
13233
  const connected = connectedWallets[0];
12808
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
12809
- onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ClButton, { size: "sm", variant: "secondary", onClick: onAction, children: "Change wallet" }),
12810
- walletsStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13234
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
13235
+ onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", variant: "secondary", onClick: onAction, children: "Change wallet" }),
13236
+ walletsStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12811
13237
  AlertBanner,
12812
13238
  {
12813
13239
  variant: "info",
12814
13240
  content: "Loading your connected wallet\u2026"
12815
13241
  }
12816
- ) : walletsStatus === "error" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13242
+ ) : walletsStatus === "error" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12817
13243
  AlertBanner,
12818
13244
  {
12819
13245
  variant: "error",
12820
13246
  content: "Couldn't load your connected wallet."
12821
13247
  }
12822
- ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13248
+ ) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12823
13249
  AlertBanner,
12824
13250
  {
12825
13251
  variant: "success",
@@ -12829,9 +13255,9 @@ function WalletActionZone({
12829
13255
  ] });
12830
13256
  }
12831
13257
  if (status === "rejected") {
12832
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
12833
- onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" }),
12834
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13258
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
13259
+ onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" }),
13260
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12835
13261
  AlertBanner,
12836
13262
  {
12837
13263
  variant: "error",
@@ -12841,7 +13267,7 @@ function WalletActionZone({
12841
13267
  ] });
12842
13268
  }
12843
13269
  if (onAction === null) return null;
12844
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" });
13270
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" });
12845
13271
  }
12846
13272
  function RequirementItem({
12847
13273
  ui,
@@ -12853,7 +13279,7 @@ function RequirementItem({
12853
13279
  walletsStatus,
12854
13280
  onContactSupport
12855
13281
  }) {
12856
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
13282
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
12857
13283
  "div",
12858
13284
  {
12859
13285
  className: cn(
@@ -12861,7 +13287,7 @@ function RequirementItem({
12861
13287
  className
12862
13288
  ),
12863
13289
  children: [
12864
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
13290
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
12865
13291
  "button",
12866
13292
  {
12867
13293
  type: "button",
@@ -12869,9 +13295,9 @@ function RequirementItem({
12869
13295
  "aria-expanded": expanded,
12870
13296
  className: "clcosdk:flex clcosdk:h-14 clcosdk:w-full clcosdk:cursor-pointer clcosdk:items-center clcosdk:justify-between clcosdk:rounded-2xl clcosdk:px-2 clcosdk:transition-colors clcosdk:hover:bg-surface",
12871
13297
  children: [
12872
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-3", children: [
12873
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(StepStatusIcon, { status: ui.status }),
12874
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13298
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-3", children: [
13299
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(StepStatusIcon, { status: ui.status }),
13300
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12875
13301
  "span",
12876
13302
  {
12877
13303
  className: cn(
@@ -12882,7 +13308,7 @@ function RequirementItem({
12882
13308
  }
12883
13309
  )
12884
13310
  ] }),
12885
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13311
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12886
13312
  import_lucide_react15.ChevronRight,
12887
13313
  {
12888
13314
  className: cn(
@@ -12895,15 +13321,15 @@ function RequirementItem({
12895
13321
  ]
12896
13322
  }
12897
13323
  ),
12898
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13324
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12899
13325
  "div",
12900
13326
  {
12901
13327
  className: cn(
12902
13328
  "clcosdk:grid clcosdk:transition-[grid-template-rows] clcosdk:duration-300 clcosdk:ease-in-out",
12903
13329
  expanded ? "clcosdk:grid-rows-[1fr]" : "clcosdk:grid-rows-[0fr]"
12904
13330
  ),
12905
- children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "clcosdk:min-h-0 clcosdk:overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:px-2 clcosdk:pb-4", children: [
12906
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13331
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "clcosdk:min-h-0 clcosdk:overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:px-2 clcosdk:pb-4", children: [
13332
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12907
13333
  "p",
12908
13334
  {
12909
13335
  className: cn(
@@ -12913,14 +13339,14 @@ function RequirementItem({
12913
13339
  children: ui.description
12914
13340
  }
12915
13341
  ),
12916
- ui.variant === "verification" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13342
+ ui.variant === "verification" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12917
13343
  VerificationActionZone,
12918
13344
  {
12919
13345
  status: ui.status,
12920
13346
  onAction,
12921
13347
  onContactSupport
12922
13348
  }
12923
- ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13349
+ ) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12924
13350
  WalletActionZone,
12925
13351
  {
12926
13352
  status: ui.status,
@@ -12939,10 +13365,10 @@ function RequirementItem({
12939
13365
  ) });
12940
13366
  }
12941
13367
 
12942
- // src/client/components/requirements/checklist/RequirementsChecklistView.tsx
12943
- var import_jsx_runtime59 = require("react/jsx-runtime");
13368
+ // src/client/components/requirements/RequirementsChecklistView.tsx
13369
+ var import_jsx_runtime61 = require("react/jsx-runtime");
12944
13370
  function RequirementsChecklistView(props) {
12945
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RequirementsChecklistViewBody, { ...props }) });
13371
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(RequirementsChecklistViewBody, { ...props }) });
12946
13372
  }
12947
13373
  function RequirementsChecklistViewBody({
12948
13374
  state,
@@ -12954,11 +13380,11 @@ function RequirementsChecklistViewBody({
12954
13380
  }) {
12955
13381
  switch (state.type) {
12956
13382
  case "loading":
12957
- return loading ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(LoadingState2, {});
13383
+ return loading ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(LoadingState2, {});
12958
13384
  case "not-authenticated":
12959
13385
  return unauthenticatedState ?? null;
12960
13386
  case "error":
12961
- return error ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13387
+ return error ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
12962
13388
  AlertBanner,
12963
13389
  {
12964
13390
  variant: "error",
@@ -12968,7 +13394,7 @@ function RequirementsChecklistViewBody({
12968
13394
  }
12969
13395
  );
12970
13396
  case "content":
12971
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
13397
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
12972
13398
  "div",
12973
13399
  {
12974
13400
  className: cn(
@@ -12976,11 +13402,11 @@ function RequirementsChecklistViewBody({
12976
13402
  className
12977
13403
  ),
12978
13404
  children: [
12979
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
12980
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: state.title }),
12981
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: state.description })
13405
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13406
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: state.title }),
13407
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: state.description })
12982
13408
  ] }),
12983
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: state.items.map((row) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13409
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: state.items.map((row) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
12984
13410
  RequirementItem,
12985
13411
  {
12986
13412
  ui: row.item,
@@ -12999,7 +13425,7 @@ function RequirementsChecklistViewBody({
12999
13425
  },
13000
13426
  row.id
13001
13427
  )) }),
13002
- state.ineligible && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13428
+ state.ineligible && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13003
13429
  AlertBanner,
13004
13430
  {
13005
13431
  variant: "error",
@@ -13007,7 +13433,7 @@ function RequirementsChecklistViewBody({
13007
13433
  content: "You are not eligible to participate."
13008
13434
  }
13009
13435
  ),
13010
- state.continueAction && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13436
+ state.continueAction && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13011
13437
  ClButton,
13012
13438
  {
13013
13439
  fullWidth: true,
@@ -13023,270 +13449,21 @@ function RequirementsChecklistViewBody({
13023
13449
  const exhaustive = state;
13024
13450
  return exhaustive;
13025
13451
  }
13026
- }
13027
- }
13028
- function LoadingState2() {
13029
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13030
- "output",
13031
- {
13032
- "aria-live": "polite",
13033
- className: "clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center clcosdk:rounded-2xl clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:p-6",
13034
- children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading requirements..." })
13035
- }
13036
- );
13037
- }
13038
-
13039
- // src/client/components/requirements/checklist/VerificationOverlay.tsx
13040
- var import_jsx_runtime60 = require("react/jsx-runtime");
13041
- function VerificationOverlay({
13042
- onClose,
13043
- children
13044
- }) {
13045
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(VerificationOverlayBody, { onClose, children }) });
13046
- }
13047
- function VerificationOverlayBody({
13048
- onClose,
13049
- children
13050
- }) {
13051
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
13052
- "div",
13053
- {
13054
- role: "dialog",
13055
- "aria-modal": "true",
13056
- "aria-label": "Identity verification",
13057
- className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-overlay clcosdk:p-4",
13058
- children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "clcosdk:relative clcosdk:flex clcosdk:max-h-[92vh] clcosdk:w-full clcosdk:max-w-[760px] clcosdk:flex-col clcosdk:overflow-y-auto clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6 clcosdk:pt-14", children: [
13059
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
13060
- CloseButton,
13061
- {
13062
- onClick: onClose,
13063
- className: "clcosdk:absolute clcosdk:top-4 clcosdk:right-4"
13064
- }
13065
- ),
13066
- children
13067
- ] })
13068
- }
13069
- );
13070
- }
13071
-
13072
- // src/client/components/requirements/identity-verification/IdentityVerificationView.tsx
13073
- var import_websdk_react = __toESM(require("@sumsub/websdk-react"), 1);
13074
- var import_jsx_runtime61 = require("react/jsx-runtime");
13075
- function IdentityVerificationView(props) {
13076
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(IdentityVerificationViewBody, { ...props }) });
13077
- }
13078
- function IdentityVerificationViewBody({
13079
- state,
13080
- onEvent,
13081
- className
13082
- }) {
13083
- switch (state.type) {
13084
- case "loading":
13085
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13086
- "output",
13087
- {
13088
- "aria-live": "polite",
13089
- className: cn(
13090
- "clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center",
13091
- className
13092
- ),
13093
- children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading identity verification..." })
13094
- }
13095
- );
13096
- case "error":
13097
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
13098
- "div",
13099
- {
13100
- className: cn(
13101
- "clcosdk:flex clcosdk:flex-col clcosdk:gap-4",
13102
- className
13103
- ),
13104
- children: [
13105
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(AlertBanner, { variant: "error", icon: true, content: state.message }),
13106
- state.retryable && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(ClButton, { size: "sm", onClick: () => onEvent({ type: "ON_RETRY" }), children: "Try again" })
13107
- ]
13108
- }
13109
- );
13110
- case "ready":
13111
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: cn("clcosdk:w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13112
- import_websdk_react.default,
13113
- {
13114
- accessToken: state.accessToken,
13115
- expirationHandler: state.refreshToken,
13116
- config: state.locale === void 0 ? {} : { lang: state.locale },
13117
- options: { addViewportTag: false, adaptIframeHeight: true },
13118
- onMessage: (type, payload) => {
13119
- onSumsubMessage(type, payload, onEvent);
13120
- },
13121
- onError: (error) => {
13122
- onEvent({ type: "ON_ERROR", error: toError(error) });
13123
- }
13124
- }
13125
- ) });
13126
- default: {
13127
- const exhaustive = state;
13128
- return exhaustive;
13129
- }
13130
- }
13131
- }
13132
- function onSumsubMessage(type, payload, onEvent) {
13133
- switch (type) {
13134
- case "idCheck.onApplicantSubmitted":
13135
- onEvent({ type: "ON_SUBMITTED" });
13136
- return;
13137
- case "idCheck.onError": {
13138
- const message = payload?.message ?? "Verification error";
13139
- onEvent({ type: "ON_ERROR", error: new Error(message) });
13140
- return;
13141
- }
13142
- default:
13143
- return;
13144
- }
13145
- }
13146
- function toError(error) {
13147
- return error instanceof Error ? error : new Error("Verification error");
13148
- }
13149
-
13150
- // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
13151
- var import_react39 = require("react");
13152
-
13153
- // src/client/hooks/requirements/data/useKycToken.ts
13154
- var import_react38 = require("react");
13155
- var IDLE_STATE = { type: "IDLE" };
13156
- var LOADING_STATE3 = { type: "LOADING" };
13157
- function useKycToken(levelName, reset) {
13158
- const { coinlist } = useCoinList();
13159
- const log = useLogger("useKycToken");
13160
- const [kycTokenState, setKycTokenState] = (0, import_react38.useState)(IDLE_STATE);
13161
- const resetPendingRef = (0, import_react38.useRef)(reset === true);
13162
- const tokenIssuedRef = (0, import_react38.useRef)(false);
13163
- (0, import_react38.useEffect)(() => {
13164
- if (!tokenIssuedRef.current) {
13165
- resetPendingRef.current = reset === true;
13166
- }
13167
- }, [reset]);
13168
- const fetchToken = (0, import_react38.useCallback)(async () => {
13169
- setKycTokenState(LOADING_STATE3);
13170
- try {
13171
- const kycToken = await coinlist.requirements.createKycToken({
13172
- levelName,
13173
- reset: resetPendingRef.current
13174
- });
13175
- resetPendingRef.current = false;
13176
- tokenIssuedRef.current = true;
13177
- log.debug(() => ({
13178
- msg: "settled",
13179
- fields: { state: "CONTENT" }
13180
- }));
13181
- setKycTokenState({ type: "CONTENT", token: kycToken.token });
13182
- return kycToken.token;
13183
- } catch (error) {
13184
- const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
13185
- log.failure(
13186
- () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
13187
- error
13188
- );
13189
- setKycTokenState({ type: "ERROR", reason });
13190
- throw error;
13191
- }
13192
- }, [coinlist, levelName, log]);
13193
- return { kycTokenState, fetchToken };
13194
- }
13195
-
13196
- // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
13197
- var NOT_AUTHENTICATED_MESSAGE2 = "Sign in to verify your identity.";
13198
- var GENERIC_ERROR_MESSAGE2 = "Unable to start identity verification right now. Please try again.";
13199
- function useIdentityVerificationViewModel(options = {}) {
13200
- const { levelName, reset, locale, onSubmitted, onError } = options;
13201
- const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
13202
- const fetchedRef = (0, import_react39.useRef)(false);
13203
- (0, import_react39.useEffect)(() => {
13204
- if (fetchedRef.current) {
13205
- return;
13206
- }
13207
- fetchedRef.current = true;
13208
- fetchToken().catch(() => {
13209
- });
13210
- }, [fetchToken]);
13211
- const state = (0, import_react39.useMemo)(() => {
13212
- switch (kycTokenState.type) {
13213
- case "IDLE":
13214
- case "LOADING":
13215
- return { type: "loading" };
13216
- case "ERROR": {
13217
- const notAuthenticated = kycTokenState.reason === "not-authenticated";
13218
- return {
13219
- type: "error",
13220
- message: notAuthenticated ? NOT_AUTHENTICATED_MESSAGE2 : GENERIC_ERROR_MESSAGE2,
13221
- retryable: !notAuthenticated
13222
- };
13223
- }
13224
- case "CONTENT":
13225
- return {
13226
- type: "ready",
13227
- accessToken: kycTokenState.token,
13228
- locale,
13229
- refreshToken: fetchToken
13230
- };
13231
- default: {
13232
- const exhaustive = kycTokenState;
13233
- return exhaustive;
13234
- }
13235
- }
13236
- }, [kycTokenState, locale, fetchToken]);
13237
- const onEvent = (0, import_react39.useCallback)(
13238
- (event) => {
13239
- switch (event.type) {
13240
- case "ON_RETRY":
13241
- fetchToken().catch(() => {
13242
- });
13243
- return;
13244
- case "ON_SUBMITTED":
13245
- onSubmitted?.();
13246
- return;
13247
- case "ON_ERROR":
13248
- onError?.(event.error);
13249
- return;
13250
- default: {
13251
- const exhaustive = event;
13252
- return exhaustive;
13253
- }
13254
- }
13255
- },
13256
- [fetchToken, onSubmitted, onError]
13257
- );
13258
- return { state, onEvent };
13259
- }
13260
-
13261
- // src/client/components/requirements/identity-verification/IdentityVerificationContainer.tsx
13262
- var import_jsx_runtime62 = require("react/jsx-runtime");
13263
- function IdentityVerificationContainer({
13264
- levelName,
13265
- reset,
13266
- locale,
13267
- onSubmitted,
13268
- onError,
13269
- className
13270
- }) {
13271
- const { state, onEvent } = useIdentityVerificationViewModel({
13272
- levelName,
13273
- reset,
13274
- locale,
13275
- onSubmitted,
13276
- onError
13277
- });
13278
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13279
- IdentityVerificationView,
13452
+ }
13453
+ }
13454
+ function LoadingState2() {
13455
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13456
+ "output",
13280
13457
  {
13281
- state,
13282
- onEvent,
13283
- className
13458
+ "aria-live": "polite",
13459
+ className: "clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center clcosdk:rounded-2xl clcosdk:border clcosdk:border-border clcosdk:bg-background clcosdk:p-6",
13460
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading requirements..." })
13284
13461
  }
13285
13462
  );
13286
13463
  }
13287
13464
 
13288
13465
  // src/client/components/requirements/tax-document/TaxDocumentModalView.tsx
13289
- var import_jsx_runtime63 = require("react/jsx-runtime");
13466
+ var import_jsx_runtime62 = require("react/jsx-runtime");
13290
13467
  function TaxDocumentModalView({
13291
13468
  state,
13292
13469
  onEvent,
@@ -13295,7 +13472,7 @@ function TaxDocumentModalView({
13295
13472
  if (state.type === "hidden") {
13296
13473
  return null;
13297
13474
  }
13298
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-black/50 clcosdk:p-4", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
13475
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-black/50 clcosdk:p-4", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
13299
13476
  "div",
13300
13477
  {
13301
13478
  className: cn(
@@ -13303,11 +13480,11 @@ function TaxDocumentModalView({
13303
13480
  className
13304
13481
  ),
13305
13482
  children: [
13306
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
13307
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: state.title }),
13308
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(CloseButton, { onClick: () => onEvent({ type: "ON_CLOSE" }) })
13483
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
13484
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: state.title }),
13485
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(CloseButton, { onClick: () => onEvent({ type: "ON_CLOSE" }) })
13309
13486
  ] }),
13310
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Screen, { screen: state.screen, onEvent })
13487
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Screen, { screen: state.screen, onEvent })
13311
13488
  ]
13312
13489
  }
13313
13490
  ) }) });
@@ -13318,11 +13495,11 @@ function Screen({
13318
13495
  }) {
13319
13496
  switch (screen.type) {
13320
13497
  case "loading":
13321
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(LoadingScreen, {});
13498
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(LoadingScreen, {});
13322
13499
  case "error":
13323
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(AlertBanner, { variant: "error", icon: true, content: screen.message });
13500
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AlertBanner, { variant: "error", icon: true, content: screen.message });
13324
13501
  case "review":
13325
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13502
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13326
13503
  ReviewScreen,
13327
13504
  {
13328
13505
  fields: screen.fields,
@@ -13333,9 +13510,9 @@ function Screen({
13333
13510
  }
13334
13511
  );
13335
13512
  case "editing":
13336
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(EditScreen, { fields: screen.fields, onEvent });
13513
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(EditScreen, { fields: screen.fields, onEvent });
13337
13514
  case "sign-only":
13338
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13515
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13339
13516
  SignOnlyScreen,
13340
13517
  {
13341
13518
  signing: screen.signing,
@@ -13350,14 +13527,14 @@ function Screen({
13350
13527
  }
13351
13528
  }
13352
13529
  function LoadingScreen() {
13353
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13530
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13354
13531
  "output",
13355
13532
  {
13356
13533
  "aria-live": "polite",
13357
13534
  className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4",
13358
- children: [0, 1, 2, 3, 4].map((row) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1", children: [
13359
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "clcosdk:h-3 clcosdk:w-28 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" }),
13360
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "clcosdk:h-5 clcosdk:w-48 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" })
13535
+ children: [0, 1, 2, 3, 4].map((row) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1", children: [
13536
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:h-3 clcosdk:w-28 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" }),
13537
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:h-5 clcosdk:w-48 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" })
13361
13538
  ] }, row))
13362
13539
  }
13363
13540
  );
@@ -13369,9 +13546,9 @@ function ReviewScreen({
13369
13546
  signError,
13370
13547
  onEvent
13371
13548
  }) {
13372
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13373
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Review your information below. If anything looks incorrect, edit before signing." }),
13374
- piiUnavailable && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13549
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13550
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Review your information below. If anything looks incorrect, edit before signing." }),
13551
+ piiUnavailable && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13375
13552
  AlertBanner,
13376
13553
  {
13377
13554
  variant: "info",
@@ -13379,27 +13556,27 @@ function ReviewScreen({
13379
13556
  content: "We don't have this information on file yet \u2014 please fill it in below."
13380
13557
  }
13381
13558
  ),
13382
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: fields.map(({ field, label, displayValue }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
13559
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: fields.map(({ field, label, displayValue }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
13383
13560
  "div",
13384
13561
  {
13385
13562
  className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
13386
13563
  children: [
13387
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13564
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13388
13565
  "span",
13389
13566
  {
13390
13567
  className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
13391
13568
  children: label
13392
13569
  }
13393
13570
  ),
13394
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: displayValue })
13571
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: displayValue })
13395
13572
  ]
13396
13573
  },
13397
13574
  field
13398
13575
  )) }),
13399
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: cn(typeClasses.caption, "clcosdk:text-text-secondary"), children: "By signing, you certify that the information above is accurate and that you are the beneficial owner of the income this form relates to. This document cannot be edited once signed." }),
13400
- signError && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(AlertBanner, { variant: "error", icon: true, content: signError }),
13401
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13402
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13576
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: cn(typeClasses.caption, "clcosdk:text-text-secondary"), children: "By signing, you certify that the information above is accurate and that you are the beneficial owner of the income this form relates to. This document cannot be edited once signed." }),
13577
+ signError && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AlertBanner, { variant: "error", icon: true, content: signError }),
13578
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13579
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13403
13580
  ClButton,
13404
13581
  {
13405
13582
  fullWidth: true,
@@ -13409,7 +13586,7 @@ function ReviewScreen({
13409
13586
  children: "Sign W-8BEN"
13410
13587
  }
13411
13588
  ),
13412
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13589
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13413
13590
  ClButton,
13414
13591
  {
13415
13592
  fullWidth: true,
@@ -13426,20 +13603,20 @@ function EditScreen({
13426
13603
  fields,
13427
13604
  onEvent
13428
13605
  }) {
13429
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13430
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: fields.map(({ field, label, placeholder, value }) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
13606
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13607
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-4 clcosdk:border-t clcosdk:border-divider clcosdk:pt-4", children: fields.map(({ field, label, placeholder, value }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
13431
13608
  "label",
13432
13609
  {
13433
13610
  className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
13434
13611
  children: [
13435
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13612
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13436
13613
  "span",
13437
13614
  {
13438
13615
  className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
13439
13616
  children: label
13440
13617
  }
13441
13618
  ),
13442
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13619
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13443
13620
  "input",
13444
13621
  {
13445
13622
  type: "text",
@@ -13460,9 +13637,9 @@ function EditScreen({
13460
13637
  },
13461
13638
  field
13462
13639
  )) }),
13463
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13464
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(ClButton, { fullWidth: true, onClick: () => onEvent({ type: "ON_SAVE_EDIT" }), children: "Save & review" }),
13465
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13640
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13641
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(ClButton, { fullWidth: true, onClick: () => onEvent({ type: "ON_SAVE_EDIT" }), children: "Save & review" }),
13642
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13466
13643
  ClButton,
13467
13644
  {
13468
13645
  fullWidth: true,
@@ -13479,10 +13656,10 @@ function SignOnlyScreen({
13479
13656
  signError,
13480
13657
  onEvent
13481
13658
  }) {
13482
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13483
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "As an entity investor, you must complete a W-8BEN-E to confirm your foreign tax status and claim applicable treaty benefits. You'll receive an email to complete the signing." }),
13484
- signError && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(AlertBanner, { variant: "error", icon: true, content: signError }),
13485
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13659
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13660
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "As an entity investor, you must complete a W-8BEN-E to confirm your foreign tax status and claim applicable treaty benefits. You'll receive an email to complete the signing." }),
13661
+ signError && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AlertBanner, { variant: "error", icon: true, content: signError }),
13662
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13486
13663
  ClButton,
13487
13664
  {
13488
13665
  fullWidth: true,
@@ -13496,12 +13673,12 @@ function SignOnlyScreen({
13496
13673
  }
13497
13674
 
13498
13675
  // src/client/hooks/requirements/tax-document/useTaxDocumentModalViewModel.ts
13499
- var import_react41 = require("react");
13676
+ var import_react42 = require("react");
13500
13677
 
13501
13678
  // src/client/hooks/requirements/data/useTaxDocument.ts
13502
- var import_react40 = require("react");
13679
+ var import_react41 = require("react");
13503
13680
  var IDLE_SIGN = { type: "idle", error: null };
13504
- var LOADING_STATE4 = { type: "LOADING" };
13681
+ var LOADING_STATE5 = { type: "LOADING" };
13505
13682
  var SIGN_FAILED_MESSAGE = "Unable to sign document. Please try again.";
13506
13683
  var DOB_INVALID_MESSAGE = "Enter your date of birth as MM/DD/YYYY.";
13507
13684
  var FIELD_KEYS = {
@@ -13574,8 +13751,8 @@ function useTaxDocument({
13574
13751
  }) {
13575
13752
  const { coinlist, isReady } = useCoinList();
13576
13753
  const log = useLogger("useTaxDocument");
13577
- const [state, setState] = (0, import_react40.useState)(LOADING_STATE4);
13578
- (0, import_react40.useEffect)(() => {
13754
+ const [state, setState] = (0, import_react41.useState)(LOADING_STATE5);
13755
+ (0, import_react41.useEffect)(() => {
13579
13756
  let isCancelled = false;
13580
13757
  if (!isOpen) {
13581
13758
  return () => {
@@ -13583,12 +13760,12 @@ function useTaxDocument({
13583
13760
  };
13584
13761
  }
13585
13762
  if (!isReady) {
13586
- setState(LOADING_STATE4);
13763
+ setState(LOADING_STATE5);
13587
13764
  return () => {
13588
13765
  isCancelled = true;
13589
13766
  };
13590
13767
  }
13591
- setState(LOADING_STATE4);
13768
+ setState(LOADING_STATE5);
13592
13769
  coinlist.requirements.getPii().then((pii) => {
13593
13770
  if (isCancelled) return;
13594
13771
  if (pii.kind === "company") {
@@ -13616,7 +13793,7 @@ function useTaxDocument({
13616
13793
  isCancelled = true;
13617
13794
  };
13618
13795
  }, [coinlist, isReady, isOpen, log]);
13619
- const onEditField = (0, import_react40.useCallback)(
13796
+ const onEditField = (0, import_react41.useCallback)(
13620
13797
  (field, value) => {
13621
13798
  setState(
13622
13799
  (prev) => prev.type === "EDITING" ? { ...prev, fields: { ...prev.fields, [field]: value } } : prev
@@ -13624,7 +13801,7 @@ function useTaxDocument({
13624
13801
  },
13625
13802
  []
13626
13803
  );
13627
- const onStartEdit = (0, import_react40.useCallback)(() => {
13804
+ const onStartEdit = (0, import_react41.useCallback)(() => {
13628
13805
  setState(
13629
13806
  (prev) => prev.type === "REVIEW" ? {
13630
13807
  type: "EDITING",
@@ -13635,7 +13812,7 @@ function useTaxDocument({
13635
13812
  } : prev
13636
13813
  );
13637
13814
  }, []);
13638
- const onSaveEdit = (0, import_react40.useCallback)(() => {
13815
+ const onSaveEdit = (0, import_react41.useCallback)(() => {
13639
13816
  setState(
13640
13817
  (prev) => prev.type === "EDITING" ? {
13641
13818
  type: "REVIEW",
@@ -13646,7 +13823,7 @@ function useTaxDocument({
13646
13823
  } : prev
13647
13824
  );
13648
13825
  }, []);
13649
- const onCancelEdit = (0, import_react40.useCallback)(() => {
13826
+ const onCancelEdit = (0, import_react41.useCallback)(() => {
13650
13827
  setState(
13651
13828
  (prev) => prev.type === "EDITING" ? {
13652
13829
  type: "REVIEW",
@@ -13657,7 +13834,7 @@ function useTaxDocument({
13657
13834
  } : prev
13658
13835
  );
13659
13836
  }, []);
13660
- const onSign = (0, import_react40.useCallback)(() => {
13837
+ const onSign = (0, import_react41.useCallback)(() => {
13661
13838
  if (state.type !== "REVIEW" && state.type !== "SIGN_ONLY") return;
13662
13839
  if (state.type === "REVIEW" && state.fields.dob.trim() !== "" && !isValidUsDate(state.fields.dob)) {
13663
13840
  setState({
@@ -13699,19 +13876,19 @@ function useTaxDocumentModalViewModel({
13699
13876
  onSubmitted
13700
13877
  }) {
13701
13878
  const { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign } = useTaxDocument({ isOpen });
13702
- (0, import_react41.useEffect)(() => {
13879
+ (0, import_react42.useEffect)(() => {
13703
13880
  if (state.type === "SUBMITTED") {
13704
13881
  onSubmitted?.(state.submission);
13705
13882
  onClose();
13706
13883
  }
13707
13884
  }, [state]);
13708
- const uiState = (0, import_react41.useMemo)(() => {
13885
+ const uiState = (0, import_react42.useMemo)(() => {
13709
13886
  if (!isOpen || state.type === "SUBMITTED") {
13710
13887
  return { type: "hidden" };
13711
13888
  }
13712
13889
  return { type: "content", title: toTitle(state), screen: toScreen(state) };
13713
13890
  }, [isOpen, state]);
13714
- const onEvent = (0, import_react41.useCallback)(
13891
+ const onEvent = (0, import_react42.useCallback)(
13715
13892
  (event) => {
13716
13893
  switch (event.type) {
13717
13894
  case "ON_CLOSE":
@@ -13794,7 +13971,7 @@ function toFieldsUi(fields) {
13794
13971
  }
13795
13972
 
13796
13973
  // src/client/components/requirements/tax-document/TaxDocumentModalContainer.tsx
13797
- var import_jsx_runtime64 = require("react/jsx-runtime");
13974
+ var import_jsx_runtime63 = require("react/jsx-runtime");
13798
13975
  function TaxDocumentModalContainer({
13799
13976
  isOpen,
13800
13977
  onClose,
@@ -13806,7 +13983,7 @@ function TaxDocumentModalContainer({
13806
13983
  onClose,
13807
13984
  onSubmitted
13808
13985
  });
13809
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
13986
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13810
13987
  TaxDocumentModalView,
13811
13988
  {
13812
13989
  state,
@@ -13816,15 +13993,48 @@ function TaxDocumentModalContainer({
13816
13993
  );
13817
13994
  }
13818
13995
 
13996
+ // src/client/components/requirements/VerificationOverlay.tsx
13997
+ var import_jsx_runtime64 = require("react/jsx-runtime");
13998
+ function VerificationOverlay({
13999
+ onClose,
14000
+ children
14001
+ }) {
14002
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(VerificationOverlayBody, { onClose, children }) });
14003
+ }
14004
+ function VerificationOverlayBody({
14005
+ onClose,
14006
+ children
14007
+ }) {
14008
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
14009
+ "div",
14010
+ {
14011
+ role: "dialog",
14012
+ "aria-modal": "true",
14013
+ "aria-label": "Identity verification",
14014
+ className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-overlay clcosdk:p-4",
14015
+ children: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "clcosdk:relative clcosdk:flex clcosdk:max-h-[92vh] clcosdk:w-full clcosdk:max-w-[760px] clcosdk:flex-col clcosdk:overflow-y-auto clcosdk:rounded-2xl clcosdk:bg-background clcosdk:p-6 clcosdk:pt-14", children: [
14016
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
14017
+ CloseButton,
14018
+ {
14019
+ onClick: onClose,
14020
+ className: "clcosdk:absolute clcosdk:top-4 clcosdk:right-4"
14021
+ }
14022
+ ),
14023
+ children
14024
+ ] })
14025
+ }
14026
+ );
14027
+ }
14028
+
13819
14029
  // src/client/components/requirements/wallet/ConnectWalletModalView.tsx
13820
- var import_react42 = require("react");
14030
+ var import_react43 = require("react");
13821
14031
  var import_jsx_runtime65 = require("react/jsx-runtime");
13822
14032
  function ConnectWalletModalView({
13823
14033
  state,
13824
14034
  onEvent,
13825
14035
  className
13826
14036
  }) {
13827
- const titleId = (0, import_react42.useId)();
14037
+ const titleId = (0, import_react43.useId)();
13828
14038
  if (state.type === "hidden") {
13829
14039
  return null;
13830
14040
  }
@@ -13927,10 +14137,10 @@ function Screen2({
13927
14137
  }
13928
14138
 
13929
14139
  // src/client/hooks/requirements/wallet/useConnectWalletModalViewModel.ts
13930
- var import_react44 = require("react");
14140
+ var import_react45 = require("react");
13931
14141
 
13932
14142
  // src/client/hooks/requirements/data/useConnectWallet.ts
13933
- var import_react43 = require("react");
14143
+ var import_react44 = require("react");
13934
14144
 
13935
14145
  // src/client/core/wallets/connect-external-wallet.ts
13936
14146
  var DEFAULT_STATEMENT = "Sign this message to prove you own this wallet. This does not cost gas or move funds.";
@@ -14061,24 +14271,24 @@ function useConnectWallet({
14061
14271
  statement
14062
14272
  }) {
14063
14273
  const { coinlist } = useCoinList();
14064
- const [state, setState] = (0, import_react43.useState)(
14274
+ const [state, setState] = (0, import_react44.useState)(
14065
14275
  () => wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
14066
14276
  );
14067
- const attempt = (0, import_react43.useRef)(0);
14068
- (0, import_react43.useEffect)(() => {
14277
+ const attempt = (0, import_react44.useRef)(0);
14278
+ (0, import_react44.useEffect)(() => {
14069
14279
  attempt.current += 1;
14070
14280
  if (!isOpen) return;
14071
14281
  setState(
14072
14282
  wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
14073
14283
  );
14074
14284
  }, [isOpen, wallet?.address]);
14075
- (0, import_react43.useEffect)(
14285
+ (0, import_react44.useEffect)(
14076
14286
  () => () => {
14077
14287
  attempt.current += 1;
14078
14288
  },
14079
14289
  []
14080
14290
  );
14081
- const onSign = (0, import_react43.useCallback)(() => {
14291
+ const onSign = (0, import_react44.useCallback)(() => {
14082
14292
  if (!wallet || state.type !== "READY") return;
14083
14293
  attempt.current += 1;
14084
14294
  const gen = attempt.current;
@@ -14140,13 +14350,13 @@ function useConnectWalletModalViewModel({
14140
14350
  challengeType,
14141
14351
  statement
14142
14352
  });
14143
- (0, import_react44.useEffect)(() => {
14353
+ (0, import_react45.useEffect)(() => {
14144
14354
  if (state.type === "CONNECTED") {
14145
14355
  onConnected?.(state.binding);
14146
14356
  onClose();
14147
14357
  }
14148
14358
  }, [state]);
14149
- const uiState = (0, import_react44.useMemo)(() => {
14359
+ const uiState = (0, import_react45.useMemo)(() => {
14150
14360
  if (!isOpen || state.type === "CONNECTED") {
14151
14361
  return { type: "hidden" };
14152
14362
  }
@@ -14171,7 +14381,7 @@ function useConnectWalletModalViewModel({
14171
14381
  canRequestConnect
14172
14382
  };
14173
14383
  }, [isOpen, state, onRequestConnect]);
14174
- const onEvent = (0, import_react44.useCallback)(
14384
+ const onEvent = (0, import_react45.useCallback)(
14175
14385
  (event) => {
14176
14386
  switch (event.type) {
14177
14387
  case "ON_CLOSE":
@@ -14211,63 +14421,12 @@ function ConnectWalletModalContainer({
14211
14421
  );
14212
14422
  }
14213
14423
 
14214
- // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
14215
- var import_react47 = require("react");
14216
-
14217
- // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.types.ts
14218
- var RequirementItemUi = {
14219
- fromDomain(req, statusInfo, label, description2, addresses = []) {
14220
- return {
14221
- variant: RequirementVariant.fromType(req.type),
14222
- status: statusInfo ? RequirementStatus.fromStatusValue(statusInfo.status) : "required",
14223
- label,
14224
- description: description2,
14225
- multiWallet: req.type === "whitelisted_wallet",
14226
- connectedWallets: addresses.map((address) => ({
14227
- id: address.id,
14228
- address: address.address,
14229
- shortAddress: shortenAddress(address.address)
14230
- }))
14231
- };
14232
- }
14233
- };
14234
- var RequirementVariant = {
14235
- fromType(type) {
14236
- switch (type) {
14237
- case "external_wallet":
14238
- case "whitelisted_wallet":
14239
- return "wallet";
14240
- default:
14241
- return "verification";
14242
- }
14243
- }
14244
- };
14245
- var RequirementStatus = {
14246
- fromStatusValue(status) {
14247
- switch (status) {
14248
- case "not_started":
14249
- case "action_needed":
14250
- return "required";
14251
- case "in_progress":
14252
- return "pending";
14253
- case "completed":
14254
- return "completed";
14255
- case "rejected":
14256
- return "rejected";
14257
- }
14258
- }
14259
- };
14260
- var ChecklistStatus = {
14261
- derive(statuses) {
14262
- if (statuses.some((s) => s.status === "rejected")) return "ineligible";
14263
- if (statuses.every((s) => s.status === "completed")) return "eligible";
14264
- return "inProgress";
14265
- }
14266
- };
14424
+ // src/client/hooks/requirements/useRequirementsChecklistViewModel.ts
14425
+ var import_react48 = require("react");
14267
14426
 
14268
14427
  // src/client/hooks/requirements/data/useOptionAddresses.ts
14269
- var import_react45 = require("react");
14270
- var LOADING_STATE5 = { type: "LOADING" };
14428
+ var import_react46 = require("react");
14429
+ var LOADING_STATE6 = { type: "LOADING" };
14271
14430
  var EMPTY_STATE = {
14272
14431
  type: "CONTENT",
14273
14432
  addresses: []
@@ -14276,19 +14435,19 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14276
14435
  const { coinlist, isReady } = useCoinList();
14277
14436
  const log = useLogger("useOptionAddresses");
14278
14437
  const { data, enabled = true } = options;
14279
- const [addressesState, setAddressesState] = (0, import_react45.useState)(
14280
- data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE5
14438
+ const [addressesState, setAddressesState] = (0, import_react46.useState)(
14439
+ data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE6
14281
14440
  );
14282
- const [fetchKey, setFetchKey] = (0, import_react45.useState)(0);
14283
- const refetch = (0, import_react45.useCallback)(() => setFetchKey((k) => k + 1), []);
14284
- const disconnect = (0, import_react45.useCallback)(
14441
+ const [fetchKey, setFetchKey] = (0, import_react46.useState)(0);
14442
+ const refetch = (0, import_react46.useCallback)(() => setFetchKey((k) => k + 1), []);
14443
+ const disconnect = (0, import_react46.useCallback)(
14285
14444
  async (addressId) => {
14286
14445
  await coinlist.wallets.remove({ offerId, addressId });
14287
14446
  refetch();
14288
14447
  },
14289
14448
  [coinlist, offerId, refetch]
14290
14449
  );
14291
- (0, import_react45.useEffect)(() => {
14450
+ (0, import_react46.useEffect)(() => {
14292
14451
  let isCancelled = false;
14293
14452
  if (!enabled) {
14294
14453
  setAddressesState(
@@ -14300,7 +14459,7 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14300
14459
  }
14301
14460
  if (!isReady) {
14302
14461
  if (data === void 0) {
14303
- setAddressesState(LOADING_STATE5);
14462
+ setAddressesState(LOADING_STATE6);
14304
14463
  }
14305
14464
  return () => {
14306
14465
  isCancelled = true;
@@ -14317,7 +14476,7 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14317
14476
  isCancelled = true;
14318
14477
  };
14319
14478
  }
14320
- setAddressesState(LOADING_STATE5);
14479
+ setAddressesState(LOADING_STATE6);
14321
14480
  coinlist.wallets.list({ offerId, offerOptionId }).then((addresses) => {
14322
14481
  if (!isCancelled) {
14323
14482
  log.debug(() => ({
@@ -14344,22 +14503,22 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14344
14503
  }
14345
14504
 
14346
14505
  // src/client/hooks/requirements/data/useRequirements.ts
14347
- var import_react46 = require("react");
14348
- var LOADING_STATE6 = { type: "LOADING" };
14506
+ var import_react47 = require("react");
14507
+ var LOADING_STATE7 = { type: "LOADING" };
14349
14508
  function useRequirements(offerId, options = {}) {
14350
14509
  const { coinlist, isReady } = useCoinList();
14351
14510
  const log = useLogger("useRequirements");
14352
14511
  const { data } = options;
14353
- const [requirementsState, setRequirementsState] = (0, import_react46.useState)(
14354
- data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE6
14512
+ const [requirementsState, setRequirementsState] = (0, import_react47.useState)(
14513
+ data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE7
14355
14514
  );
14356
- const [fetchKey, setFetchKey] = (0, import_react46.useState)(0);
14357
- const refetch = (0, import_react46.useCallback)(() => setFetchKey((k) => k + 1), []);
14358
- (0, import_react46.useEffect)(() => {
14515
+ const [fetchKey, setFetchKey] = (0, import_react47.useState)(0);
14516
+ const refetch = (0, import_react47.useCallback)(() => setFetchKey((k) => k + 1), []);
14517
+ (0, import_react47.useEffect)(() => {
14359
14518
  let isCancelled = false;
14360
14519
  if (!isReady) {
14361
14520
  if (data === void 0) {
14362
- setRequirementsState(LOADING_STATE6);
14521
+ setRequirementsState(LOADING_STATE7);
14363
14522
  }
14364
14523
  return () => {
14365
14524
  isCancelled = true;
@@ -14376,7 +14535,7 @@ function useRequirements(offerId, options = {}) {
14376
14535
  isCancelled = true;
14377
14536
  };
14378
14537
  }
14379
- setRequirementsState(LOADING_STATE6);
14538
+ setRequirementsState(LOADING_STATE7);
14380
14539
  Promise.all([
14381
14540
  coinlist.requirements.forOffer(offerId),
14382
14541
  coinlist.requirements.statuses(offerId)
@@ -14413,7 +14572,58 @@ function useRequirements(offerId, options = {}) {
14413
14572
  return { requirementsState, refetch };
14414
14573
  }
14415
14574
 
14416
- // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
14575
+ // src/client/hooks/requirements/useRequirementsChecklistViewModel.types.ts
14576
+ var RequirementItemUi = {
14577
+ fromDomain(req, statusInfo, label, description2, addresses = []) {
14578
+ return {
14579
+ variant: RequirementVariant.fromType(req.type),
14580
+ status: statusInfo ? RequirementStatus.fromStatusValue(statusInfo.status) : "required",
14581
+ label,
14582
+ description: description2,
14583
+ multiWallet: req.type === "whitelisted_wallet",
14584
+ connectedWallets: addresses.map((address) => ({
14585
+ id: address.id,
14586
+ address: address.address,
14587
+ shortAddress: shortenAddress(address.address)
14588
+ }))
14589
+ };
14590
+ }
14591
+ };
14592
+ var RequirementVariant = {
14593
+ fromType(type) {
14594
+ switch (type) {
14595
+ case "external_wallet":
14596
+ case "whitelisted_wallet":
14597
+ return "wallet";
14598
+ default:
14599
+ return "verification";
14600
+ }
14601
+ }
14602
+ };
14603
+ var RequirementStatus = {
14604
+ fromStatusValue(status) {
14605
+ switch (status) {
14606
+ case "not_started":
14607
+ case "action_needed":
14608
+ return "required";
14609
+ case "in_progress":
14610
+ return "pending";
14611
+ case "completed":
14612
+ return "completed";
14613
+ case "rejected":
14614
+ return "rejected";
14615
+ }
14616
+ }
14617
+ };
14618
+ var ChecklistStatus = {
14619
+ derive(statuses) {
14620
+ if (statuses.some((s) => s.status === "rejected")) return "ineligible";
14621
+ if (statuses.every((s) => s.status === "completed")) return "eligible";
14622
+ return "inProgress";
14623
+ }
14624
+ };
14625
+
14626
+ // src/client/hooks/requirements/useRequirementsChecklistViewModel.ts
14417
14627
  var DEFAULT_LABELS = {
14418
14628
  kyc_approved: "KYC Verification",
14419
14629
  external_wallet: "External Wallet",
@@ -14455,19 +14665,19 @@ function useRequirementsChecklistViewModel(options) {
14455
14665
  const log = useLogger("useRequirementsChecklistViewModel");
14456
14666
  const { coinlist } = useCoinList();
14457
14667
  const { requirementsState, refetch } = useRequirements(offerId, { data });
14458
- const [expandedId, setExpandedId] = (0, import_react47.useState)(null);
14459
- const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react47.useState)(false);
14460
- const [connectWalletOpen, setConnectWalletOpen] = (0, import_react47.useState)(false);
14461
- const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react47.useState)(null);
14462
- const isMountedRef = (0, import_react47.useRef)(true);
14463
- (0, import_react47.useEffect)(() => {
14668
+ const [expandedId, setExpandedId] = (0, import_react48.useState)(null);
14669
+ const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react48.useState)(false);
14670
+ const [connectWalletOpen, setConnectWalletOpen] = (0, import_react48.useState)(false);
14671
+ const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react48.useState)(null);
14672
+ const isMountedRef = (0, import_react48.useRef)(true);
14673
+ (0, import_react48.useEffect)(() => {
14464
14674
  isMountedRef.current = true;
14465
14675
  return () => {
14466
14676
  isMountedRef.current = false;
14467
14677
  };
14468
14678
  }, []);
14469
- const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react47.useState)(false);
14470
- (0, import_react47.useEffect)(() => {
14679
+ const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react48.useState)(false);
14680
+ (0, import_react48.useEffect)(() => {
14471
14681
  if (requirementsState.type === "CONTENT") {
14472
14682
  setHasWalletRequirement(
14473
14683
  (requirementsState.requirements[optionId] ?? []).some(
@@ -14483,14 +14693,14 @@ function useRequirementsChecklistViewModel(options) {
14483
14693
  } = useOptionAddresses(offerId, optionId, {
14484
14694
  enabled: hasWalletRequirement
14485
14695
  });
14486
- const removeWallet = (0, import_react47.useCallback)(
14696
+ const removeWallet = (0, import_react48.useCallback)(
14487
14697
  async (addressId) => {
14488
14698
  await disconnect(OfferOptionAddressId(addressId));
14489
14699
  refetch();
14490
14700
  },
14491
14701
  [disconnect, refetch]
14492
14702
  );
14493
- const awaitVerificationResult = (0, import_react47.useCallback)(
14703
+ const awaitVerificationResult = (0, import_react48.useCallback)(
14494
14704
  (requirementId, statusBeforeSubmit) => {
14495
14705
  void (async () => {
14496
14706
  const deadline = Date.now() + VERIFICATION_POLL_TIMEOUT_MS;
@@ -14517,11 +14727,11 @@ function useRequirementsChecklistViewModel(options) {
14517
14727
  },
14518
14728
  [coinlist, offerId, refetch, log]
14519
14729
  );
14520
- const requirements = (0, import_react47.useMemo)(
14730
+ const requirements = (0, import_react48.useMemo)(
14521
14731
  () => requirementsState.type === "CONTENT" ? requirementsState.requirements[optionId] ?? [] : [],
14522
14732
  [requirementsState, optionId]
14523
14733
  );
14524
- const statusById = (0, import_react47.useMemo)(() => {
14734
+ const statusById = (0, import_react48.useMemo)(() => {
14525
14735
  if (requirementsState.type !== "CONTENT") {
14526
14736
  return /* @__PURE__ */ new Map();
14527
14737
  }
@@ -14530,7 +14740,7 @@ function useRequirementsChecklistViewModel(options) {
14530
14740
  requirementsState.statuses.filter((s) => ids.has(s.id)).map((s) => [s.id, s])
14531
14741
  );
14532
14742
  }, [requirementsState, requirements]);
14533
- const state = (0, import_react47.useMemo)(() => {
14743
+ const state = (0, import_react48.useMemo)(() => {
14534
14744
  switch (requirementsState.type) {
14535
14745
  case "LOADING":
14536
14746
  return { type: "loading" };
@@ -14599,7 +14809,7 @@ function useRequirementsChecklistViewModel(options) {
14599
14809
  identityVerificationOptions,
14600
14810
  removeWallet
14601
14811
  ]);
14602
- const handleRequirementAction = (0, import_react47.useCallback)(
14812
+ const handleRequirementAction = (0, import_react48.useCallback)(
14603
14813
  (requirement) => {
14604
14814
  const inlineVerification = statusById.get(requirement.id)?.kycLevel !== void 0 && onRequirementActionOverride === void 0;
14605
14815
  if (inlineVerification) {
@@ -14631,7 +14841,7 @@ function useRequirementsChecklistViewModel(options) {
14631
14841
  coinlist
14632
14842
  ]
14633
14843
  );
14634
- const onEvent = (0, import_react47.useCallback)(
14844
+ const onEvent = (0, import_react48.useCallback)(
14635
14845
  (event) => {
14636
14846
  switch (event.type) {
14637
14847
  case "ON_TOGGLE_ITEM":
@@ -14728,7 +14938,7 @@ function toVerificationUi(verifyingRequirementId, statusById, identityVerificati
14728
14938
  };
14729
14939
  }
14730
14940
 
14731
- // src/client/components/requirements/checklist/RequirementsChecklistContainer.tsx
14941
+ // src/client/components/requirements/RequirementsChecklistContainer.tsx
14732
14942
  var import_jsx_runtime67 = require("react/jsx-runtime");
14733
14943
  function RequirementsChecklistContainer({
14734
14944
  loading,
@@ -14794,10 +15004,10 @@ function RequirementsChecklistContainer({
14794
15004
  ] });
14795
15005
  }
14796
15006
 
14797
- // src/client/core/observability/pino-client-logger.ts
15007
+ // src/client/core/shared/observability/pino-client-logger.ts
14798
15008
  var import_pino = require("pino");
14799
15009
 
14800
- // src/shared/core/observability/pino-logger.ts
15010
+ // src/universal/core/shared/observability/pino-logger.ts
14801
15011
  function toPinoRecord(event) {
14802
15012
  try {
14803
15013
  const record = {};
@@ -14923,7 +15133,7 @@ function reportRenderFailure(sink, error) {
14923
15133
  }
14924
15134
  }
14925
15135
 
14926
- // src/client/core/observability/pino-client-logger.ts
15136
+ // src/client/core/shared/observability/pino-client-logger.ts
14927
15137
  function pinoClientLogger(options) {
14928
15138
  return loggerOverPino(
14929
15139
  // `name` as a child binding rather than pino's `name` option: the option
@@ -14939,18 +15149,18 @@ function pinoClientLogger(options) {
14939
15149
  }
14940
15150
 
14941
15151
  // src/client/hooks/auth/useCompleteOAuth.ts
14942
- var import_react48 = require("react");
15152
+ var import_react49 = require("react");
14943
15153
  function useCompleteOAuth(options) {
14944
15154
  const { coinlist } = useCoinList();
14945
15155
  const log = useLogger("useCompleteOAuth");
14946
- const postOAuthCompleteRef = (0, import_react48.useRef)(options.postOAuthComplete);
14947
- const onFailureRef = (0, import_react48.useRef)(options.onFailure);
14948
- const onSuccessRef = (0, import_react48.useRef)(options.onSuccess);
15156
+ const postOAuthCompleteRef = (0, import_react49.useRef)(options.postOAuthComplete);
15157
+ const onFailureRef = (0, import_react49.useRef)(options.onFailure);
15158
+ const onSuccessRef = (0, import_react49.useRef)(options.onSuccess);
14949
15159
  postOAuthCompleteRef.current = options.postOAuthComplete;
14950
15160
  onFailureRef.current = options.onFailure;
14951
15161
  onSuccessRef.current = options.onSuccess;
14952
- const hasStartedExchangeRef = (0, import_react48.useRef)(false);
14953
- (0, import_react48.useEffect)(() => {
15162
+ const hasStartedExchangeRef = (0, import_react49.useRef)(false);
15163
+ (0, import_react49.useEffect)(() => {
14954
15164
  if (typeof window === "undefined") return;
14955
15165
  const params = new URLSearchParams(window.location.search);
14956
15166
  if (!params.has("code") && !params.has("error")) return;
@@ -15014,20 +15224,20 @@ function useCompleteOAuth(options) {
15014
15224
  }
15015
15225
 
15016
15226
  // src/client/hooks/checkout/coin-list/token-sale/data/useParticipations.ts
15017
- var import_react49 = require("react");
15018
- var LOADING_STATE7 = { type: "LOADING" };
15227
+ var import_react50 = require("react");
15228
+ var LOADING_STATE8 = { type: "LOADING" };
15019
15229
  function useParticipations(offerId, options = {}) {
15020
15230
  const { coinlist, isReady } = useCoinList();
15021
15231
  const log = useLogger("useParticipations");
15022
15232
  const { data } = options;
15023
- const [participationsState, setParticipationsState] = (0, import_react49.useState)(
15024
- data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE7
15233
+ const [participationsState, setParticipationsState] = (0, import_react50.useState)(
15234
+ data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE8
15025
15235
  );
15026
- (0, import_react49.useEffect)(() => {
15236
+ (0, import_react50.useEffect)(() => {
15027
15237
  let isCancelled = false;
15028
15238
  if (!isReady) {
15029
15239
  if (data === void 0) {
15030
- setParticipationsState(LOADING_STATE7);
15240
+ setParticipationsState(LOADING_STATE8);
15031
15241
  }
15032
15242
  return () => {
15033
15243
  isCancelled = true;
@@ -15038,7 +15248,7 @@ function useParticipations(offerId, options = {}) {
15038
15248
  isCancelled = true;
15039
15249
  };
15040
15250
  }
15041
- setParticipationsState(LOADING_STATE7);
15251
+ setParticipationsState(LOADING_STATE8);
15042
15252
  coinlist.tokenSale.list(offerId).then((participations) => {
15043
15253
  if (!isCancelled) {
15044
15254
  log.debug(() => ({
@@ -15065,20 +15275,20 @@ function useParticipations(offerId, options = {}) {
15065
15275
  }
15066
15276
 
15067
15277
  // src/client/hooks/offers/data/useOfferDetails.ts
15068
- var import_react50 = require("react");
15069
- var LOADING_STATE8 = { type: "LOADING" };
15278
+ var import_react51 = require("react");
15279
+ var LOADING_STATE9 = { type: "LOADING" };
15070
15280
  function useOfferDetails(offerId, options = {}) {
15071
15281
  const { coinlist, isReady } = useCoinList();
15072
15282
  const log = useLogger("useOfferDetails");
15073
15283
  const { data } = options;
15074
- const [offerDetailsState, setOfferDetailsState] = (0, import_react50.useState)(
15075
- data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE8
15284
+ const [offerDetailsState, setOfferDetailsState] = (0, import_react51.useState)(
15285
+ data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE9
15076
15286
  );
15077
- (0, import_react50.useEffect)(() => {
15287
+ (0, import_react51.useEffect)(() => {
15078
15288
  let isCancelled = false;
15079
15289
  if (!isReady) {
15080
15290
  if (data === void 0) {
15081
- setOfferDetailsState(LOADING_STATE8);
15291
+ setOfferDetailsState(LOADING_STATE9);
15082
15292
  }
15083
15293
  return () => {
15084
15294
  isCancelled = true;
@@ -15089,7 +15299,7 @@ function useOfferDetails(offerId, options = {}) {
15089
15299
  isCancelled = true;
15090
15300
  };
15091
15301
  }
15092
- setOfferDetailsState(LOADING_STATE8);
15302
+ setOfferDetailsState(LOADING_STATE9);
15093
15303
  coinlist.offers.get(offerId).then((offerDetail) => {
15094
15304
  if (!isCancelled) {
15095
15305
  log.debug(() => ({
@@ -15129,66 +15339,6 @@ var OfferAssetCardUi = {
15129
15339
  })
15130
15340
  };
15131
15341
 
15132
- // src/client/hooks/tokens/data/useTokenMetadata.ts
15133
- var import_react51 = require("react");
15134
- var DISABLED_STATE = { type: "DISABLED" };
15135
- var LOADING_STATE9 = { type: "LOADING" };
15136
- function useTokenMetadata(options) {
15137
- const { chain, address, data, enabled = true } = options;
15138
- const { coinlist, isReady } = useCoinList();
15139
- const log = useLogger("useTokenMetadata");
15140
- const [state, setState] = (0, import_react51.useState)(
15141
- () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE9
15142
- );
15143
- const [refetchCount, setRefetchCount] = (0, import_react51.useState)(0);
15144
- const refetch = (0, import_react51.useCallback)(() => {
15145
- setRefetchCount((count) => count + 1);
15146
- }, []);
15147
- (0, import_react51.useEffect)(() => {
15148
- let isCancelled = false;
15149
- const seedActive = data !== void 0 && refetchCount === 0;
15150
- if (!isReady || !enabled || seedActive) {
15151
- return () => {
15152
- isCancelled = true;
15153
- };
15154
- }
15155
- setState(LOADING_STATE9);
15156
- coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
15157
- if (!isCancelled) {
15158
- log.debug(() => ({
15159
- msg: "settled",
15160
- fields: {
15161
- state: "CONTENT",
15162
- listed: tokenMetadata !== null,
15163
- symbol: tokenMetadata?.symbol ?? null
15164
- }
15165
- }));
15166
- setState({ type: "CONTENT", tokenMetadata });
15167
- }
15168
- }).catch((error) => {
15169
- if (!isCancelled) {
15170
- log.failure(
15171
- () => ({
15172
- msg: "settled",
15173
- fields: { state: "ERROR", reason: "generic-error" }
15174
- }),
15175
- error
15176
- );
15177
- setState({ type: "ERROR", reason: "generic-error" });
15178
- }
15179
- });
15180
- return () => {
15181
- isCancelled = true;
15182
- };
15183
- }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
15184
- return {
15185
- // LOADING would be a lie while disabled: nothing is in flight and nothing
15186
- // will replace it. Settled states (a seed, a previous answer) survive.
15187
- state: !enabled && state.type === "LOADING" ? DISABLED_STATE : state,
15188
- refetch
15189
- };
15190
- }
15191
-
15192
15342
  // src/client/ui/format/date.ts
15193
15343
  function formatMonthYear(date, locale) {
15194
15344
  return new Intl.DateTimeFormat(locale, {
@@ -15278,7 +15428,9 @@ function formatMonthYear(date, locale) {
15278
15428
  formatCountdown,
15279
15429
  formatMonthYear,
15280
15430
  formatSaleCardCountdown,
15431
+ offerAssetIconUrl,
15281
15432
  offerIconUrl,
15433
+ offerTokenIdentifier,
15282
15434
  ondoLoadErrorReason,
15283
15435
  pinoClientLogger,
15284
15436
  prepareOndoBuy,
@@ -15287,6 +15439,9 @@ function formatMonthYear(date, locale) {
15287
15439
  quoteOverAsks,
15288
15440
  stablecoinIconUrl,
15289
15441
  submitErc20Approval,
15442
+ tokenLogoUrl,
15443
+ tokenMetadataOf,
15444
+ useCheckoutOfferTokenMetadata,
15290
15445
  useCoinList,
15291
15446
  useCoinListSignInCardViewModel,
15292
15447
  useCompleteOAuth,