@coinlist-co/react 0.11.1-rc.e102bdb → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{chunk-7CTH4KPU.js → chunk-6CQHDASY.js} +648 -620
  2. package/dist/chunk-6CQHDASY.js.map +1 -0
  3. package/dist/{chunk-UZUQALFY.js → chunk-F6WGUKZC.js} +9 -9
  4. package/dist/chunk-F6WGUKZC.js.map +1 -0
  5. package/dist/{chunk-LSPZETDH.js → chunk-ZFBEI3BW.js} +131 -134
  6. package/dist/chunk-ZFBEI3BW.js.map +1 -0
  7. package/dist/client/index.cjs +1489 -1346
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +395 -254
  10. package/dist/client/index.d.ts +395 -254
  11. package/dist/client/index.js +852 -739
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/{collections-BBI_XydI.d.cts → collections-DOm9VKVm.d.cts} +1 -1
  14. package/dist/{collections-BrX9rRWc.d.ts → collections-aCv-Wr2a.d.ts} +1 -1
  15. package/dist/{config-CMl1bR3F.d.cts → config-DIaFzrMW.d.cts} +56 -13
  16. package/dist/{config-CMl1bR3F.d.ts → config-DIaFzrMW.d.ts} +56 -13
  17. package/dist/server/index.cjs +262 -236
  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 +948 -919
  24. package/dist/universal/index.cjs.map +1 -0
  25. package/dist/{shared → universal}/index.d.cts +566 -536
  26. package/dist/{shared → universal}/index.d.ts +566 -536
  27. package/dist/{shared → universal}/index.js +9 -5
  28. package/package.json +23 -17
  29. package/dist/chunk-7CTH4KPU.js.map +0 -1
  30. package/dist/chunk-LSPZETDH.js.map +0 -1
  31. package/dist/chunk-UZUQALFY.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;
@@ -1346,517 +1389,32 @@ function multiplyAmounts(a, b) {
1346
1389
  return BlockchainAmount({
1347
1390
  raw: product / 10n ** BigInt(b.decimals),
1348
1391
  decimals: a.decimals
1349
- });
1350
- }
1351
- function divideAmounts(a, b) {
1352
- if (b.raw === 0n) {
1353
- throw new MathError("Cannot divide a BlockchainAmount by zero");
1354
- }
1355
- const scaled = a.raw * 10n ** BigInt(b.decimals);
1356
- return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
1357
- }
1358
- function combineAmounts(a, b, op) {
1359
- if (a.decimals !== b.decimals) {
1360
- throw new InvariantError(
1361
- `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
1362
- );
1363
- }
1364
- const raw = op(a.raw, b.raw);
1365
- if (raw < 0n || raw > MAX_UINT_256) {
1366
- throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
1367
- }
1368
- return BlockchainAmount({ raw, decimals: a.decimals });
1369
- }
1370
- var AssetSymbol = (value) => value;
1371
- var StablecoinSymbol = (value) => value;
1372
- var Bps = (value) => value;
1373
-
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
- }
1379
-
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;
1387
-
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
1394
- };
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;
1416
- }
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;
1435
- }
1436
- }
1437
- }
1438
-
1439
- // src/shared/types/providers/superstate/swap.ts
1440
- var SwapAuthorization = {
1441
- fromDto: (dto) => ({
1442
- authorized: dto.authorized
1443
- })
1444
- };
1445
- var SwapPreview = {
1446
- 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
- )
1456
- })
1457
- };
1458
- var SwapStatus = {
1459
- fromDto: (dto) => ({
1460
- stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
1461
- swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
1462
- })
1463
- };
1464
- var TokenAllowance = {
1465
- fromDto: (dto) => ({
1466
- allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
1467
- })
1468
- };
1469
- var TokenBalance = {
1470
- fromDto: (dto) => ({
1471
- balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
1472
- })
1473
- };
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
-
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);
1547
- }
1548
- async function getTokenAllowance(api, params) {
1549
- const dto = await api.send({
1550
- 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
- },
1558
- attributes: Attributes.protected()
1559
- });
1560
- return TokenAllowance.fromDto(dto);
1561
- }
1562
- async function getTokenBalance(api, params) {
1563
- const dto = await api.send({
1564
- method: "GET",
1565
- url: "/v1/token/balance",
1566
- queryParams: {
1567
- chain: params.chain,
1568
- token_address: params.tokenAddress,
1569
- owner: params.owner
1570
- },
1571
- attributes: Attributes.protected()
1572
- });
1573
- return TokenBalance.fromDto(dto);
1574
- }
1575
- async function allowWallet(api, params) {
1576
- const dto = await api.send({
1577
- 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
- },
1584
- attributes: Attributes.protected()
1585
- });
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
- };
1594
- }
1595
-
1596
- // src/shared/core/blockchain/erc20/erc20-namespace.ts
1597
- var Erc20NamespaceImpl = class {
1598
- constructor(ctx) {
1599
- this.ctx = ctx;
1600
- this.log = internalLogger(ctx.logger, "ERC20");
1601
- }
1602
- async getAllowance(params) {
1603
- return this.log.wrap("getAllowance", params, async () => {
1604
- await this.ctx.ensureUserAuthenticated();
1605
- return getTokenAllowance(this.ctx.api, params);
1606
- });
1607
- }
1608
- async getBalance(params) {
1609
- return this.log.wrap("getBalance", params, async () => {
1610
- await this.ctx.ensureUserAuthenticated();
1611
- return getTokenBalance(this.ctx.api, params);
1612
- });
1613
- }
1614
- };
1615
-
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);
1621
- }
1622
- function formatAmount(amount, locale, options) {
1623
- const decimal = formatRawAmount(amount);
1624
- let [integerPart, fractionPart = ""] = decimal.split(".");
1625
- const maxFractionDigits = options?.maxFractionDigits;
1626
- const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
1627
- if (maxFractionDigits !== void 0 && fractionPart.length > maxFractionDigits) {
1628
- ({ integerPart, fractionPart } = roundFractionHalfUp(
1629
- integerPart,
1630
- fractionPart,
1631
- maxFractionDigits
1632
- ));
1633
- }
1634
- const fraction = minFractionDigits === 0 ? "" : fractionPart.padEnd(minFractionDigits, "0");
1635
- const integerFormatted = BigInt(integerPart).toLocaleString(locale);
1636
- if (minFractionDigits === 0 && fraction === "") {
1637
- return FormattedAmountUi(integerFormatted);
1638
- }
1639
- const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
1640
- return FormattedAmountUi(`${integerFormatted}${decimalSeparator}${fraction}`);
1641
- }
1642
- function roundFractionHalfUp(integerPart, fractionPart, maxFractionDigits) {
1643
- if (fractionPart.length <= maxFractionDigits) {
1644
- return { integerPart, fractionPart };
1645
- }
1646
- if (maxFractionDigits === 0) {
1647
- const roundUp = fractionPart[0] >= "5";
1648
- const integer = BigInt(integerPart) + (roundUp ? 1n : 0n);
1649
- return { integerPart: integer.toString(), fractionPart: "" };
1650
- }
1651
- const trimmed = fractionPart.slice(0, maxFractionDigits);
1652
- if (fractionPart[maxFractionDigits] < "5") {
1653
- return { integerPart, fractionPart: trimmed };
1654
- }
1655
- const digits = trimmed.split("").map((digit) => Number.parseInt(digit, 10));
1656
- let carry = 1;
1657
- for (let i = digits.length - 1; i >= 0 && carry > 0; i -= 1) {
1658
- const sum = digits[i] + carry;
1659
- if (sum === 10) {
1660
- digits[i] = 0;
1661
- carry = 1;
1662
- } else {
1663
- digits[i] = sum;
1664
- carry = 0;
1665
- }
1666
- }
1667
- return {
1668
- integerPart: carry > 0 ? (BigInt(integerPart) + 1n).toString() : integerPart,
1669
- fractionPart: digits.join("")
1670
- };
1671
- }
1672
- function formatRawAmount(amount) {
1673
- return (0, import_viem2.formatUnits)(amount.raw, amount.decimals);
1674
- }
1675
- function formatBpsAsPercent(bps, locale) {
1676
- const whole = bps / 100n;
1677
- const fraction = bps % 100n;
1678
- const wholeFormatted = whole.toLocaleString(locale);
1679
- const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
1680
- if (fraction === 0n) {
1681
- return FormattedPercentUi(`${wholeFormatted}%`);
1682
- }
1683
- const fractionFormatted = fraction.toString().padStart(2, "0").replace(/0+$/, "");
1684
- return FormattedPercentUi(
1685
- `${wholeFormatted}${decimalSeparator}${fractionFormatted}%`
1686
- );
1687
- }
1688
- function usdAmount(amount) {
1689
- return FormattedAmountAssetUi(`$${amount}`);
1690
- }
1691
- function assetAmount(amount, symbol) {
1692
- return FormattedAmountAssetUi(`${amount} ${symbol}`);
1693
- }
1694
- var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
1695
- var USD_FRACTION_DIGITS = AssetDecimals(2);
1696
- function formattedUsdPrice(amount, locale) {
1697
- if (!amount) return NA_AMOUNT_ASSET_UI;
1698
- return usdAmount(
1699
- formatAmount(amount, locale, { maxFractionDigits: USD_FRACTION_DIGITS })
1700
- );
1701
- }
1702
-
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;
1392
+ });
1393
+ }
1394
+ function divideAmounts(a, b) {
1395
+ if (b.raw === 0n) {
1396
+ throw new MathError("Cannot divide a BlockchainAmount by zero");
1844
1397
  }
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
- };
1398
+ const scaled = a.raw * 10n ** BigInt(b.decimals);
1399
+ return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
1400
+ }
1401
+ function combineAmounts(a, b, op) {
1402
+ if (a.decimals !== b.decimals) {
1403
+ throw new InvariantError(
1404
+ `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
1405
+ );
1406
+ }
1407
+ const raw = op(a.raw, b.raw);
1408
+ if (raw < 0n || raw > MAX_UINT_256) {
1409
+ throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
1410
+ }
1411
+ return BlockchainAmount({ raw, decimals: a.decimals });
1412
+ }
1413
+ var AssetSymbol = (value) => value;
1414
+ var StablecoinSymbol = (value) => value;
1415
+ var Bps = (value) => value;
1858
1416
 
1859
- // src/shared/types/offer.ts
1417
+ // src/universal/types/offer.ts
1860
1418
  var OfferId = (value) => value;
1861
1419
  var OfferSlug = (value) => value;
1862
1420
  var Offer = {
@@ -1875,7 +1433,7 @@ var Offer = {
1875
1433
  logoUrl: dto.logo_url,
1876
1434
  startsAt: new Date(dto.starts_at),
1877
1435
  endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1878
- tokens: dto.tokens.map(OfferToken.fromDto)
1436
+ tokens: OfferToken.listFromDto(dto.tokens)
1879
1437
  };
1880
1438
  }
1881
1439
  };
@@ -1884,12 +1442,30 @@ var OfferToken = {
1884
1442
  role: dto.role,
1885
1443
  chain: Chain(dto.chain),
1886
1444
  address: EvmContractAddress(dto.address)
1887
- })
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)
1888
1458
  };
1889
1459
 
1890
- // src/shared/types/offer-detail.ts
1460
+ // src/universal/types/offer-detail.ts
1891
1461
  var OfferOptionId = (value) => value;
1892
1462
  var OfferOptionSlug = (value) => value;
1463
+ var OfferSwapContract = {
1464
+ fromDto: (dto) => ({
1465
+ chain: Chain(dto.chain),
1466
+ address: EvmContractAddress(dto.address)
1467
+ })
1468
+ };
1893
1469
  var OfferDetail = {
1894
1470
  fromDto: (dto) => {
1895
1471
  if (!Array.isArray(dto.funding_assets)) {
@@ -1927,6 +1503,12 @@ var OfferDetail = {
1927
1503
  `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1928
1504
  );
1929
1505
  }
1506
+ const swapContracts = dto.swap_contracts === void 0 ? [] : dto.swap_contracts;
1507
+ if (!Array.isArray(swapContracts)) {
1508
+ throw new ValidationError(
1509
+ `OfferDetail.swap_contracts: expected an array, got ${typeof swapContracts}`
1510
+ );
1511
+ }
1930
1512
  return {
1931
1513
  id: OfferId(dto.id),
1932
1514
  slug: OfferSlug(dto.slug),
@@ -1934,7 +1516,8 @@ var OfferDetail = {
1934
1516
  name: dto.name,
1935
1517
  asset: Asset.fromDto(dto.asset),
1936
1518
  fundingAssets: dto.funding_assets.map(Asset.fromDto),
1937
- tokens: dto.tokens.map(OfferToken.fromDto),
1519
+ tokens: OfferToken.listFromDto(dto.tokens),
1520
+ swapContracts: swapContracts.map(OfferSwapContract.fromDto),
1938
1521
  about: notBlankStringOrNull(dto.about),
1939
1522
  tagline: dto.tagline,
1940
1523
  bannerUrl: dto.banner_url,
@@ -1988,7 +1571,7 @@ var Milestone = {
1988
1571
  })
1989
1572
  };
1990
1573
 
1991
- // src/shared/types/providers/coin-list/token-sale.ts
1574
+ // src/universal/types/providers/coin-list/token-sale.ts
1992
1575
  var ParticipationId = (value) => value;
1993
1576
  var Blockchain = (value) => value;
1994
1577
  var WalletAddress = (value) => value;
@@ -2035,7 +1618,7 @@ var CreateParticipationParams = {
2035
1618
  })
2036
1619
  };
2037
1620
 
2038
- // src/shared/api/frontline/providers/coin-list/token-sale.ts
1621
+ // src/universal/api/frontline/providers/coin-list/token-sale.ts
2039
1622
  async function fetchParticipations(api, offerId) {
2040
1623
  return fetchAllPages(
2041
1624
  (params) => fetchParticipationsPage(api, params),
@@ -2069,7 +1652,7 @@ async function createParticipation(api, params) {
2069
1652
  return Participation.fromDto(dto);
2070
1653
  }
2071
1654
 
2072
- // src/shared/core/checkout/coin-list/token-sale-namespace.ts
1655
+ // src/universal/core/checkout/coin-list/token-sale-namespace.ts
2073
1656
  var CoinListTokenSaleNamespaceImpl = class {
2074
1657
  constructor(ctx) {
2075
1658
  this.ctx = ctx;
@@ -2101,15 +1684,70 @@ var CoinListTokenSaleNamespaceImpl = class {
2101
1684
  }
2102
1685
  };
2103
1686
 
2104
- // src/shared/core/checkout/ondo/constants.ts
2105
- var ONDO_SWAP_CONTRACT_ADDRESSES = {
1687
+ // src/universal/core/shared/blockchain/token-registry.ts
1688
+ var USDC_SYMBOL = StablecoinSymbol("USDC");
1689
+ var USDC = {
1690
+ name: "USD Coin",
1691
+ symbol: USDC_SYMBOL,
1692
+ decimals: AssetDecimals(6)
1693
+ };
1694
+ var USDT_SYMBOL = StablecoinSymbol("USDT");
1695
+ var USDT = {
1696
+ name: "Tether USD",
1697
+ symbol: USDT_SYMBOL,
1698
+ decimals: AssetDecimals(6)
1699
+ };
1700
+ var USDC_ADDRESSES = {
1701
+ ethereum_mainnet: EvmContractAddress(
1702
+ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
1703
+ ),
2106
1704
  ethereum_sepolia: EvmContractAddress(
2107
- "0x7014019ed51Edab984a71D30F2707D2dB2316A7A"
1705
+ "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
1706
+ ),
1707
+ base_mainnet: EvmContractAddress(
1708
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
1709
+ ),
1710
+ base_sepolia: EvmContractAddress(
1711
+ "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
2108
1712
  )
2109
1713
  };
2110
- function ondoSwapContractAddress(chain) {
2111
- return ONDO_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
2112
- }
1714
+ var USDT_ADDRESSES = {
1715
+ ethereum_mainnet: EvmContractAddress(
1716
+ "0xdac17f958d2ee523a2206206994597c13d831ec7"
1717
+ ),
1718
+ ethereum_sepolia: EvmContractAddress(
1719
+ "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
1720
+ ),
1721
+ base_mainnet: EvmContractAddress(
1722
+ "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
1723
+ ),
1724
+ base_sepolia: null
1725
+ };
1726
+ var TOKEN_REGISTRY = {
1727
+ erc20: (symbol) => {
1728
+ switch (symbol) {
1729
+ case "USDC":
1730
+ return USDC;
1731
+ case "USDT":
1732
+ return USDT;
1733
+ default:
1734
+ throw new InvariantError(`Unknown asset symbol: ${symbol}`);
1735
+ }
1736
+ },
1737
+ /**
1738
+ * USDC's contract on `chain`. USDC is deployed on every chain the SDK
1739
+ * models, so the table is total and the answer is never `null`.
1740
+ */
1741
+ usdcAddress: (chain) => USDC_ADDRESSES[chain],
1742
+ /**
1743
+ * USDT's contract on `chain`, or `null` where Tether publishes none —
1744
+ * Base Sepolia today. The honest answer, never a fake address a balance
1745
+ * read would call.
1746
+ */
1747
+ usdtAddress: (chain) => USDT_ADDRESSES[chain]
1748
+ };
1749
+
1750
+ // src/universal/core/checkout/ondo/constants.ts
2113
1751
  var ONDO_POLL_INTERVAL_MS = 15e3;
2114
1752
  var ONDO_QUOTE_EXPIRY_THRESHOLD_MS = 5e3;
2115
1753
  var DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString("1000");
@@ -2119,7 +1757,7 @@ var ONDO_SUPPORTED_INPUT_ASSETS = [
2119
1757
  USDC_SYMBOL
2120
1758
  ];
2121
1759
 
2122
- // src/shared/core/checkout/ondo/math.ts
1760
+ // src/universal/core/checkout/ondo/math.ts
2123
1761
  function computeOndoBuyPrice(transaction) {
2124
1762
  const { notionalValue, receiveOutputAmount } = transaction;
2125
1763
  return pricePerShare({
@@ -2127,42 +1765,246 @@ function computeOndoBuyPrice(transaction) {
2127
1765
  shares: receiveOutputAmount
2128
1766
  });
2129
1767
  }
2130
- function computeOndoSellPrice(transaction) {
2131
- const { expected, spendInputAmount } = transaction;
2132
- return pricePerShare({
2133
- usd: grossProceeds(expected),
2134
- shares: spendInputAmount
2135
- });
1768
+ function computeOndoSellPrice(transaction) {
1769
+ const { expected, spendInputAmount } = transaction;
1770
+ return pricePerShare({
1771
+ usd: grossProceeds(expected),
1772
+ shares: spendInputAmount
1773
+ });
1774
+ }
1775
+ function grossProceeds(expected) {
1776
+ const raw = expected.quantity.raw + expected.fee.raw;
1777
+ if (raw > MAX_UINT_256) {
1778
+ throw new MathError(`Ondo sell proceeds: out of uint256 bounds (${raw})`);
1779
+ }
1780
+ return BlockchainAmount.add(expected.quantity, expected.fee);
1781
+ }
1782
+ function pricePerShare({
1783
+ usd,
1784
+ shares
1785
+ }) {
1786
+ const price = BlockchainAmount.div(usd, shares);
1787
+ return BlockchainAmount({
1788
+ raw: assertPriceFits(price.raw),
1789
+ decimals: price.decimals
1790
+ });
1791
+ }
1792
+ function assertPriceFits(raw) {
1793
+ try {
1794
+ return assertUint256(raw);
1795
+ } catch {
1796
+ throw new MathError(`Ondo price: out of uint256 bounds (${raw})`);
1797
+ }
1798
+ }
1799
+
1800
+ // src/universal/core/shared/blockchain/formatters.ts
1801
+ var import_viem2 = require("viem");
1802
+
1803
+ // src/universal/types/blockchain/ui.ts
1804
+ var FormattedAmountUi = (value) => value;
1805
+ var FormattedPercentUi = (value) => value;
1806
+ var TxExplorerUrl = (value) => value;
1807
+ var ShortenedWalletAddress = (value) => value;
1808
+ var FormattedAmountAssetUi = (value) => value;
1809
+ var AssetIconUrl = (value) => value;
1810
+
1811
+ // src/universal/core/shared/blockchain/formatters.ts
1812
+ function shortenAddress(address) {
1813
+ const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
1814
+ return ShortenedWalletAddress(short);
1815
+ }
1816
+ function formatAmount(amount, locale, options) {
1817
+ const decimal = formatRawAmount(amount);
1818
+ let [integerPart, fractionPart = ""] = decimal.split(".");
1819
+ const maxFractionDigits = options?.maxFractionDigits;
1820
+ const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
1821
+ if (maxFractionDigits !== void 0 && fractionPart.length > maxFractionDigits) {
1822
+ ({ integerPart, fractionPart } = roundFractionHalfUp(
1823
+ integerPart,
1824
+ fractionPart,
1825
+ maxFractionDigits
1826
+ ));
1827
+ }
1828
+ const fraction = minFractionDigits === 0 ? "" : fractionPart.padEnd(minFractionDigits, "0");
1829
+ const integerFormatted = BigInt(integerPart).toLocaleString(locale);
1830
+ if (minFractionDigits === 0 && fraction === "") {
1831
+ return FormattedAmountUi(integerFormatted);
1832
+ }
1833
+ const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
1834
+ return FormattedAmountUi(`${integerFormatted}${decimalSeparator}${fraction}`);
1835
+ }
1836
+ function roundFractionHalfUp(integerPart, fractionPart, maxFractionDigits) {
1837
+ if (fractionPart.length <= maxFractionDigits) {
1838
+ return { integerPart, fractionPart };
1839
+ }
1840
+ if (maxFractionDigits === 0) {
1841
+ const roundUp = fractionPart[0] >= "5";
1842
+ const integer = BigInt(integerPart) + (roundUp ? 1n : 0n);
1843
+ return { integerPart: integer.toString(), fractionPart: "" };
1844
+ }
1845
+ const trimmed = fractionPart.slice(0, maxFractionDigits);
1846
+ if (fractionPart[maxFractionDigits] < "5") {
1847
+ return { integerPart, fractionPart: trimmed };
1848
+ }
1849
+ const digits = trimmed.split("").map((digit) => Number.parseInt(digit, 10));
1850
+ let carry = 1;
1851
+ for (let i = digits.length - 1; i >= 0 && carry > 0; i -= 1) {
1852
+ const sum = digits[i] + carry;
1853
+ if (sum === 10) {
1854
+ digits[i] = 0;
1855
+ carry = 1;
1856
+ } else {
1857
+ digits[i] = sum;
1858
+ carry = 0;
1859
+ }
1860
+ }
1861
+ return {
1862
+ integerPart: carry > 0 ? (BigInt(integerPart) + 1n).toString() : integerPart,
1863
+ fractionPart: digits.join("")
1864
+ };
1865
+ }
1866
+ function formatRawAmount(amount) {
1867
+ return (0, import_viem2.formatUnits)(amount.raw, amount.decimals);
1868
+ }
1869
+ function formatBpsAsPercent(bps, locale) {
1870
+ const whole = bps / 100n;
1871
+ const fraction = bps % 100n;
1872
+ const wholeFormatted = whole.toLocaleString(locale);
1873
+ const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
1874
+ if (fraction === 0n) {
1875
+ return FormattedPercentUi(`${wholeFormatted}%`);
1876
+ }
1877
+ const fractionFormatted = fraction.toString().padStart(2, "0").replace(/0+$/, "");
1878
+ return FormattedPercentUi(
1879
+ `${wholeFormatted}${decimalSeparator}${fractionFormatted}%`
1880
+ );
1881
+ }
1882
+ function usdAmount(amount) {
1883
+ return FormattedAmountAssetUi(`$${amount}`);
1884
+ }
1885
+ function assetAmount(amount, symbol) {
1886
+ return FormattedAmountAssetUi(`${amount} ${symbol}`);
1887
+ }
1888
+ var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
1889
+ var USD_FRACTION_DIGITS = AssetDecimals(2);
1890
+ function formattedUsdPrice(amount, locale) {
1891
+ if (!amount) return NA_AMOUNT_ASSET_UI;
1892
+ return usdAmount(
1893
+ formatAmount(amount, locale, { maxFractionDigits: USD_FRACTION_DIGITS })
1894
+ );
1895
+ }
1896
+
1897
+ // src/universal/core/shared/blockchain/chain.ts
1898
+ var CHAIN_IDS = {
1899
+ ethereum_mainnet: 1,
1900
+ ethereum_sepolia: 11155111,
1901
+ base_mainnet: 8453,
1902
+ base_sepolia: 84532
1903
+ };
1904
+ function chainFromId(chainId) {
1905
+ const chains = Object.keys(CHAIN_IDS);
1906
+ const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);
1907
+ if (!chain) {
1908
+ throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
1909
+ }
1910
+ return chain;
1911
+ }
1912
+ function getNetworkName(chain) {
1913
+ switch (chain) {
1914
+ case "ethereum_mainnet":
1915
+ return "Ethereum";
1916
+ case "ethereum_sepolia":
1917
+ return "Ethereum Sepolia";
1918
+ case "base_mainnet":
1919
+ return "Base";
1920
+ case "base_sepolia":
1921
+ return "Base Sepolia";
1922
+ default: {
1923
+ const _exhaustive = chain;
1924
+ return _exhaustive;
1925
+ }
1926
+ }
1927
+ }
1928
+ function txExplorerUrl(chain, txHash) {
1929
+ return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);
2136
1930
  }
2137
- function grossProceeds(expected) {
2138
- const raw = expected.quantity.raw + expected.fee.raw;
2139
- if (raw > MAX_UINT_256) {
2140
- throw new MathError(`Ondo sell proceeds: out of uint256 bounds (${raw})`);
1931
+ function explorerBaseUrl(chain) {
1932
+ switch (chain) {
1933
+ case "ethereum_mainnet":
1934
+ return "https://etherscan.io";
1935
+ case "ethereum_sepolia":
1936
+ return "https://sepolia.etherscan.io";
1937
+ case "base_mainnet":
1938
+ return "https://basescan.org";
1939
+ case "base_sepolia":
1940
+ return "https://sepolia-explorer.base.org";
1941
+ default: {
1942
+ const _exhaustive = chain;
1943
+ return _exhaustive;
1944
+ }
2141
1945
  }
2142
- return BlockchainAmount.add(expected.quantity, expected.fee);
2143
1946
  }
2144
- function pricePerShare({
2145
- usd,
2146
- shares
1947
+
1948
+ // src/universal/core/shared/blockchain/math.ts
1949
+ var import_viem3 = require("viem");
1950
+ function blockchainAmountFromRawOrThrow({
1951
+ label,
1952
+ raw,
1953
+ decimals
2147
1954
  }) {
2148
- const price = BlockchainAmount.div(usd, shares);
2149
- return BlockchainAmount({
2150
- raw: assertPriceFits(price.raw),
2151
- decimals: price.decimals
2152
- });
1955
+ const trimmed = raw.trim();
1956
+ if (trimmed === "") {
1957
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1958
+ }
1959
+ let value;
1960
+ try {
1961
+ value = BigInt(trimmed);
1962
+ } catch {
1963
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1964
+ }
1965
+ try {
1966
+ return BlockchainAmount({ raw: assertUint256(value), decimals });
1967
+ } catch {
1968
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
1969
+ }
2153
1970
  }
2154
- function assertPriceFits(raw) {
1971
+ function parseBlockchainAmount(amount, decimals) {
1972
+ const trimmed = amount.trim();
1973
+ if (trimmed === "") return { valid: false, reason: { type: "empty" } };
1974
+ if (trimmed.startsWith("-")) {
1975
+ return { valid: false, reason: { type: "negative" } };
1976
+ }
1977
+ if (/[eE]/.test(trimmed)) {
1978
+ return { valid: false, reason: { type: "invalid-format" } };
1979
+ }
1980
+ if (!/^\d+(\.\d+)?$/.test(trimmed)) {
1981
+ return { valid: false, reason: { type: "invalid-format" } };
1982
+ }
1983
+ const [, fraction = ""] = trimmed.split(".");
1984
+ if (fraction.length > decimals) {
1985
+ return {
1986
+ valid: false,
1987
+ reason: { type: "too-many-decimals", maxDecimals: decimals }
1988
+ };
1989
+ }
2155
1990
  try {
2156
- return assertUint256(raw);
1991
+ const raw = (0, import_viem3.parseUnits)(trimmed, decimals);
1992
+ if (raw > MAX_UINT_256) {
1993
+ return { valid: false, reason: { type: "overflow" } };
1994
+ }
1995
+ return {
1996
+ valid: true,
1997
+ amount: BlockchainAmount({ raw, decimals })
1998
+ };
2157
1999
  } catch {
2158
- throw new MathError(`Ondo price: out of uint256 bounds (${raw})`);
2000
+ return { valid: false, reason: { type: "invalid-format" } };
2159
2001
  }
2160
2002
  }
2161
2003
 
2162
- // src/shared/types/trading.ts
2004
+ // src/universal/types/trading.ts
2163
2005
  var Ticker = (value) => value;
2164
2006
 
2165
- // src/shared/types/providers/ondo/ondo.ts
2007
+ // src/universal/types/providers/ondo/ondo.ts
2166
2008
  var OndoTradingStatus = {
2167
2009
  fromDto: (dto) => {
2168
2010
  if (!dto.tradable) return { type: "not-tradable", side: dto.side };
@@ -2328,7 +2170,7 @@ function parseExpiresAt(value) {
2328
2170
  return date;
2329
2171
  }
2330
2172
 
2331
- // src/shared/api/frontline/providers/ondo/ondo.ts
2173
+ // src/universal/api/frontline/providers/ondo/ondo.ts
2332
2174
  async function getOndoTradingStatus(api, params) {
2333
2175
  const dto = await api.send({
2334
2176
  method: "GET",
@@ -2423,7 +2265,7 @@ function sizeParam(params) {
2423
2265
  return { notional_value: notionalValue };
2424
2266
  }
2425
2267
 
2426
- // src/shared/core/checkout/ondo/ondo-namespace.ts
2268
+ // src/universal/core/checkout/ondo/ondo-namespace.ts
2427
2269
  var OndoNamespaceImpl = class {
2428
2270
  constructor(ctx) {
2429
2271
  this.ctx = ctx;
@@ -2455,7 +2297,7 @@ var OndoNamespaceImpl = class {
2455
2297
  }
2456
2298
  };
2457
2299
 
2458
- // src/shared/core/checkout/superstate/blockchain/abi.ts
2300
+ // src/universal/core/checkout/superstate/blockchain/abi.ts
2459
2301
  var SUPERSTATE_SWAP_ABI = [
2460
2302
  {
2461
2303
  type: "function",
@@ -2677,7 +2519,13 @@ var SUPERSTATE_SWAP_ABI = [
2677
2519
  }
2678
2520
  ];
2679
2521
 
2680
- // src/shared/core/checkout/superstate/blockchain/math.ts
2522
+ // src/universal/core/shared/blockchain/bps.ts
2523
+ var BPS_DENOM = Bps(10000n);
2524
+ function applyBps(amount, bps) {
2525
+ return assertUint256(amount * bps / BPS_DENOM);
2526
+ }
2527
+
2528
+ // src/universal/core/checkout/superstate/blockchain/math.ts
2681
2529
  function computePrice({
2682
2530
  inputTokenAmount,
2683
2531
  outputTokenAmount
@@ -2694,74 +2542,231 @@ function computeSlip(amount, slippage) {
2694
2542
  const slipRaw = applyBps(amount.raw, retained);
2695
2543
  return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
2696
2544
  }
2697
-
2698
- // src/shared/core/checkout/superstate/blockchain/quote.ts
2699
- var SwapQuote = {
2700
- /**
2701
- * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
2702
- * input and fee are denominated in the input token; the output in the output
2703
- * token.
2704
- */
2705
- fromPreview: (preview, inputDecimals, outputDecimals) => ({
2706
- inputTokenAmount: BlockchainAmount({
2707
- raw: preview.inputAmount,
2708
- decimals: inputDecimals
2709
- }),
2710
- fee: BlockchainAmount({ raw: preview.fee, decimals: inputDecimals }),
2711
- outputTokenAmount: BlockchainAmount({
2712
- raw: preview.outputAmount,
2713
- decimals: outputDecimals
2714
- })
2715
- })
2716
- };
2717
-
2718
- // src/shared/core/checkout/superstate/blockchain/status.ts
2719
- function isStopped(status) {
2720
- return (status.stopped & status.swapLevel) !== 0n;
2545
+
2546
+ // src/universal/core/checkout/superstate/blockchain/quote.ts
2547
+ var SwapQuote = {
2548
+ /**
2549
+ * Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
2550
+ * input and fee are denominated in the input token; the output in the output
2551
+ * token.
2552
+ */
2553
+ fromPreview: (preview, inputDecimals, outputDecimals) => ({
2554
+ inputTokenAmount: BlockchainAmount({
2555
+ raw: preview.inputAmount,
2556
+ decimals: inputDecimals
2557
+ }),
2558
+ fee: BlockchainAmount({ raw: preview.fee, decimals: inputDecimals }),
2559
+ outputTokenAmount: BlockchainAmount({
2560
+ raw: preview.outputAmount,
2561
+ decimals: outputDecimals
2562
+ })
2563
+ })
2564
+ };
2565
+
2566
+ // src/universal/core/checkout/superstate/blockchain/status.ts
2567
+ function isStopped(status) {
2568
+ return (status.stopped & status.swapLevel) !== 0n;
2569
+ }
2570
+
2571
+ // src/universal/core/checkout/superstate/blockchain/swapped-event.ts
2572
+ var import_viem4 = require("viem");
2573
+ function decodeSwappedOutputAmount(receipt, outputDecimals) {
2574
+ try {
2575
+ const [swapped] = (0, import_viem4.parseEventLogs)({
2576
+ abi: SUPERSTATE_SWAP_ABI,
2577
+ eventName: "Swapped",
2578
+ logs: receipt.logs
2579
+ });
2580
+ if (!swapped) return null;
2581
+ const raw = swapped.args.outputAmount;
2582
+ if (raw < 0n || raw > MAX_UINT_256) return null;
2583
+ return BlockchainAmount({ raw, decimals: outputDecimals });
2584
+ } catch {
2585
+ return null;
2586
+ }
2587
+ }
2588
+
2589
+ // src/universal/core/checkout/superstate/constants.ts
2590
+ var SUPERSTATE_ISSUER_NAME = "Superstate";
2591
+ var SUPERSTATE_SUPPORTED_INPUT_ASSETS = [USDC_SYMBOL];
2592
+ var SWAP_POLL_INTERVAL_MS = 15e3;
2593
+ var DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1000000n;
2594
+ var SLIPPAGE_OPTIONS_BPS = [25n, 50n, 100n, 200n, 500n].map(
2595
+ (n) => Bps(n)
2596
+ );
2597
+ var DEFAULT_SLIPPAGE_BPS = Bps(50n);
2598
+ var SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA = EvmContractAddress("0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557");
2599
+ var SUPERSTATE_SWAP_CONTRACT_ADDRESSES = {
2600
+ ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA
2601
+ };
2602
+ function superstateSwapContractAddress(chain) {
2603
+ return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
2604
+ }
2605
+
2606
+ // src/universal/core/checkout/superstate/formatters.ts
2607
+ function formattedPricePerShare(quote, locale) {
2608
+ if (!quote) return NA_AMOUNT_ASSET_UI;
2609
+ return formattedUsdPrice(computePrice(quote), locale);
2610
+ }
2611
+
2612
+ // src/universal/types/providers/superstate/swap.ts
2613
+ var SwapAuthorization = {
2614
+ fromDto: (dto) => ({
2615
+ authorized: dto.authorized
2616
+ })
2617
+ };
2618
+ var SwapPreview = {
2619
+ fromDto: (dto) => ({
2620
+ inputAmount: parseUint256(
2621
+ BigInt(dto.pay_input_amount),
2622
+ "SwapPreview.pay_input_amount"
2623
+ ),
2624
+ fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
2625
+ outputAmount: parseUint256(
2626
+ BigInt(dto.receive_output_amount),
2627
+ "SwapPreview.receive_output_amount"
2628
+ )
2629
+ })
2630
+ };
2631
+ var SwapStatus = {
2632
+ fromDto: (dto) => ({
2633
+ stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
2634
+ swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
2635
+ })
2636
+ };
2637
+ var TokenAllowance = {
2638
+ fromDto: (dto) => ({
2639
+ allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
2640
+ })
2641
+ };
2642
+ var TokenBalance = {
2643
+ fromDto: (dto) => ({
2644
+ balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
2645
+ })
2646
+ };
2647
+ var AllowWalletResponse = {
2648
+ fromDto: (dto) => {
2649
+ switch (dto.action) {
2650
+ case "broadcast_transaction":
2651
+ return {
2652
+ action: "broadcast_transaction",
2653
+ to: EvmContractAddress(dto.to),
2654
+ data: HexEncodedTransactionData(dto.data)
2655
+ };
2656
+ case "none":
2657
+ return {
2658
+ action: "none",
2659
+ alreadyAllowed: dto.already_allowed
2660
+ };
2661
+ default: {
2662
+ const _exhaustive = dto;
2663
+ return _exhaustive;
2664
+ }
2665
+ }
2666
+ }
2667
+ };
2668
+
2669
+ // src/universal/api/frontline/providers/superstate/swap.ts
2670
+ async function getSwapAuthorization(api, params) {
2671
+ const dto = await api.send({
2672
+ method: "GET",
2673
+ url: "/v1/wallet/authorized",
2674
+ queryParams: {
2675
+ chain: params.chain,
2676
+ contract_address: params.contractAddress,
2677
+ wallet_address: params.walletAddress
2678
+ },
2679
+ attributes: Attributes.protected()
2680
+ });
2681
+ return SwapAuthorization.fromDto(dto);
2682
+ }
2683
+ async function getSwapOutputToken(api, params) {
2684
+ const dto = await api.send({
2685
+ method: "GET",
2686
+ url: "/v1/swap/output-token",
2687
+ queryParams: {
2688
+ chain: params.chain,
2689
+ contract_address: params.contractAddress
2690
+ },
2691
+ attributes: Attributes.protected()
2692
+ });
2693
+ return toErc20Asset(dto);
2694
+ }
2695
+ async function getSwapPreview(api, params) {
2696
+ const dto = await api.send({
2697
+ method: "GET",
2698
+ url: "/v1/swap/preview",
2699
+ queryParams: {
2700
+ chain: params.chain,
2701
+ contract_address: params.contractAddress,
2702
+ input_token: params.inputToken,
2703
+ amount: params.amount.toString()
2704
+ },
2705
+ attributes: Attributes.protected()
2706
+ });
2707
+ return SwapPreview.fromDto(dto);
2708
+ }
2709
+ async function getSwapStatus(api, params) {
2710
+ const dto = await api.send({
2711
+ method: "GET",
2712
+ url: "/v1/swap/status",
2713
+ queryParams: {
2714
+ chain: params.chain,
2715
+ contract_address: params.contractAddress
2716
+ },
2717
+ attributes: Attributes.protected()
2718
+ });
2719
+ return SwapStatus.fromDto(dto);
2721
2720
  }
2722
-
2723
- // src/shared/core/checkout/superstate/blockchain/swapped-event.ts
2724
- var import_viem4 = require("viem");
2725
- function decodeSwappedOutputAmount(receipt, outputDecimals) {
2726
- try {
2727
- const [swapped] = (0, import_viem4.parseEventLogs)({
2728
- abi: SUPERSTATE_SWAP_ABI,
2729
- eventName: "Swapped",
2730
- logs: receipt.logs
2731
- });
2732
- if (!swapped) return null;
2733
- const raw = swapped.args.outputAmount;
2734
- if (raw < 0n || raw > MAX_UINT_256) return null;
2735
- return BlockchainAmount({ raw, decimals: outputDecimals });
2736
- } catch {
2737
- return null;
2738
- }
2721
+ async function getTokenAllowance(api, params) {
2722
+ const dto = await api.send({
2723
+ method: "GET",
2724
+ url: "/v1/token/allowance",
2725
+ queryParams: {
2726
+ chain: params.chain,
2727
+ token_address: params.tokenAddress,
2728
+ owner: params.owner,
2729
+ spender: params.spender
2730
+ },
2731
+ attributes: Attributes.protected()
2732
+ });
2733
+ return TokenAllowance.fromDto(dto);
2739
2734
  }
2740
-
2741
- // src/shared/core/checkout/superstate/constants.ts
2742
- var SUPERSTATE_ISSUER_NAME = "Superstate";
2743
- var SUPERSTATE_SUPPORTED_INPUT_ASSETS = [USDC_SYMBOL];
2744
- var SWAP_POLL_INTERVAL_MS = 15e3;
2745
- var DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1000000n;
2746
- var SLIPPAGE_OPTIONS_BPS = [25n, 50n, 100n, 200n, 500n].map(
2747
- (n) => Bps(n)
2748
- );
2749
- var DEFAULT_SLIPPAGE_BPS = Bps(50n);
2750
- var SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA = EvmContractAddress("0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557");
2751
- var SUPERSTATE_SWAP_CONTRACT_ADDRESSES = {
2752
- ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA
2753
- };
2754
- function superstateSwapContractAddress(chain) {
2755
- return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
2735
+ async function getTokenBalance(api, params) {
2736
+ const dto = await api.send({
2737
+ method: "GET",
2738
+ url: "/v1/token/balance",
2739
+ queryParams: {
2740
+ chain: params.chain,
2741
+ token_address: params.tokenAddress,
2742
+ owner: params.owner
2743
+ },
2744
+ attributes: Attributes.protected()
2745
+ });
2746
+ return TokenBalance.fromDto(dto);
2756
2747
  }
2757
-
2758
- // src/shared/core/checkout/superstate/formatters.ts
2759
- function formattedPricePerShare(quote, locale) {
2760
- if (!quote) return NA_AMOUNT_ASSET_UI;
2761
- return formattedUsdPrice(computePrice(quote), locale);
2748
+ async function allowWallet(api, params) {
2749
+ const dto = await api.send({
2750
+ method: "POST",
2751
+ url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
2752
+ body: {
2753
+ wallet_address: params.walletAddress,
2754
+ chain: params.chain,
2755
+ signature: params.signature
2756
+ },
2757
+ attributes: Attributes.protected()
2758
+ });
2759
+ return AllowWalletResponse.fromDto(dto);
2760
+ }
2761
+ function toErc20Asset(dto) {
2762
+ return {
2763
+ name: dto.name,
2764
+ symbol: AssetSymbol(dto.symbol),
2765
+ decimals: AssetDecimals(dto.decimals)
2766
+ };
2762
2767
  }
2763
2768
 
2764
- // src/shared/core/checkout/superstate/swap-namespace.ts
2769
+ // src/universal/core/checkout/superstate/swap-namespace.ts
2765
2770
  var SuperstateSwapNamespaceImpl = class {
2766
2771
  constructor(ctx) {
2767
2772
  this.ctx = ctx;
@@ -2799,7 +2804,7 @@ var SuperstateSwapNamespaceImpl = class {
2799
2804
  }
2800
2805
  };
2801
2806
 
2802
- // src/shared/api/frontline/offers.ts
2807
+ // src/universal/api/frontline/offers.ts
2803
2808
  async function fetchOffers(api, clientCreds) {
2804
2809
  return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
2805
2810
  }
@@ -2828,7 +2833,7 @@ async function fetchOfferDetails(api, id, clientCreds) {
2828
2833
  return OfferDetail.fromDto(dto);
2829
2834
  }
2830
2835
 
2831
- // src/shared/core/offers/offers-namespace.ts
2836
+ // src/universal/core/offers/offers-namespace.ts
2832
2837
  var OffersNamespaceImpl = class {
2833
2838
  constructor(ctx) {
2834
2839
  this.ctx = ctx;
@@ -2854,7 +2859,12 @@ var OffersNamespaceImpl = class {
2854
2859
  }
2855
2860
  };
2856
2861
 
2857
- // src/shared/types/document-submission.ts
2862
+ // src/universal/core/offers/swap-contracts.ts
2863
+ function swapSpender(swapContracts, chain) {
2864
+ return swapContracts.find((contract) => contract.chain === chain)?.address ?? null;
2865
+ }
2866
+
2867
+ // src/universal/types/document-submission.ts
2858
2868
  var DocumentSubmission = {
2859
2869
  fromDto: (dto) => ({
2860
2870
  status: dto.status,
@@ -2862,7 +2872,7 @@ var DocumentSubmission = {
2862
2872
  })
2863
2873
  };
2864
2874
 
2865
- // src/shared/api/frontline/documents.ts
2875
+ // src/universal/api/frontline/documents.ts
2866
2876
  async function submitDocument(api, documentType, fields) {
2867
2877
  const dto = await api.send({
2868
2878
  method: "POST",
@@ -2873,14 +2883,14 @@ async function submitDocument(api, documentType, fields) {
2873
2883
  return DocumentSubmission.fromDto(dto);
2874
2884
  }
2875
2885
 
2876
- // src/shared/types/kyc.ts
2886
+ // src/universal/types/kyc.ts
2877
2887
  var KycToken = {
2878
2888
  fromDto: (dto) => ({
2879
2889
  token: dto.token
2880
2890
  })
2881
2891
  };
2882
2892
 
2883
- // src/shared/api/frontline/kyc.ts
2893
+ // src/universal/api/frontline/kyc.ts
2884
2894
  async function createKycToken(api, levelName, reset) {
2885
2895
  const dto = await api.send({
2886
2896
  method: "POST",
@@ -2894,7 +2904,7 @@ async function createKycToken(api, levelName, reset) {
2894
2904
  return KycToken.fromDto(dto);
2895
2905
  }
2896
2906
 
2897
- // src/shared/types/pii.ts
2907
+ // src/universal/types/pii.ts
2898
2908
  var Iso2CountryCode = (value) => value;
2899
2909
  var PiiJurisdiction = {
2900
2910
  fromDto: (dto) => ({
@@ -2922,7 +2932,7 @@ var Pii = {
2922
2932
  })
2923
2933
  };
2924
2934
 
2925
- // src/shared/api/frontline/pii.ts
2935
+ // src/universal/api/frontline/pii.ts
2926
2936
  async function fetchPii(api) {
2927
2937
  const dto = await api.send({
2928
2938
  method: "GET",
@@ -2932,7 +2942,7 @@ async function fetchPii(api) {
2932
2942
  return Pii.fromDto(dto);
2933
2943
  }
2934
2944
 
2935
- // src/shared/types/requirement.ts
2945
+ // src/universal/types/requirement.ts
2936
2946
  var RequirementId = (value) => value;
2937
2947
  var Requirement = {
2938
2948
  fromDto: (dto) => ({
@@ -2953,7 +2963,7 @@ var RequirementStatusInfo = {
2953
2963
  )
2954
2964
  };
2955
2965
 
2956
- // src/shared/api/frontline/requirements.ts
2966
+ // src/universal/api/frontline/requirements.ts
2957
2967
  async function fetchOfferRequirements(api, offerId, clientCreds) {
2958
2968
  const response = await api.send({
2959
2969
  method: "GET",
@@ -2979,7 +2989,7 @@ async function fetchRequirementStatuses(api, offerId) {
2979
2989
  return RequirementStatusInfo.fromStatusesDto(response);
2980
2990
  }
2981
2991
 
2982
- // src/shared/core/requirements/requirements-namespace.ts
2992
+ // src/universal/core/requirements/requirements-namespace.ts
2983
2993
  var RequirementsNamespaceImpl = class {
2984
2994
  constructor(ctx) {
2985
2995
  this.ctx = ctx;
@@ -3029,10 +3039,30 @@ var RequirementsNamespaceImpl = class {
3029
3039
  }
3030
3040
  };
3031
3041
 
3032
- // src/shared/api/nabu/tokens.ts
3042
+ // src/universal/core/shared/blockchain/erc20/erc20-namespace.ts
3043
+ var Erc20NamespaceImpl = class {
3044
+ constructor(ctx) {
3045
+ this.ctx = ctx;
3046
+ this.log = internalLogger(ctx.logger, "ERC20");
3047
+ }
3048
+ async getAllowance(params) {
3049
+ return this.log.wrap("getAllowance", params, async () => {
3050
+ await this.ctx.ensureUserAuthenticated();
3051
+ return getTokenAllowance(this.ctx.api, params);
3052
+ });
3053
+ }
3054
+ async getBalance(params) {
3055
+ return this.log.wrap("getBalance", params, async () => {
3056
+ await this.ctx.ensureUserAuthenticated();
3057
+ return getTokenBalance(this.ctx.api, params);
3058
+ });
3059
+ }
3060
+ };
3061
+
3062
+ // src/universal/api/nabu/tokens.ts
3033
3063
  var import_viem5 = require("viem");
3034
3064
 
3035
- // src/shared/types/token-metadata.ts
3065
+ // src/universal/types/token-metadata.ts
3036
3066
  var TokenLogoUrl = (value) => value;
3037
3067
  var TokenLogo = {
3038
3068
  /** `baseUrl` is the registry origin; registry URLs are root-relative. */
@@ -3115,7 +3145,7 @@ var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
3115
3145
  url.startsWith("http") ? url : `${baseUrl.replace(/\/$/, "")}${url}`
3116
3146
  );
3117
3147
 
3118
- // src/shared/api/nabu/tokens.ts
3148
+ // src/universal/api/nabu/tokens.ts
3119
3149
  function createNabuApiClient(baseUrl, logger = null) {
3120
3150
  return new HttpClient({ baseUrl }, {}, logger);
3121
3151
  }
@@ -3206,10 +3236,10 @@ function checksummed(address) {
3206
3236
  }
3207
3237
  }
3208
3238
 
3209
- // src/shared/core/tokens/tokens-namespace.ts
3239
+ // src/universal/core/tokens/tokens-namespace.ts
3210
3240
  var TokensNamespaceImpl = class {
3211
3241
  /**
3212
- * Takes the registry origin rather than a `SharedNamespaceContext`: the
3242
+ * Takes the registry origin rather than a `UniversalNamespaceContext`: the
3213
3243
  * registry is unauthenticated and on its own host, so the frontline sender
3214
3244
  * and the auth check would both be dead weight here.
3215
3245
  */
@@ -3233,7 +3263,7 @@ var TokensNamespaceImpl = class {
3233
3263
  }
3234
3264
  };
3235
3265
 
3236
- // src/shared/types/offer-option-address.ts
3266
+ // src/universal/types/offer-option-address.ts
3237
3267
  var OfferOptionAddressId = (value) => value;
3238
3268
  var OfferOptionAddress = {
3239
3269
  /** Maps the API DTO into the SDK offer-option-address domain model. */
@@ -3255,7 +3285,7 @@ var ConnectExternalWalletParams = {
3255
3285
  })
3256
3286
  };
3257
3287
 
3258
- // src/shared/types/wallet-ownership-challenge.ts
3288
+ // src/universal/types/wallet-ownership-challenge.ts
3259
3289
  var WalletOwnershipChallenge = {
3260
3290
  /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
3261
3291
  fromDto: (dto) => ({
@@ -3294,7 +3324,7 @@ var CreateWalletOwnershipChallengeParams = {
3294
3324
  }
3295
3325
  };
3296
3326
 
3297
- // src/shared/api/frontline/wallet-connect.ts
3327
+ // src/universal/api/frontline/wallet-connect.ts
3298
3328
  async function createWalletOwnershipChallenge(api, params) {
3299
3329
  const dto = await api.send({
3300
3330
  method: "POST",
@@ -3331,7 +3361,7 @@ async function removeOptionAddress(api, offerId, addressId) {
3331
3361
  return OfferOptionAddress.fromDto(dto);
3332
3362
  }
3333
3363
 
3334
- // src/shared/core/wallets/wallets-namespace.ts
3364
+ // src/universal/core/wallets/wallets-namespace.ts
3335
3365
  var WalletsNamespaceImpl = class {
3336
3366
  constructor(ctx) {
3337
3367
  this.ctx = ctx;
@@ -3374,7 +3404,7 @@ var WalletsNamespaceImpl = class {
3374
3404
  }
3375
3405
  };
3376
3406
 
3377
- // src/shared/types/blockchain/wallet-error.ts
3407
+ // src/universal/types/blockchain/wallet-error.ts
3378
3408
  var RedactedWalletError = {
3379
3409
  fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
3380
3410
  };
@@ -3458,7 +3488,7 @@ async function executeTokenSale(params) {
3458
3488
  return { type: "success", participation, approvalTxHash };
3459
3489
  }
3460
3490
 
3461
- // src/client/core/observability/flow-logging.ts
3491
+ // src/client/core/shared/observability/flow-logging.ts
3462
3492
  async function withFlowLogging(log, flow, fields, onProgress, run) {
3463
3493
  const flowLog = log.child({ flow });
3464
3494
  flowLog.info(() => ({ msg: "flow started", fields }));
@@ -3550,16 +3580,6 @@ var ClientCoinListTokenSaleNamespaceImpl = class extends CoinListTokenSaleNamesp
3550
3580
  }
3551
3581
  };
3552
3582
 
3553
- // src/shared/core/blockchain/address.ts
3554
- var import_viem6 = require("viem");
3555
- function isSameEvmAddress(a, b) {
3556
- try {
3557
- return (0, import_viem6.isAddressEqual)(a, b);
3558
- } catch {
3559
- return false;
3560
- }
3561
- }
3562
-
3563
3583
  // src/client/core/checkout/ondo/ondo-flows.ts
3564
3584
  async function prepareOndoBuy(params) {
3565
3585
  const { ondo, symbol, chain, wallet, amount } = params;
@@ -3586,9 +3606,17 @@ async function prepareOndoSell(params) {
3586
3606
  );
3587
3607
  }
3588
3608
  async function prepare(params, build) {
3589
- const { erc20, wallet, chain, tokenAddress, amount, onProgress } = params;
3609
+ const {
3610
+ erc20,
3611
+ wallet,
3612
+ chain,
3613
+ swapContracts,
3614
+ tokenAddress,
3615
+ amount,
3616
+ onProgress
3617
+ } = params;
3590
3618
  const emit2 = (phase) => onProgress?.(phase);
3591
- const spender = ondoSwapContractAddress(chain);
3619
+ const spender = swapSpender(swapContracts, chain);
3592
3620
  if (spender === null) {
3593
3621
  return { type: "error", error: { step: "unsupported-chain", chain } };
3594
3622
  }
@@ -3619,16 +3647,6 @@ async function executeOndoSwap(params) {
3619
3647
  if (now.getTime() >= transaction.expiresAt.getTime()) {
3620
3648
  return { type: "error", error: { step: "quote-expired" } };
3621
3649
  }
3622
- const spender = ondoSwapContractAddress(chain);
3623
- if (spender === null || !isSameEvmAddress(transaction.tx.to, spender)) {
3624
- return {
3625
- type: "error",
3626
- error: {
3627
- step: "spender-mismatch",
3628
- expected: spender ?? transaction.tx.to
3629
- }
3630
- };
3631
- }
3632
3650
  emit2("broadcasting-swap");
3633
3651
  let txHash;
3634
3652
  try {
@@ -3920,7 +3938,7 @@ var ClientSuperstateSwapNamespaceImpl = class extends SuperstateSwapNamespaceImp
3920
3938
  }
3921
3939
  };
3922
3940
 
3923
- // src/client/core/utils/open-in-new-tab.ts
3941
+ // src/client/core/shared/utils/open-in-new-tab.ts
3924
3942
  function openInNewTab(url) {
3925
3943
  window.open(url, "_blank", "noopener,noreferrer");
3926
3944
  }
@@ -3978,7 +3996,7 @@ var ClientSupportNamespaceImpl = class {
3978
3996
  }
3979
3997
  };
3980
3998
 
3981
- // src/shared/api/nabu/config.ts
3999
+ // src/universal/api/nabu/config.ts
3982
4000
  var NABU_BASE_URL = "https://asset.coinlist.co";
3983
4001
 
3984
4002
  // src/client/core/coinlist-client.ts
@@ -4116,7 +4134,7 @@ var CoinListProvider = CoinListContextProvider;
4116
4134
  var import_react4 = require("react");
4117
4135
 
4118
4136
  // src/client/generated/sdk-styles.gen.ts
4119
- var sdkStyles = '/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--clcosdk-font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--clcosdk-color-red-400:oklch(70.4% .191 22.216);--clcosdk-color-red-500:oklch(63.7% .237 25.331);--clcosdk-color-amber-500:oklch(76.9% .188 70.08);--clcosdk-color-gray-400:oklch(70.7% .022 261.325);--clcosdk-color-gray-500:oklch(55.1% .027 264.364);--clcosdk-color-black:#000;--clcosdk-spacing:.25rem;--clcosdk-container-sm:24rem;--clcosdk-container-md:28rem;--clcosdk-container-xl:36rem;--clcosdk-text-xs:.75rem;--clcosdk-text-xs--line-height:calc(1 / .75);--clcosdk-text-sm:.875rem;--clcosdk-text-sm--line-height:calc(1.25 / .875);--clcosdk-text-base:1rem;--clcosdk-text-base--line-height:calc(1.5 / 1);--clcosdk-text-lg:1.125rem;--clcosdk-text-lg--line-height:calc(1.75 / 1.125);--clcosdk-font-weight-normal:400;--clcosdk-font-weight-medium:500;--clcosdk-font-weight-semibold:600;--clcosdk-radius-md:.375rem;--clcosdk-radius-lg:.5rem;--clcosdk-radius-xl:.75rem;--clcosdk-radius-2xl:1rem;--clcosdk-ease-out:cubic-bezier(0, 0, .2, 1);--clcosdk-ease-in-out:cubic-bezier(.4, 0, .2, 1);--clcosdk-animate-spin:spin 1s linear infinite;--clcosdk-animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--clcosdk-color-brand-primary:var(--color-brand-primary)}}@layer base{.clco-sdk-root{--color-brand-primary:#171717;--color-brand-primary-hover:#000;--color-brand-primary-active:#262626;--color-accent:#2b3a67;--color-accent-hover:#243057;--color-accent-active:#1d2647;--color-accent-focus:#c7d2fe;--color-accent-subtle:#eef1f8;--color-text-primary:#171717;--color-text-secondary:#8c8c8c;--color-text-disabled:#d1d1d1;--color-text-inverse:#fff;--color-background:#fff;--color-surface:#fafafa;--color-section:#f3f3f3;--color-border:#e5e5e5;--color-divider:#ececec;--color-overlay:#00000080;--color-positive:#15803d;--color-positive-subtle:#dcfce7;--color-negative:#dc2626;--color-negative-subtle:#fee2e2;--color-success:#2c8c5e;--color-success-subtle:#e6f4ec;--color-success-border:#cfe9db;--color-warning:#e08a1a;--color-warning-subtle:#fff7ed;--color-warning-border:#fdead7;--color-error:#b42318;--color-error-subtle:#feeceb;--color-error-border:#fbd5d2;--shadow-step-active:0px 0px 10px 0px #0000001a;--shadow-dialog:0px 8px 32px 0px #0000001a;--btn-primary-gradient:linear-gradient(180deg, #262626 0%, #1c1c1c 50%, #0f0f0f 100%);--btn-primary-shadow:inset 0px -1px 3px 0px #00000059, inset 0px 1px 2px 0px #ffffff2e, inset 0px 1px 0px 0px #ffffff1a;--sale-card-surface:linear-gradient(to top, #0a0a0a 0%, #1a1a1a 100%);--color-sale-card-text:#f4f4f5;--color-sale-card-text-muted:#a1a1aa;--color-sale-card-text-strong:#fff;--color-sale-card-border:#ffffff40;--color-sale-card-chrome-border:#ffffff4d;--color-sale-card-chrome-bg:#ffffff26;--color-sale-card-chrome-emphasis-border:#fff6;--color-sale-card-chrome-emphasis-bg:#ffffff40;--color-sale-card-focus-ring:#ffffff80}@media (prefers-color-scheme:dark){.clco-sdk-root:not(:where(.light,.light *)){--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140;--shadow-step-active:0px 0px 10px 0px #00000080;--shadow-dialog:0px 8px 32px 0px #0009;--btn-primary-gradient:linear-gradient(180deg, #fafafa 0%, #f0f0f0 50%, #e4e4e7 100%);--btn-primary-shadow:inset 0px -1px 3px 0px #0000001f, inset 0px 1px 2px 0px #fff9, inset 0px 1px 0px 0px #fff6}}:where(.dark,.dark *) .clco-sdk-root{--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140;--shadow-step-active:0px 0px 10px 0px #00000080;--shadow-dialog:0px 8px 32px 0px #0009;--btn-primary-gradient:linear-gradient(180deg, #fafafa 0%, #f0f0f0 50%, #e4e4e7 100%);--btn-primary-shadow:inset 0px -1px 3px 0px #0000001f, inset 0px 1px 2px 0px #fff9, inset 0px 1px 0px 0px #fff6}.clco-sdk-root{color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,sans-serif}.clco-sdk-root *,.clco-sdk-root :before,.clco-sdk-root :after{box-sizing:border-box}.clco-sdk-root button{appearance:none;cursor:pointer;font:inherit;color:inherit;background:0 0;border:none;padding:0}.clco-sdk-root input,.clco-sdk-root textarea,.clco-sdk-root select{font:inherit;color:inherit;background:0 0;border:none;border-radius:0;padding:0}.clco-sdk-root a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.clco-sdk-root ul,.clco-sdk-root ol{margin:0;padding:0;list-style:none}.clco-sdk-root h1,.clco-sdk-root h2,.clco-sdk-root h3,.clco-sdk-root h4,.clco-sdk-root h5,.clco-sdk-root h6,.clco-sdk-root p,.clco-sdk-root figure,.clco-sdk-root blockquote,.clco-sdk-root dl,.clco-sdk-root dd,.clco-sdk-root pre{margin:0}.clco-sdk-root img,.clco-sdk-root svg{max-width:100%;display:block}@keyframes clco-status-ping{0%{opacity:.7;transform:scale(1)}75%,to{opacity:0;transform:scale(3.25)}}.clco-sdk-root .clcosdk-status-dot-ping{animation:1.6s cubic-bezier(0,0,.2,1) infinite clco-status-ping}@media (prefers-reduced-motion:reduce){.clco-sdk-root .clcosdk-status-dot-ping{opacity:0;animation:none}}}@layer components;@layer utilities{.clcosdk\\:pointer-events-none{pointer-events:none}.clcosdk\\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.clcosdk\\:absolute{position:absolute}.clcosdk\\:fixed{position:fixed}.clcosdk\\:relative{position:relative}.clcosdk\\:inset-0{inset:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:top-1\\/2{top:50%}.clcosdk\\:top-4{top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:top-full{top:100%}.clcosdk\\:-right-0\\.5{right:calc(var(--clcosdk-spacing) * -.5)}.clcosdk\\:right-4{right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:right-\\[-14\\%\\]{right:-14%}.clcosdk\\:-bottom-0\\.5{bottom:calc(var(--clcosdk-spacing) * -.5)}.clcosdk\\:bottom-full{bottom:100%}.clcosdk\\:left-1\\/2{left:50%}.clcosdk\\:z-0{z-index:0}.clcosdk\\:z-10{z-index:10}.clcosdk\\:z-50{z-index:50}.clcosdk\\:order-1{order:1}.clcosdk\\:order-2{order:2}.clcosdk\\:mt-2{margin-top:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:mt-4{margin-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:mt-auto{margin-top:auto}.clcosdk\\:mb-2{margin-bottom:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:flex{display:flex}.clcosdk\\:grid{display:grid}.clcosdk\\:inline-flex{display:inline-flex}.clcosdk\\:size-2{width:calc(var(--clcosdk-spacing) * 2);height:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:size-3{width:calc(var(--clcosdk-spacing) * 3);height:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:size-3\\.5{width:calc(var(--clcosdk-spacing) * 3.5);height:calc(var(--clcosdk-spacing) * 3.5)}.clcosdk\\:size-4{width:calc(var(--clcosdk-spacing) * 4);height:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:size-5{width:calc(var(--clcosdk-spacing) * 5);height:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:size-10{width:calc(var(--clcosdk-spacing) * 10);height:calc(var(--clcosdk-spacing) * 10)}.clcosdk\\:size-16{width:calc(var(--clcosdk-spacing) * 16);height:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:size-24{width:calc(var(--clcosdk-spacing) * 24);height:calc(var(--clcosdk-spacing) * 24)}.clcosdk\\:size-\\[15rem\\]{width:15rem;height:15rem}.clcosdk\\:size-full{width:100%;height:100%}.clcosdk\\:h-1{height:calc(var(--clcosdk-spacing) * 1)}.clcosdk\\:h-3{height:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:h-4{height:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:h-5{height:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:h-6{height:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:h-8{height:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:h-9{height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:h-10{height:calc(var(--clcosdk-spacing) * 10)}.clcosdk\\:h-11{height:calc(var(--clcosdk-spacing) * 11)}.clcosdk\\:h-12{height:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:h-14{height:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:h-\\[18px\\]{height:18px}.clcosdk\\:h-\\[54px\\]{height:54px}.clcosdk\\:h-\\[71px\\]{height:71px}.clcosdk\\:h-auto{height:auto}.clcosdk\\:h-full{height:100%}.clcosdk\\:h-px{height:1px}.clcosdk\\:max-h-\\[92vh\\]{max-height:92vh}.clcosdk\\:max-h-full{max-height:100%}.clcosdk\\:min-h-0{min-height:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:min-h-9{min-height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:min-h-40{min-height:calc(var(--clcosdk-spacing) * 40)}.clcosdk\\:min-h-screen{min-height:100vh}.clcosdk\\:w-1{width:calc(var(--clcosdk-spacing) * 1)}.clcosdk\\:w-4{width:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:w-5{width:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:w-6{width:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:w-8{width:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:w-10{width:calc(var(--clcosdk-spacing) * 10)}.clcosdk\\:w-12{width:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:w-16{width:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:w-20{width:calc(var(--clcosdk-spacing) * 20)}.clcosdk\\:w-24{width:calc(var(--clcosdk-spacing) * 24)}.clcosdk\\:w-28{width:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:w-32{width:calc(var(--clcosdk-spacing) * 32)}.clcosdk\\:w-40{width:calc(var(--clcosdk-spacing) * 40)}.clcosdk\\:w-48{width:calc(var(--clcosdk-spacing) * 48)}.clcosdk\\:w-80{width:calc(var(--clcosdk-spacing) * 80)}.clcosdk\\:w-96{width:calc(var(--clcosdk-spacing) * 96)}.clcosdk\\:w-\\[16px\\]{width:16px}.clcosdk\\:w-\\[28rem\\]{width:28rem}.clcosdk\\:w-\\[448px\\]{width:448px}.clcosdk\\:w-auto{width:auto}.clcosdk\\:w-component{width:448px}.clcosdk\\:w-fit{width:fit-content}.clcosdk\\:w-full{width:100%}.clcosdk\\:w-max{width:max-content}.clcosdk\\:max-w-\\[16rem\\]{max-width:16rem}.clcosdk\\:max-w-\\[28rem\\]{max-width:28rem}.clcosdk\\:max-w-\\[30rem\\]{max-width:30rem}.clcosdk\\:max-w-\\[40rem\\]{max-width:40rem}.clcosdk\\:max-w-\\[56rem\\]{max-width:56rem}.clcosdk\\:max-w-\\[64rem\\]{max-width:64rem}.clcosdk\\:max-w-\\[760px\\]{max-width:760px}.clcosdk\\:max-w-full{max-width:100%}.clcosdk\\:max-w-md{max-width:var(--clcosdk-container-md)}.clcosdk\\:max-w-sm{max-width:var(--clcosdk-container-sm)}.clcosdk\\:max-w-xl{max-width:var(--clcosdk-container-xl)}.clcosdk\\:min-w-0{min-width:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:flex-1{flex:1}.clcosdk\\:shrink-0{flex-shrink:0}.clcosdk\\:-translate-x-1\\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:-translate-y-1\\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:rotate-90{rotate:90deg}.clcosdk\\:rotate-180{rotate:180deg}.clcosdk\\:animate-pulse{animation:var(--clcosdk-animate-pulse)}.clcosdk\\:animate-spin{animation:var(--clcosdk-animate-spin)}.clcosdk\\:cursor-pointer{cursor:pointer}.clcosdk\\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.clcosdk\\:grid-rows-\\[0fr\\]{grid-template-rows:0fr}.clcosdk\\:grid-rows-\\[1fr\\]{grid-template-rows:1fr}.clcosdk\\:flex-col{flex-direction:column}.clcosdk\\:flex-wrap{flex-wrap:wrap}.clcosdk\\:items-center{align-items:center}.clcosdk\\:items-end{align-items:flex-end}.clcosdk\\:items-start{align-items:flex-start}.clcosdk\\:justify-between{justify-content:space-between}.clcosdk\\:justify-center{justify-content:center}.clcosdk\\:justify-end{justify-content:flex-end}.clcosdk\\:gap-1{gap:calc(var(--clcosdk-spacing) * 1)}.clcosdk\\:gap-1\\.5{gap:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:gap-2{gap:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:gap-2\\.5{gap:calc(var(--clcosdk-spacing) * 2.5)}.clcosdk\\:gap-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:gap-\\[5px\\]{gap:5px}:where(.clcosdk\\:space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.clcosdk\\:divide-border>:not(:last-child)){border-color:var(--color-border)}:where(.clcosdk\\:divide-divider>:not(:last-child)){border-color:var(--color-divider)}.clcosdk\\:self-start{align-self:flex-start}.clcosdk\\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.clcosdk\\:overflow-hidden{overflow:hidden}.clcosdk\\:overflow-y-auto{overflow-y:auto}.clcosdk\\:rounded{border-radius:.25rem}.clcosdk\\:rounded-2xl{border-radius:var(--clcosdk-radius-2xl)}.clcosdk\\:rounded-\\[20px\\]{border-radius:20px}.clcosdk\\:rounded-\\[28px\\]{border-radius:28px}.clcosdk\\:rounded-btn{border-radius:12px}.clcosdk\\:rounded-card{border-radius:24px}.clcosdk\\:rounded-full{border-radius:3.40282e38px}.clcosdk\\:rounded-lg{border-radius:var(--clcosdk-radius-lg)}.clcosdk\\:rounded-md{border-radius:var(--clcosdk-radius-md)}.clcosdk\\:rounded-xl{border-radius:var(--clcosdk-radius-xl)}.clcosdk\\:border{border-style:var(--tw-border-style);border-width:1px}.clcosdk\\:border-2{border-style:var(--tw-border-style);border-width:2px}.clcosdk\\:border-\\[1\\.5px\\]{border-style:var(--tw-border-style);border-width:1.5px}.clcosdk\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.clcosdk\\:border-accent\\/60{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/60{border-color:color-mix(in oklab, var(--color-accent) 60%, transparent)}}.clcosdk\\:border-amber-500{border-color:var(--clcosdk-color-amber-500)}.clcosdk\\:border-background{border-color:var(--color-background)}.clcosdk\\:border-border{border-color:var(--color-border)}.clcosdk\\:border-brand-primary{border-color:var(--color-brand-primary)}.clcosdk\\:border-current{border-color:currentColor}.clcosdk\\:border-divider{border-color:var(--color-divider)}.clcosdk\\:border-error-border{border-color:var(--color-error-border)}.clcosdk\\:border-sale-card-border{border-color:var(--color-sale-card-border)}.clcosdk\\:border-sale-card-chrome-border{border-color:var(--color-sale-card-chrome-border)}.clcosdk\\:border-success-border{border-color:var(--color-success-border)}.clcosdk\\:border-warning-border{border-color:var(--color-warning-border)}.clcosdk\\:border-t-transparent{border-top-color:#0000}.clcosdk\\:bg-background{background-color:var(--color-background)}.clcosdk\\:bg-black\\/50{background-color:var(--clcosdk-color-black)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:bg-black\\/50{background-color:color-mix(in oklab, var(--clcosdk-color-black) 50%, transparent)}}.clcosdk\\:bg-brand-primary{background-color:var(--color-brand-primary)}.clcosdk\\:bg-divider{background-color:var(--color-divider)}.clcosdk\\:bg-error-subtle{background-color:var(--color-error-subtle)}.clcosdk\\:bg-overlay{background-color:var(--color-overlay)}.clcosdk\\:bg-positive{background-color:var(--color-positive)}.clcosdk\\:bg-positive-subtle{background-color:var(--color-positive-subtle)}.clcosdk\\:bg-sale-card-chrome-bg{background-color:var(--color-sale-card-chrome-bg)}.clcosdk\\:bg-section{background-color:var(--color-section)}.clcosdk\\:bg-success-subtle{background-color:var(--color-success-subtle)}.clcosdk\\:bg-surface{background-color:var(--color-surface)}.clcosdk\\:bg-text-disabled{background-color:var(--color-text-disabled)}.clcosdk\\:bg-text-primary{background-color:var(--color-text-primary)}.clcosdk\\:bg-transparent{background-color:#0000}.clcosdk\\:bg-warning-subtle{background-color:var(--color-warning-subtle)}.clcosdk\\:bg-\\[image\\:var\\(--btn-primary-gradient\\)\\]{background-image:var(--btn-primary-gradient)}.clcosdk\\:bg-\\[image\\:var\\(--sale-card-surface\\)\\]{background-image:var(--sale-card-surface)}.clcosdk\\:object-contain{object-fit:contain}.clcosdk\\:object-cover{object-fit:cover}.clcosdk\\:p-0{padding:calc(var(--clcosdk-spacing) * 0)}.clcosdk\\:p-1\\.5{padding:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:p-3{padding:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:p-3\\.5{padding:calc(var(--clcosdk-spacing) * 3.5)}.clcosdk\\:p-4{padding:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:p-5{padding:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:p-8{padding:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:p-16{padding:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:px-2{padding-inline:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:px-3{padding-inline:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:px-4{padding-inline:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:px-5{padding-inline:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:py-1\\.5{padding-block:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:py-2{padding-block:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:py-3{padding-block:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:py-8{padding-block:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:py-12{padding-block:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:pt-1{padding-top:calc(var(--clcosdk-spacing) * 1)}.clcosdk\\:pt-4{padding-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pt-14{padding-top:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:pr-1\\.5{padding-right:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:pr-3{padding-right:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:pr-4{padding-right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pb-4{padding-bottom:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pl-3{padding-left:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:text-center{text-align:center}.clcosdk\\:text-left{text-align:left}.clcosdk\\:text-right{text-align:right}.clcosdk\\:font-mono{font-family:var(--clcosdk-font-mono)}.clcosdk\\:text-base{font-size:var(--clcosdk-text-base);line-height:var(--tw-leading,var(--clcosdk-text-base--line-height))}.clcosdk\\:text-lg{font-size:var(--clcosdk-text-lg);line-height:var(--tw-leading,var(--clcosdk-text-lg--line-height))}.clcosdk\\:text-sm{font-size:var(--clcosdk-text-sm);line-height:var(--tw-leading,var(--clcosdk-text-sm--line-height))}.clcosdk\\:text-xs{font-size:var(--clcosdk-text-xs);line-height:var(--tw-leading,var(--clcosdk-text-xs--line-height))}.clcosdk\\:text-\\[11px\\]{font-size:11px}.clcosdk\\:text-\\[12px\\]{font-size:12px}.clcosdk\\:text-\\[13px\\]{font-size:13px}.clcosdk\\:text-\\[14px\\]{font-size:14px}.clcosdk\\:text-\\[15px\\]{font-size:15px}.clcosdk\\:text-\\[16px\\]{font-size:16px}.clcosdk\\:text-\\[18px\\]{font-size:18px}.clcosdk\\:text-\\[22px\\]{font-size:22px}.clcosdk\\:text-\\[28px\\]{font-size:28px}.clcosdk\\:text-\\[36px\\]{font-size:36px}.clcosdk\\:text-\\[48px\\]{font-size:48px}.clcosdk\\:text-\\[64px\\]{font-size:64px}.clcosdk\\:leading-\\[105\\%\\]{--tw-leading:105%;line-height:105%}.clcosdk\\:leading-\\[108\\%\\]{--tw-leading:108%;line-height:108%}.clcosdk\\:leading-\\[110\\%\\]{--tw-leading:110%;line-height:110%}.clcosdk\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:leading-\\[130\\%\\]{--tw-leading:130%;line-height:130%}.clcosdk\\:leading-\\[140\\%\\]{--tw-leading:140%;line-height:140%}.clcosdk\\:leading-\\[150\\%\\]{--tw-leading:150%;line-height:150%}.clcosdk\\:leading-\\[160\\%\\]{--tw-leading:160%;line-height:160%}.clcosdk\\:font-medium{--tw-font-weight:var(--clcosdk-font-weight-medium);font-weight:var(--clcosdk-font-weight-medium)}.clcosdk\\:font-normal{--tw-font-weight:var(--clcosdk-font-weight-normal);font-weight:var(--clcosdk-font-weight-normal)}.clcosdk\\:font-semibold{--tw-font-weight:var(--clcosdk-font-weight-semibold);font-weight:var(--clcosdk-font-weight-semibold)}.clcosdk\\:tracking-\\[0\\.12px\\]{--tw-tracking:.12px;letter-spacing:.12px}.clcosdk\\:tracking-\\[0\\.28px\\]{--tw-tracking:.28px;letter-spacing:.28px}.clcosdk\\:break-words{overflow-wrap:break-word}.clcosdk\\:whitespace-nowrap{white-space:nowrap}.clcosdk\\:text-background{color:var(--color-background)}.clcosdk\\:text-brand-primary{color:var(--color-brand-primary)}.clcosdk\\:text-error{color:var(--color-error)}.clcosdk\\:text-positive{color:var(--color-positive)}.clcosdk\\:text-sale-card-text{color:var(--color-sale-card-text)}.clcosdk\\:text-sale-card-text-muted{color:var(--color-sale-card-text-muted)}.clcosdk\\:text-sale-card-text-strong{color:var(--color-sale-card-text-strong)}.clcosdk\\:text-success{color:var(--color-success)}.clcosdk\\:text-text-disabled{color:var(--color-text-disabled)}.clcosdk\\:text-text-inverse{color:var(--color-text-inverse)}.clcosdk\\:text-text-primary{color:var(--color-text-primary)}.clcosdk\\:text-text-secondary{color:var(--color-text-secondary)}.clcosdk\\:text-warning{color:var(--color-warning)}.clcosdk\\:capitalize{text-transform:capitalize}.clcosdk\\:lining-nums{--tw-numeric-figure:lining-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.clcosdk\\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.clcosdk\\:no-underline{text-decoration-line:none}.clcosdk\\:underline{text-decoration-line:underline}.clcosdk\\:underline-offset-2{text-underline-offset:2px}.clcosdk\\:underline-offset-4{text-underline-offset:4px}.clcosdk\\:opacity-0{opacity:0}.clcosdk\\:opacity-60{opacity:.6}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.2\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f633);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0px_1px_1px_0px_rgba\\(10\\,10\\,10\\,0\\.04\\)\\,0px_8px_12px_0px_rgba\\(10\\,10\\,10\\,0\\.08\\)\\]{--tw-shadow:0px 1px 1px 0px var(--tw-shadow-color,#0a0a0a0a), 0px 8px 12px 0px var(--tw-shadow-color,#0a0a0a14);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0px_4px_12px_0px_rgba\\(0\\,0\\,0\\,0\\.08\\)\\,0px_12px_28px_0px_rgba\\(0\\,0\\,0\\,0\\.13\\)\\]{--tw-shadow:0px 4px 12px 0px var(--tw-shadow-color,#00000014), 0px 12px 28px 0px var(--tw-shadow-color,#00000021);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[var\\(--btn-primary-shadow\\)\\]{--tw-shadow:var(--btn-primary-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-card{--tw-shadow:0px 4px 6px -2px var(--tw-shadow-color,#0000000d), 0px 12px 24px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-dialog{--tw-shadow:var(--shadow-dialog);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-step-active{--tw-shadow:var(--shadow-step-active);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:transition-\\[background-color\\,border-color\\]{transition-property:background-color,border-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-\\[grid-template-rows\\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.clcosdk\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.clcosdk\\:duration-500{--tw-duration:.5s;transition-duration:.5s}.clcosdk\\:ease-in-out{--tw-ease:var(--clcosdk-ease-in-out);transition-timing-function:var(--clcosdk-ease-in-out)}.clcosdk\\:ease-out{--tw-ease:var(--clcosdk-ease-out);transition-timing-function:var(--clcosdk-ease-out)}.clcosdk\\:outline-none{--tw-outline-style:none;outline-style:none}.clcosdk\\:group-focus-within\\:opacity-100:is(:where(.clcosdk\\:group):focus-within *){opacity:1}@media (hover:hover){.clcosdk\\:group-hover\\:border-sale-card-chrome-emphasis-border:is(:where(.clcosdk\\:group):hover *){border-color:var(--color-sale-card-chrome-emphasis-border)}.clcosdk\\:group-hover\\:bg-sale-card-chrome-emphasis-bg:is(:where(.clcosdk\\:group):hover *){background-color:var(--color-sale-card-chrome-emphasis-bg)}.clcosdk\\:group-hover\\:opacity-100:is(:where(.clcosdk\\:group):hover *){opacity:1}}.clcosdk\\:group-focus-visible\\:border-sale-card-chrome-emphasis-border:is(:where(.clcosdk\\:group):focus-visible *){border-color:var(--color-sale-card-chrome-emphasis-border)}.clcosdk\\:group-focus-visible\\:bg-sale-card-chrome-emphasis-bg:is(:where(.clcosdk\\:group):focus-visible *){background-color:var(--color-sale-card-chrome-emphasis-bg)}.clcosdk\\:placeholder\\:text-text-disabled::placeholder{color:var(--color-text-disabled)}@media (hover:hover){.clcosdk\\:hover\\:scale-\\[1\\.02\\]:hover{scale:1.02}.clcosdk\\:hover\\:border-text-disabled:hover{border-color:var(--color-text-disabled)}.clcosdk\\:hover\\:bg-\\[\\#fcdcd8\\]:hover{background-color:#fcdcd8}.clcosdk\\:hover\\:bg-border:hover{background-color:var(--color-border)}.clcosdk\\:hover\\:bg-brand-primary:hover{background-color:var(--color-brand-primary)}.clcosdk\\:hover\\:bg-brand-primary-hover:hover{background-color:var(--color-brand-primary-hover)}.clcosdk\\:hover\\:bg-section:hover{background-color:var(--color-section)}.clcosdk\\:hover\\:bg-surface:hover{background-color:var(--color-surface)}.clcosdk\\:hover\\:text-\\[\\#8b1a13\\]:hover{color:#8b1a13}.clcosdk\\:hover\\:text-text-primary:hover{color:var(--color-text-primary)}.clcosdk\\:hover\\:underline:hover{text-decoration-line:underline}.clcosdk\\:hover\\:opacity-80:hover{opacity:.8}.clcosdk\\:hover\\:opacity-90:hover{opacity:.9}}.clcosdk\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:focus-visible\\:ring-gray-400:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-400)}.clcosdk\\:focus-visible\\:ring-gray-500:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-500)}.clcosdk\\:focus-visible\\:ring-red-400:focus-visible{--tw-ring-color:var(--clcosdk-color-red-400)}.clcosdk\\:focus-visible\\:ring-red-500:focus-visible{--tw-ring-color:var(--clcosdk-color-red-500)}.clcosdk\\:focus-visible\\:ring-sale-card-focus-ring:focus-visible{--tw-ring-color:var(--color-sale-card-focus-ring)}.clcosdk\\:focus-visible\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.clcosdk\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.clcosdk\\:active\\:bg-\\[\\#d9d9d9\\]:active{background-color:#d9d9d9}.clcosdk\\:active\\:bg-\\[\\#f9c9c4\\]:active{background-color:#f9c9c4}.clcosdk\\:active\\:bg-border:active{background-color:var(--color-border)}.clcosdk\\:active\\:bg-brand-primary-active:active{background-color:var(--color-brand-primary-active)}.clcosdk\\:active\\:text-\\[\\#6d1510\\]:active{color:#6d1510}.clcosdk\\:active\\:opacity-80:active{opacity:.8}.clcosdk\\:disabled\\:pointer-events-none:disabled{pointer-events:none}.clcosdk\\:disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.clcosdk\\:disabled\\:opacity-40:disabled{opacity:.4}.clcosdk\\:disabled\\:opacity-50:disabled{opacity:.5}.clcosdk\\:aria-disabled\\:cursor-not-allowed[aria-disabled=true]{cursor:not-allowed}.clcosdk\\:aria-disabled\\:opacity-50[aria-disabled=true]{opacity:.5}@media not all and (min-width:48rem){.clcosdk\\:max-md\\:hidden{display:none}.clcosdk\\:max-md\\:w-full{width:100%}.clcosdk\\:max-md\\:justify-start{justify-content:flex-start}.clcosdk\\:max-md\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:max-md\\:rounded-none{border-radius:0}.clcosdk\\:max-md\\:border-0{border-style:var(--tw-border-style);border-width:0}.clcosdk\\:max-md\\:bg-transparent{background-color:#0000}.clcosdk\\:max-md\\:p-0{padding:calc(var(--clcosdk-spacing) * 0)}@media (hover:hover){.clcosdk\\:max-md\\:hover\\:scale-100:hover{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}}}@media (min-width:40rem){.clcosdk\\:sm\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:48rem){.clcosdk\\:md\\:right-\\[-10\\%\\]{right:-10%}.clcosdk\\:md\\:order-1{order:1}.clcosdk\\:md\\:order-2{order:2}.clcosdk\\:md\\:hidden{display:none}.clcosdk\\:md\\:size-\\[20rem\\]{width:20rem;height:20rem}.clcosdk\\:md\\:h-9{height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:md\\:h-12{height:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:md\\:h-\\[54px\\]{height:54px}.clcosdk\\:md\\:w-9{width:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:md\\:w-12{width:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:md\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.clcosdk\\:md\\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.clcosdk\\:md\\:grid-cols-\\[minmax\\(0\\,11fr\\)_minmax\\(0\\,8fr\\)\\]{grid-template-columns:minmax(0,11fr) minmax(0,8fr)}.clcosdk\\:md\\:flex-row{flex-direction:row}.clcosdk\\:md\\:items-center{align-items:center}.clcosdk\\:md\\:items-end{align-items:flex-end}.clcosdk\\:md\\:justify-between{justify-content:space-between}.clcosdk\\:md\\:justify-end{justify-content:flex-end}.clcosdk\\:md\\:gap-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:md\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:gap-x-12{column-gap:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:md\\:self-end{align-self:flex-end}.clcosdk\\:md\\:rounded-\\[40px\\]{border-radius:40px}.clcosdk\\:md\\:rounded-card{border-radius:24px}.clcosdk\\:md\\:rounded-dialog{border-radius:32px}.clcosdk\\:md\\:p-4{padding:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:md\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:p-8{padding:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:md\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:px-8{padding-inline:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:md\\:py-2{padding-block:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:md\\:pr-2{padding-right:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:md\\:pr-4{padding-right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:md\\:pl-4{padding-left:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:md\\:text-base{font-size:var(--clcosdk-text-base);line-height:var(--tw-leading,var(--clcosdk-text-base--line-height))}.clcosdk\\:md\\:text-\\[14px\\]{font-size:14px}.clcosdk\\:md\\:text-\\[16px\\]{font-size:16px}.clcosdk\\:md\\:text-\\[18px\\]{font-size:18px}.clcosdk\\:md\\:text-\\[28px\\]{font-size:28px}.clcosdk\\:md\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:md\\:leading-\\[160\\%\\]{--tw-leading:160%;line-height:160%}}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:not(:where(.light,.light *)):hover{background-color:#f8717133}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:where(.dark,.dark *):hover{background-color:#f8717133}}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:not(:where(.light,.light *)):hover{color:#fca5a5}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:where(.dark,.dark *):hover{color:#fca5a5}}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:not(:where(.light,.light *)):active{background-color:#f871714d}}.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:where(.dark,.dark *):active{background-color:#f871714d}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-divider:not(:where(.light,.light *)):active{background-color:var(--color-divider)}}.clcosdk\\:dark\\:active\\:bg-divider:where(.dark,.dark *):active{background-color:var(--color-divider)}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:not(:where(.light,.light *)):active{color:#f87171}}.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:where(.dark,.dark *):active{color:#f87171}.clcosdk\\:\\[\\&_circle\\]\\:fill-error-subtle circle{fill:var(--color-error-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-success-subtle circle{fill:var(--color-success-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-warning-subtle circle{fill:var(--color-warning-subtle)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}';
4137
+ var sdkStyles = '/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--clcosdk-font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--clcosdk-color-red-400:oklch(70.4% .191 22.216);--clcosdk-color-red-500:oklch(63.7% .237 25.331);--clcosdk-color-amber-500:oklch(76.9% .188 70.08);--clcosdk-color-gray-400:oklch(70.7% .022 261.325);--clcosdk-color-gray-500:oklch(55.1% .027 264.364);--clcosdk-color-black:#000;--clcosdk-spacing:.25rem;--clcosdk-container-sm:24rem;--clcosdk-container-md:28rem;--clcosdk-container-xl:36rem;--clcosdk-text-xs:.75rem;--clcosdk-text-xs--line-height:calc(1 / .75);--clcosdk-text-sm:.875rem;--clcosdk-text-sm--line-height:calc(1.25 / .875);--clcosdk-text-base:1rem;--clcosdk-text-base--line-height:calc(1.5 / 1);--clcosdk-text-lg:1.125rem;--clcosdk-text-lg--line-height:calc(1.75 / 1.125);--clcosdk-font-weight-normal:400;--clcosdk-font-weight-medium:500;--clcosdk-font-weight-semibold:600;--clcosdk-radius-md:.375rem;--clcosdk-radius-lg:.5rem;--clcosdk-radius-xl:.75rem;--clcosdk-radius-2xl:1rem;--clcosdk-ease-out:cubic-bezier(0, 0, .2, 1);--clcosdk-ease-in-out:cubic-bezier(.4, 0, .2, 1);--clcosdk-animate-spin:spin 1s linear infinite;--clcosdk-animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--clcosdk-color-brand-primary:var(--color-brand-primary)}}@layer base{.clco-sdk-root{--color-brand-primary:#171717;--color-brand-primary-hover:#000;--color-brand-primary-active:#262626;--color-accent:#2b3a67;--color-accent-hover:#243057;--color-accent-active:#1d2647;--color-accent-focus:#c7d2fe;--color-accent-subtle:#eef1f8;--color-text-primary:#171717;--color-text-secondary:#8c8c8c;--color-text-disabled:#d1d1d1;--color-text-inverse:#fff;--color-background:#fff;--color-surface:#fafafa;--color-section:#f3f3f3;--color-border:#e5e5e5;--color-divider:#ececec;--color-overlay:#00000080;--color-positive:#15803d;--color-positive-subtle:#dcfce7;--color-negative:#dc2626;--color-negative-subtle:#fee2e2;--color-success:#2c8c5e;--color-success-subtle:#e6f4ec;--color-success-border:#cfe9db;--color-warning:#e08a1a;--color-warning-subtle:#fff7ed;--color-warning-border:#fdead7;--color-error:#b42318;--color-error-subtle:#feeceb;--color-error-border:#fbd5d2;--shadow-step-active:0px 0px 10px 0px #0000001a;--shadow-dialog:0px 8px 32px 0px #0000001a;--btn-primary-gradient:linear-gradient(180deg, #262626 0%, #1c1c1c 50%, #0f0f0f 100%);--btn-primary-shadow:inset 0px -1px 3px 0px #00000059, inset 0px 1px 2px 0px #ffffff2e, inset 0px 1px 0px 0px #ffffff1a;--sale-card-surface:linear-gradient(to top, #0a0a0a 0%, #1a1a1a 100%);--color-sale-card-text:#f4f4f5;--color-sale-card-text-muted:#a1a1aa;--color-sale-card-text-strong:#fff;--color-sale-card-border:#ffffff40;--color-sale-card-chrome-border:#ffffff4d;--color-sale-card-chrome-bg:#ffffff26;--color-sale-card-chrome-emphasis-border:#fff6;--color-sale-card-chrome-emphasis-bg:#ffffff40;--color-sale-card-focus-ring:#ffffff80}@media (prefers-color-scheme:dark){.clco-sdk-root:not(:where(.light,.light *)){--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140;--shadow-step-active:0px 0px 10px 0px #00000080;--shadow-dialog:0px 8px 32px 0px #0009;--btn-primary-gradient:linear-gradient(180deg, #fafafa 0%, #f0f0f0 50%, #e4e4e7 100%);--btn-primary-shadow:inset 0px -1px 3px 0px #0000001f, inset 0px 1px 2px 0px #fff9, inset 0px 1px 0px 0px #fff6}}:where(.dark,.dark *) .clco-sdk-root{--color-brand-primary:#f4f4f5;--color-brand-primary-hover:#fff;--color-brand-primary-active:#e4e4e7;--color-accent:#6f82c9;--color-accent-hover:#8799e4;--color-accent-active:#5b6fcf;--color-accent-focus:#6f82c959;--color-accent-subtle:#6f82c91f;--color-text-primary:#f4f4f5;--color-text-secondary:#a1a1aa;--color-text-disabled:#71717a;--color-text-inverse:#171717;--color-background:#0f1115;--color-surface:#161a20;--color-section:#20242c;--color-border:#2a2e35;--color-divider:#323741;--color-overlay:#000000b3;--color-positive:#22c55e;--color-positive-subtle:#22c55e1f;--color-negative:#ef4444;--color-negative-subtle:#ef44441f;--color-success:#34d399;--color-success-subtle:#34d3991f;--color-success-border:#34d39940;--color-warning:#f59e0b;--color-warning-subtle:#f59e0b1f;--color-warning-border:#f59e0b40;--color-error:#f87171;--color-error-subtle:#f871711f;--color-error-border:#f8717140;--shadow-step-active:0px 0px 10px 0px #00000080;--shadow-dialog:0px 8px 32px 0px #0009;--btn-primary-gradient:linear-gradient(180deg, #fafafa 0%, #f0f0f0 50%, #e4e4e7 100%);--btn-primary-shadow:inset 0px -1px 3px 0px #0000001f, inset 0px 1px 2px 0px #fff9, inset 0px 1px 0px 0px #fff6}.clco-sdk-root{color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,sans-serif}.clco-sdk-root *,.clco-sdk-root :before,.clco-sdk-root :after{box-sizing:border-box}.clco-sdk-root button{appearance:none;cursor:pointer;font:inherit;color:inherit;background:0 0;border:none;padding:0}.clco-sdk-root input,.clco-sdk-root textarea,.clco-sdk-root select{font:inherit;color:inherit;background:0 0;border:none;border-radius:0;padding:0}.clco-sdk-root a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.clco-sdk-root ul,.clco-sdk-root ol{margin:0;padding:0;list-style:none}.clco-sdk-root h1,.clco-sdk-root h2,.clco-sdk-root h3,.clco-sdk-root h4,.clco-sdk-root h5,.clco-sdk-root h6,.clco-sdk-root p,.clco-sdk-root figure,.clco-sdk-root blockquote,.clco-sdk-root dl,.clco-sdk-root dd,.clco-sdk-root pre{margin:0}.clco-sdk-root img,.clco-sdk-root svg{max-width:100%;display:block}@keyframes clco-status-ping{0%{opacity:.7;transform:scale(1)}75%,to{opacity:0;transform:scale(3.25)}}.clco-sdk-root .clcosdk-status-dot-ping{animation:1.6s cubic-bezier(0,0,.2,1) infinite clco-status-ping}@media (prefers-reduced-motion:reduce){.clco-sdk-root .clcosdk-status-dot-ping{opacity:0;animation:none}}}@layer components;@layer utilities{.clcosdk\\:pointer-events-none{pointer-events:none}.clcosdk\\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.clcosdk\\:absolute{position:absolute}.clcosdk\\:fixed{position:fixed}.clcosdk\\:relative{position:relative}.clcosdk\\:inset-0{inset:0}.clcosdk\\:top-1\\/2{top:50%}.clcosdk\\:top-4{top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:top-full{top:100%}.clcosdk\\:-right-0\\.5{right:calc(var(--clcosdk-spacing) * -.5)}.clcosdk\\:right-4{right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:right-\\[-14\\%\\]{right:-14%}.clcosdk\\:-bottom-0\\.5{bottom:calc(var(--clcosdk-spacing) * -.5)}.clcosdk\\:bottom-full{bottom:100%}.clcosdk\\:left-1\\/2{left:50%}.clcosdk\\:z-0{z-index:0}.clcosdk\\:z-10{z-index:10}.clcosdk\\:z-50{z-index:50}.clcosdk\\:order-1{order:1}.clcosdk\\:order-2{order:2}.clcosdk\\:mt-2{margin-top:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:mt-4{margin-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:mt-auto{margin-top:auto}.clcosdk\\:mb-2{margin-bottom:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:flex{display:flex}.clcosdk\\:grid{display:grid}.clcosdk\\:inline-flex{display:inline-flex}.clcosdk\\:size-2{width:calc(var(--clcosdk-spacing) * 2);height:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:size-3{width:calc(var(--clcosdk-spacing) * 3);height:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:size-3\\.5{width:calc(var(--clcosdk-spacing) * 3.5);height:calc(var(--clcosdk-spacing) * 3.5)}.clcosdk\\:size-4{width:calc(var(--clcosdk-spacing) * 4);height:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:size-5{width:calc(var(--clcosdk-spacing) * 5);height:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:size-10{width:calc(var(--clcosdk-spacing) * 10);height:calc(var(--clcosdk-spacing) * 10)}.clcosdk\\:size-16{width:calc(var(--clcosdk-spacing) * 16);height:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:size-24{width:calc(var(--clcosdk-spacing) * 24);height:calc(var(--clcosdk-spacing) * 24)}.clcosdk\\:size-\\[15rem\\]{width:15rem;height:15rem}.clcosdk\\:size-full{width:100%;height:100%}.clcosdk\\:h-1{height:var(--clcosdk-spacing)}.clcosdk\\:h-3{height:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:h-4{height:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:h-5{height:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:h-6{height:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:h-8{height:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:h-9{height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:h-10{height:calc(var(--clcosdk-spacing) * 10)}.clcosdk\\:h-11{height:calc(var(--clcosdk-spacing) * 11)}.clcosdk\\:h-12{height:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:h-14{height:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:h-\\[18px\\]{height:18px}.clcosdk\\:h-\\[54px\\]{height:54px}.clcosdk\\:h-\\[71px\\]{height:71px}.clcosdk\\:h-auto{height:auto}.clcosdk\\:h-full{height:100%}.clcosdk\\:h-px{height:1px}.clcosdk\\:max-h-\\[92vh\\]{max-height:92vh}.clcosdk\\:max-h-full{max-height:100%}.clcosdk\\:min-h-0{min-height:0}.clcosdk\\:min-h-9{min-height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:min-h-40{min-height:calc(var(--clcosdk-spacing) * 40)}.clcosdk\\:min-h-screen{min-height:100vh}.clcosdk\\:w-1{width:var(--clcosdk-spacing)}.clcosdk\\:w-4{width:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:w-5{width:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:w-6{width:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:w-8{width:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:w-10{width:calc(var(--clcosdk-spacing) * 10)}.clcosdk\\:w-12{width:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:w-16{width:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:w-20{width:calc(var(--clcosdk-spacing) * 20)}.clcosdk\\:w-24{width:calc(var(--clcosdk-spacing) * 24)}.clcosdk\\:w-28{width:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:w-32{width:calc(var(--clcosdk-spacing) * 32)}.clcosdk\\:w-40{width:calc(var(--clcosdk-spacing) * 40)}.clcosdk\\:w-48{width:calc(var(--clcosdk-spacing) * 48)}.clcosdk\\:w-80{width:calc(var(--clcosdk-spacing) * 80)}.clcosdk\\:w-96{width:calc(var(--clcosdk-spacing) * 96)}.clcosdk\\:w-\\[16px\\]{width:16px}.clcosdk\\:w-\\[28rem\\]{width:28rem}.clcosdk\\:w-\\[448px\\]{width:448px}.clcosdk\\:w-auto{width:auto}.clcosdk\\:w-component{width:448px}.clcosdk\\:w-fit{width:fit-content}.clcosdk\\:w-full{width:100%}.clcosdk\\:w-max{width:max-content}.clcosdk\\:max-w-\\[16rem\\]{max-width:16rem}.clcosdk\\:max-w-\\[28rem\\]{max-width:28rem}.clcosdk\\:max-w-\\[30rem\\]{max-width:30rem}.clcosdk\\:max-w-\\[40rem\\]{max-width:40rem}.clcosdk\\:max-w-\\[56rem\\]{max-width:56rem}.clcosdk\\:max-w-\\[64rem\\]{max-width:64rem}.clcosdk\\:max-w-\\[760px\\]{max-width:760px}.clcosdk\\:max-w-full{max-width:100%}.clcosdk\\:max-w-md{max-width:var(--clcosdk-container-md)}.clcosdk\\:max-w-sm{max-width:var(--clcosdk-container-sm)}.clcosdk\\:max-w-xl{max-width:var(--clcosdk-container-xl)}.clcosdk\\:min-w-0{min-width:0}.clcosdk\\:flex-1{flex:1}.clcosdk\\:shrink-0{flex-shrink:0}.clcosdk\\:-translate-x-1\\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:-translate-y-1\\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:rotate-90{rotate:90deg}.clcosdk\\:rotate-180{rotate:180deg}.clcosdk\\:animate-pulse{animation:var(--clcosdk-animate-pulse)}.clcosdk\\:animate-spin{animation:var(--clcosdk-animate-spin)}.clcosdk\\:cursor-pointer{cursor:pointer}.clcosdk\\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.clcosdk\\:grid-rows-\\[0fr\\]{grid-template-rows:0fr}.clcosdk\\:grid-rows-\\[1fr\\]{grid-template-rows:1fr}.clcosdk\\:flex-col{flex-direction:column}.clcosdk\\:flex-wrap{flex-wrap:wrap}.clcosdk\\:items-center{align-items:center}.clcosdk\\:items-end{align-items:flex-end}.clcosdk\\:items-start{align-items:flex-start}.clcosdk\\:justify-between{justify-content:space-between}.clcosdk\\:justify-center{justify-content:center}.clcosdk\\:justify-end{justify-content:flex-end}.clcosdk\\:gap-1{gap:var(--clcosdk-spacing)}.clcosdk\\:gap-1\\.5{gap:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:gap-2{gap:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:gap-2\\.5{gap:calc(var(--clcosdk-spacing) * 2.5)}.clcosdk\\:gap-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:gap-\\[5px\\]{gap:5px}:where(.clcosdk\\:space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--clcosdk-spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--clcosdk-spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.clcosdk\\:divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.clcosdk\\:divide-border>:not(:last-child)){border-color:var(--color-border)}:where(.clcosdk\\:divide-divider>:not(:last-child)){border-color:var(--color-divider)}.clcosdk\\:self-start{align-self:flex-start}.clcosdk\\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.clcosdk\\:overflow-hidden{overflow:hidden}.clcosdk\\:overflow-y-auto{overflow-y:auto}.clcosdk\\:rounded{border-radius:.25rem}.clcosdk\\:rounded-2xl{border-radius:var(--clcosdk-radius-2xl)}.clcosdk\\:rounded-\\[20px\\]{border-radius:20px}.clcosdk\\:rounded-\\[28px\\]{border-radius:28px}.clcosdk\\:rounded-btn{border-radius:12px}.clcosdk\\:rounded-card{border-radius:24px}.clcosdk\\:rounded-full{border-radius:3.40282e38px}.clcosdk\\:rounded-lg{border-radius:var(--clcosdk-radius-lg)}.clcosdk\\:rounded-md{border-radius:var(--clcosdk-radius-md)}.clcosdk\\:rounded-xl{border-radius:var(--clcosdk-radius-xl)}.clcosdk\\:border{border-style:var(--tw-border-style);border-width:1px}.clcosdk\\:border-2{border-style:var(--tw-border-style);border-width:2px}.clcosdk\\:border-\\[1\\.5px\\]{border-style:var(--tw-border-style);border-width:1.5px}.clcosdk\\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.clcosdk\\:border-accent\\/60{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/60{border-color:color-mix(in oklab, var(--color-accent) 60%, transparent)}}.clcosdk\\:border-amber-500{border-color:var(--clcosdk-color-amber-500)}.clcosdk\\:border-background{border-color:var(--color-background)}.clcosdk\\:border-border{border-color:var(--color-border)}.clcosdk\\:border-brand-primary{border-color:var(--color-brand-primary)}.clcosdk\\:border-current{border-color:currentColor}.clcosdk\\:border-divider{border-color:var(--color-divider)}.clcosdk\\:border-error-border{border-color:var(--color-error-border)}.clcosdk\\:border-sale-card-border{border-color:var(--color-sale-card-border)}.clcosdk\\:border-sale-card-chrome-border{border-color:var(--color-sale-card-chrome-border)}.clcosdk\\:border-success-border{border-color:var(--color-success-border)}.clcosdk\\:border-warning-border{border-color:var(--color-warning-border)}.clcosdk\\:border-t-transparent{border-top-color:#0000}.clcosdk\\:bg-background{background-color:var(--color-background)}.clcosdk\\:bg-black\\/50{background-color:var(--clcosdk-color-black)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:bg-black\\/50{background-color:color-mix(in oklab, var(--clcosdk-color-black) 50%, transparent)}}.clcosdk\\:bg-brand-primary{background-color:var(--color-brand-primary)}.clcosdk\\:bg-divider{background-color:var(--color-divider)}.clcosdk\\:bg-error-subtle{background-color:var(--color-error-subtle)}.clcosdk\\:bg-overlay{background-color:var(--color-overlay)}.clcosdk\\:bg-positive{background-color:var(--color-positive)}.clcosdk\\:bg-positive-subtle{background-color:var(--color-positive-subtle)}.clcosdk\\:bg-sale-card-chrome-bg{background-color:var(--color-sale-card-chrome-bg)}.clcosdk\\:bg-section{background-color:var(--color-section)}.clcosdk\\:bg-success-subtle{background-color:var(--color-success-subtle)}.clcosdk\\:bg-surface{background-color:var(--color-surface)}.clcosdk\\:bg-text-disabled{background-color:var(--color-text-disabled)}.clcosdk\\:bg-text-primary{background-color:var(--color-text-primary)}.clcosdk\\:bg-transparent{background-color:#0000}.clcosdk\\:bg-warning-subtle{background-color:var(--color-warning-subtle)}.clcosdk\\:bg-\\[image\\:var\\(--btn-primary-gradient\\)\\]{background-image:var(--btn-primary-gradient)}.clcosdk\\:bg-\\[image\\:var\\(--sale-card-surface\\)\\]{background-image:var(--sale-card-surface)}.clcosdk\\:object-contain{object-fit:contain}.clcosdk\\:object-cover{object-fit:cover}.clcosdk\\:p-0{padding:0}.clcosdk\\:p-1\\.5{padding:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:p-3{padding:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:p-3\\.5{padding:calc(var(--clcosdk-spacing) * 3.5)}.clcosdk\\:p-4{padding:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:p-5{padding:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:p-8{padding:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:p-16{padding:calc(var(--clcosdk-spacing) * 16)}.clcosdk\\:px-2{padding-inline:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:px-3{padding-inline:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:px-4{padding-inline:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:px-5{padding-inline:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:py-1\\.5{padding-block:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:py-2{padding-block:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:py-3{padding-block:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:py-8{padding-block:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:py-12{padding-block:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:pt-1{padding-top:var(--clcosdk-spacing)}.clcosdk\\:pt-4{padding-top:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pt-14{padding-top:calc(var(--clcosdk-spacing) * 14)}.clcosdk\\:pr-1\\.5{padding-right:calc(var(--clcosdk-spacing) * 1.5)}.clcosdk\\:pr-3{padding-right:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:pr-4{padding-right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pb-4{padding-bottom:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:pl-3{padding-left:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:text-center{text-align:center}.clcosdk\\:text-left{text-align:left}.clcosdk\\:text-right{text-align:right}.clcosdk\\:font-mono{font-family:var(--clcosdk-font-mono)}.clcosdk\\:text-base{font-size:var(--clcosdk-text-base);line-height:var(--tw-leading,var(--clcosdk-text-base--line-height))}.clcosdk\\:text-lg{font-size:var(--clcosdk-text-lg);line-height:var(--tw-leading,var(--clcosdk-text-lg--line-height))}.clcosdk\\:text-sm{font-size:var(--clcosdk-text-sm);line-height:var(--tw-leading,var(--clcosdk-text-sm--line-height))}.clcosdk\\:text-xs{font-size:var(--clcosdk-text-xs);line-height:var(--tw-leading,var(--clcosdk-text-xs--line-height))}.clcosdk\\:text-\\[11px\\]{font-size:11px}.clcosdk\\:text-\\[12px\\]{font-size:12px}.clcosdk\\:text-\\[13px\\]{font-size:13px}.clcosdk\\:text-\\[14px\\]{font-size:14px}.clcosdk\\:text-\\[15px\\]{font-size:15px}.clcosdk\\:text-\\[16px\\]{font-size:16px}.clcosdk\\:text-\\[18px\\]{font-size:18px}.clcosdk\\:text-\\[22px\\]{font-size:22px}.clcosdk\\:text-\\[28px\\]{font-size:28px}.clcosdk\\:text-\\[36px\\]{font-size:36px}.clcosdk\\:text-\\[48px\\]{font-size:48px}.clcosdk\\:text-\\[64px\\]{font-size:64px}.clcosdk\\:leading-\\[105\\%\\]{--tw-leading:105%;line-height:105%}.clcosdk\\:leading-\\[108\\%\\]{--tw-leading:108%;line-height:108%}.clcosdk\\:leading-\\[110\\%\\]{--tw-leading:110%;line-height:110%}.clcosdk\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:leading-\\[130\\%\\]{--tw-leading:130%;line-height:130%}.clcosdk\\:leading-\\[140\\%\\]{--tw-leading:140%;line-height:140%}.clcosdk\\:leading-\\[150\\%\\]{--tw-leading:150%;line-height:150%}.clcosdk\\:leading-\\[160\\%\\]{--tw-leading:160%;line-height:160%}.clcosdk\\:font-medium{--tw-font-weight:var(--clcosdk-font-weight-medium);font-weight:var(--clcosdk-font-weight-medium)}.clcosdk\\:font-normal{--tw-font-weight:var(--clcosdk-font-weight-normal);font-weight:var(--clcosdk-font-weight-normal)}.clcosdk\\:font-semibold{--tw-font-weight:var(--clcosdk-font-weight-semibold);font-weight:var(--clcosdk-font-weight-semibold)}.clcosdk\\:tracking-\\[0\\.12px\\]{--tw-tracking:.12px;letter-spacing:.12px}.clcosdk\\:tracking-\\[0\\.28px\\]{--tw-tracking:.28px;letter-spacing:.28px}.clcosdk\\:break-words{overflow-wrap:break-word}.clcosdk\\:whitespace-nowrap{white-space:nowrap}.clcosdk\\:text-background{color:var(--color-background)}.clcosdk\\:text-brand-primary{color:var(--color-brand-primary)}.clcosdk\\:text-error{color:var(--color-error)}.clcosdk\\:text-positive{color:var(--color-positive)}.clcosdk\\:text-sale-card-text{color:var(--color-sale-card-text)}.clcosdk\\:text-sale-card-text-muted{color:var(--color-sale-card-text-muted)}.clcosdk\\:text-sale-card-text-strong{color:var(--color-sale-card-text-strong)}.clcosdk\\:text-success{color:var(--color-success)}.clcosdk\\:text-text-disabled{color:var(--color-text-disabled)}.clcosdk\\:text-text-inverse{color:var(--color-text-inverse)}.clcosdk\\:text-text-primary{color:var(--color-text-primary)}.clcosdk\\:text-text-secondary{color:var(--color-text-secondary)}.clcosdk\\:text-warning{color:var(--color-warning)}.clcosdk\\:capitalize{text-transform:capitalize}.clcosdk\\:lining-nums{--tw-numeric-figure:lining-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.clcosdk\\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.clcosdk\\:no-underline{text-decoration-line:none}.clcosdk\\:underline{text-decoration-line:underline}.clcosdk\\:underline-offset-2{text-underline-offset:2px}.clcosdk\\:underline-offset-4{text-underline-offset:4px}.clcosdk\\:opacity-0{opacity:0}.clcosdk\\:opacity-60{opacity:.6}.clcosdk\\:shadow-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.2\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f633);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0px_1px_1px_0px_rgba\\(10\\,10\\,10\\,0\\.04\\)\\,0px_8px_12px_0px_rgba\\(10\\,10\\,10\\,0\\.08\\)\\]{--tw-shadow:0px 1px 1px 0px var(--tw-shadow-color,#0a0a0a0a), 0px 8px 12px 0px var(--tw-shadow-color,#0a0a0a14);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[0px_4px_12px_0px_rgba\\(0\\,0\\,0\\,0\\.08\\)\\,0px_12px_28px_0px_rgba\\(0\\,0\\,0\\,0\\.13\\)\\]{--tw-shadow:0px 4px 12px 0px var(--tw-shadow-color,#00000014), 0px 12px 28px 0px var(--tw-shadow-color,#00000021);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-\\[var\\(--btn-primary-shadow\\)\\]{--tw-shadow:var(--btn-primary-shadow);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-card{--tw-shadow:0px 4px 6px -2px var(--tw-shadow-color,#0000000d), 0px 12px 24px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-dialog{--tw-shadow:var(--shadow-dialog);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:shadow-step-active{--tw-shadow:var(--shadow-step-active);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:transition-\\[background-color\\,border-color\\]{transition-property:background-color,border-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-\\[grid-template-rows\\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.clcosdk\\:duration-200{--tw-duration:.2s;transition-duration:.2s}.clcosdk\\:duration-300{--tw-duration:.3s;transition-duration:.3s}.clcosdk\\:duration-500{--tw-duration:.5s;transition-duration:.5s}.clcosdk\\:ease-in-out{--tw-ease:var(--clcosdk-ease-in-out);transition-timing-function:var(--clcosdk-ease-in-out)}.clcosdk\\:ease-out{--tw-ease:var(--clcosdk-ease-out);transition-timing-function:var(--clcosdk-ease-out)}.clcosdk\\:outline-none{--tw-outline-style:none;outline-style:none}.clcosdk\\:group-focus-within\\:opacity-100:is(:where(.clcosdk\\:group):focus-within *){opacity:1}@media (hover:hover){.clcosdk\\:group-hover\\:border-sale-card-chrome-emphasis-border:is(:where(.clcosdk\\:group):hover *){border-color:var(--color-sale-card-chrome-emphasis-border)}.clcosdk\\:group-hover\\:bg-sale-card-chrome-emphasis-bg:is(:where(.clcosdk\\:group):hover *){background-color:var(--color-sale-card-chrome-emphasis-bg)}.clcosdk\\:group-hover\\:opacity-100:is(:where(.clcosdk\\:group):hover *){opacity:1}}.clcosdk\\:group-focus-visible\\:border-sale-card-chrome-emphasis-border:is(:where(.clcosdk\\:group):focus-visible *){border-color:var(--color-sale-card-chrome-emphasis-border)}.clcosdk\\:group-focus-visible\\:bg-sale-card-chrome-emphasis-bg:is(:where(.clcosdk\\:group):focus-visible *){background-color:var(--color-sale-card-chrome-emphasis-bg)}.clcosdk\\:placeholder\\:text-text-disabled::placeholder{color:var(--color-text-disabled)}@media (hover:hover){.clcosdk\\:hover\\:scale-\\[1\\.02\\]:hover{scale:1.02}.clcosdk\\:hover\\:border-text-disabled:hover{border-color:var(--color-text-disabled)}.clcosdk\\:hover\\:bg-\\[\\#fcdcd8\\]:hover{background-color:#fcdcd8}.clcosdk\\:hover\\:bg-border:hover{background-color:var(--color-border)}.clcosdk\\:hover\\:bg-brand-primary:hover{background-color:var(--color-brand-primary)}.clcosdk\\:hover\\:bg-brand-primary-hover:hover{background-color:var(--color-brand-primary-hover)}.clcosdk\\:hover\\:bg-section:hover{background-color:var(--color-section)}.clcosdk\\:hover\\:bg-surface:hover{background-color:var(--color-surface)}.clcosdk\\:hover\\:text-\\[\\#8b1a13\\]:hover{color:#8b1a13}.clcosdk\\:hover\\:text-text-primary:hover{color:var(--color-text-primary)}.clcosdk\\:hover\\:underline:hover{text-decoration-line:underline}.clcosdk\\:hover\\:opacity-80:hover{opacity:.8}.clcosdk\\:hover\\:opacity-90:hover{opacity:.9}}.clcosdk\\:focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.clcosdk\\:focus-visible\\:ring-gray-400:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-400)}.clcosdk\\:focus-visible\\:ring-gray-500:focus-visible{--tw-ring-color:var(--clcosdk-color-gray-500)}.clcosdk\\:focus-visible\\:ring-red-400:focus-visible{--tw-ring-color:var(--clcosdk-color-red-400)}.clcosdk\\:focus-visible\\:ring-red-500:focus-visible{--tw-ring-color:var(--clcosdk-color-red-500)}.clcosdk\\:focus-visible\\:ring-sale-card-focus-ring:focus-visible{--tw-ring-color:var(--color-sale-card-focus-ring)}.clcosdk\\:focus-visible\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.clcosdk\\:focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.clcosdk\\:active\\:bg-\\[\\#d9d9d9\\]:active{background-color:#d9d9d9}.clcosdk\\:active\\:bg-\\[\\#f9c9c4\\]:active{background-color:#f9c9c4}.clcosdk\\:active\\:bg-border:active{background-color:var(--color-border)}.clcosdk\\:active\\:bg-brand-primary-active:active{background-color:var(--color-brand-primary-active)}.clcosdk\\:active\\:text-\\[\\#6d1510\\]:active{color:#6d1510}.clcosdk\\:active\\:opacity-80:active{opacity:.8}.clcosdk\\:disabled\\:pointer-events-none:disabled{pointer-events:none}.clcosdk\\:disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.clcosdk\\:disabled\\:opacity-40:disabled{opacity:.4}.clcosdk\\:disabled\\:opacity-50:disabled{opacity:.5}.clcosdk\\:aria-disabled\\:cursor-not-allowed[aria-disabled=true]{cursor:not-allowed}.clcosdk\\:aria-disabled\\:opacity-50[aria-disabled=true]{opacity:.5}@media not all and (min-width:48rem){.clcosdk\\:max-md\\:hidden{display:none}.clcosdk\\:max-md\\:w-full{width:100%}.clcosdk\\:max-md\\:justify-start{justify-content:flex-start}.clcosdk\\:max-md\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:max-md\\:rounded-none{border-radius:0}.clcosdk\\:max-md\\:border-0{border-style:var(--tw-border-style);border-width:0}.clcosdk\\:max-md\\:bg-transparent{background-color:#0000}.clcosdk\\:max-md\\:p-0{padding:0}@media (hover:hover){.clcosdk\\:max-md\\:hover\\:scale-100:hover{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x) var(--tw-scale-y)}}}@media (min-width:40rem){.clcosdk\\:sm\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:48rem){.clcosdk\\:md\\:right-\\[-10\\%\\]{right:-10%}.clcosdk\\:md\\:order-1{order:1}.clcosdk\\:md\\:order-2{order:2}.clcosdk\\:md\\:hidden{display:none}.clcosdk\\:md\\:size-\\[20rem\\]{width:20rem;height:20rem}.clcosdk\\:md\\:h-9{height:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:md\\:h-12{height:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:md\\:h-\\[54px\\]{height:54px}.clcosdk\\:md\\:w-9{width:calc(var(--clcosdk-spacing) * 9)}.clcosdk\\:md\\:w-12{width:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:md\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.clcosdk\\:md\\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.clcosdk\\:md\\:grid-cols-\\[minmax\\(0\\,11fr\\)_minmax\\(0\\,8fr\\)\\]{grid-template-columns:minmax(0,11fr) minmax(0,8fr)}.clcosdk\\:md\\:flex-row{flex-direction:row}.clcosdk\\:md\\:items-center{align-items:center}.clcosdk\\:md\\:items-end{align-items:flex-end}.clcosdk\\:md\\:justify-between{justify-content:space-between}.clcosdk\\:md\\:justify-end{justify-content:flex-end}.clcosdk\\:md\\:gap-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:md\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:gap-x-12{column-gap:calc(var(--clcosdk-spacing) * 12)}.clcosdk\\:md\\:self-end{align-self:flex-end}.clcosdk\\:md\\:rounded-\\[40px\\]{border-radius:40px}.clcosdk\\:md\\:rounded-card{border-radius:24px}.clcosdk\\:md\\:rounded-dialog{border-radius:32px}.clcosdk\\:md\\:p-4{padding:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:md\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:p-8{padding:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:md\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:px-8{padding-inline:calc(var(--clcosdk-spacing) * 8)}.clcosdk\\:md\\:py-2{padding-block:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:md\\:pr-2{padding-right:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:md\\:pr-4{padding-right:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:md\\:pl-4{padding-left:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:md\\:text-base{font-size:var(--clcosdk-text-base);line-height:var(--tw-leading,var(--clcosdk-text-base--line-height))}.clcosdk\\:md\\:text-\\[14px\\]{font-size:14px}.clcosdk\\:md\\:text-\\[16px\\]{font-size:16px}.clcosdk\\:md\\:text-\\[18px\\]{font-size:18px}.clcosdk\\:md\\:text-\\[28px\\]{font-size:28px}.clcosdk\\:md\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:md\\:leading-\\[160\\%\\]{--tw-leading:160%;line-height:160%}}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:not(:where(.light,.light *)):hover{background-color:#f8717133}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.20\\)\\]:where(.dark,.dark *):hover{background-color:#f8717133}}@media (prefers-color-scheme:dark){@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:not(:where(.light,.light *)):hover{color:#fca5a5}}}@media (hover:hover){.clcosdk\\:dark\\:hover\\:text-\\[\\#fca5a5\\]:where(.dark,.dark *):hover{color:#fca5a5}}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:not(:where(.light,.light *)):active{background-color:#f871714d}}.clcosdk\\:dark\\:active\\:bg-\\[rgba\\(248\\,113\\,113\\,0\\.30\\)\\]:where(.dark,.dark *):active{background-color:#f871714d}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:bg-divider:not(:where(.light,.light *)):active{background-color:var(--color-divider)}}.clcosdk\\:dark\\:active\\:bg-divider:where(.dark,.dark *):active{background-color:var(--color-divider)}@media (prefers-color-scheme:dark){.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:not(:where(.light,.light *)):active{color:#f87171}}.clcosdk\\:dark\\:active\\:text-\\[\\#f87171\\]:where(.dark,.dark *):active{color:#f87171}.clcosdk\\:\\[\\&_circle\\]\\:fill-error-subtle circle{fill:var(--color-error-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-success-subtle circle{fill:var(--color-success-subtle)}.clcosdk\\:\\[\\&_circle\\]\\:fill-warning-subtle circle{fill:var(--color-warning-subtle)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}';
4120
4138
 
4121
4139
  // src/client/CoinListStyleScope.tsx
4122
4140
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -4649,7 +4667,7 @@ function CoinListSignInCardContainer({
4649
4667
  }
4650
4668
 
4651
4669
  // src/client/components/checkout/CheckoutContainer.tsx
4652
- var import_react34 = require("react");
4670
+ var import_react35 = require("react");
4653
4671
 
4654
4672
  // src/client/components/checkout/shared/amount/CheckoutAmountInput.tsx
4655
4673
  var import_react8 = require("react");
@@ -8447,7 +8465,7 @@ function ErrorView4({
8447
8465
  }
8448
8466
 
8449
8467
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
8450
- var import_react22 = require("react");
8468
+ var import_react23 = require("react");
8451
8469
 
8452
8470
  // src/client/hooks/checkout/ondo/buy/amount/useOndoBuyAmountViewModel.ts
8453
8471
  var import_react15 = require("react");
@@ -8474,6 +8492,26 @@ function stablecoinIconUrl(symbol) {
8474
8492
  function offerIconUrl(offer) {
8475
8493
  return offer.logoUrl === "" ? null : AssetIconUrl(offer.logoUrl);
8476
8494
  }
8495
+ function tokenLogoUrl(logo, minWidth = 40) {
8496
+ switch (logo.kind) {
8497
+ case "VECTOR":
8498
+ return AssetIconUrl(logo.url);
8499
+ case "RASTER": {
8500
+ const chosen = logo.variants.reduce(
8501
+ (smallest, variant) => variant.width >= minWidth && (smallest === null || variant.width < smallest.width) ? variant : smallest,
8502
+ null
8503
+ );
8504
+ return AssetIconUrl((chosen ?? logo.original).url);
8505
+ }
8506
+ default: {
8507
+ const exhaustive = logo;
8508
+ return exhaustive;
8509
+ }
8510
+ }
8511
+ }
8512
+ function offerAssetIconUrl(offer, tokenMetadata) {
8513
+ return (tokenMetadata ? tokenLogoUrl(tokenMetadata.logo) : null) ?? offerIconUrl(offer);
8514
+ }
8477
8515
 
8478
8516
  // src/client/hooks/checkout/shared/checkout-ui.types.ts
8479
8517
  var CheckoutAssetUi = {
@@ -8482,10 +8520,10 @@ var CheckoutAssetUi = {
8482
8520
  * name and symbol, the caller supplies the chain it is being traded on and
8483
8521
  * whatever icon it has for it.
8484
8522
  *
8485
- * `iconUrl` is a caller's parameter rather than the token's own because a
8486
- * token does not carry one - the SDK ships no icon registry, and the only
8487
- * source is the offer being bought. Which is also why it defaults to `null`:
8488
- * the input asset a user pays with has no offer behind it.
8523
+ * `iconUrl` is a caller's parameter rather than the token's own because an
8524
+ * `Erc20Asset` does not carry one, and which source supplies it is the
8525
+ * caller's to decide. Which is also why it defaults to `null`: the input
8526
+ * asset a user pays with has no offer behind it.
8489
8527
  *
8490
8528
  * An asset sourced from the offer rather than from a token has its own
8491
8529
  * companion, {@link fromOffer}. One companion per source, not one per call
@@ -8502,7 +8540,7 @@ var CheckoutAssetUi = {
8502
8540
  }),
8503
8541
  /**
8504
8542
  * The view of the asset an offer sells: the offer supplies its name and the
8505
- * only icon the SDK has, the caller supplies the symbol and the chain.
8543
+ * fallback artwork, the caller supplies the symbol and the chain.
8506
8544
  *
8507
8545
  * `symbol` is a parameter rather than `offer.asset.code` because the symbol a
8508
8546
  * provider trades under is the provider's, not the catalogue's - Ondo's
@@ -8510,14 +8548,26 @@ var CheckoutAssetUi = {
8510
8548
  * asset stands in. Keeping it out here is what lets one companion serve every
8511
8549
  * provider instead of forking per provider.
8512
8550
  *
8551
+ * The icon is resolved from the public token registry when `tokenMetadata`
8552
+ * carries a listed token — `useCheckoutOfferTokenMetadata` fetches it,
8553
+ * keyed by the token `OfferDetail.tokens` lists for this chain — and falls
8554
+ * back to the offer's own logo otherwise. `null` covers every way the
8555
+ * registry answer can be absent (unlisted, not settled, lookup failed);
8556
+ * which one it is stays the concern of the hook's state machine, not of
8557
+ * this model, because the icon is the same either way.
8558
+ *
8513
8559
  * Deliberately no decimals. An offer names an asset; it does not answer for
8514
8560
  * the scale of any particular quantity, and every amount a checkout renders
8515
8561
  * arrives as a `BlockchainAmount` carrying its own.
8516
8562
  */
8517
- fromOffer: (offer, { symbol, networkName }) => ({
8563
+ fromOffer: (offer, {
8564
+ symbol,
8565
+ networkName,
8566
+ tokenMetadata
8567
+ }) => ({
8518
8568
  name: offer.name,
8519
8569
  symbol,
8520
- iconUrl: offerIconUrl(offer),
8570
+ iconUrl: offerAssetIconUrl(offer, tokenMetadata),
8521
8571
  network: { name: networkName, iconUrl: null }
8522
8572
  })
8523
8573
  };
@@ -8602,6 +8652,7 @@ function useOndoBuyAmountViewModel({
8602
8652
  stepInput,
8603
8653
  ondoSymbol,
8604
8654
  chain,
8655
+ swapContracts,
8605
8656
  enabled = true,
8606
8657
  onComplete,
8607
8658
  onEdit
@@ -8706,6 +8757,7 @@ function useOndoBuyAmountViewModel({
8706
8757
  wallet: stepInput.wallet,
8707
8758
  symbol: ondoSymbol,
8708
8759
  chain,
8760
+ swapContracts,
8709
8761
  // The input asset is USDC on every chain the SDK models (it is the
8710
8762
  // only member of `ONDO_SUPPORTED_INPUT_ASSETS`), and its registry
8711
8763
  // table is total, so the address is never null.
@@ -9036,6 +9088,7 @@ function useOndoBuyReviewViewModel({
9036
9088
  ondoSymbol,
9037
9089
  chain,
9038
9090
  offer,
9091
+ outputTokenMetadata,
9039
9092
  enabled = true,
9040
9093
  onComplete
9041
9094
  }) {
@@ -9088,7 +9141,8 @@ function useOndoBuyReviewViewModel({
9088
9141
  type: "active",
9089
9142
  outputAsset: CheckoutAssetUi.fromOffer(offer, {
9090
9143
  symbol: ondoSymbol,
9091
- networkName: getNetworkName(chain)
9144
+ networkName: getNetworkName(chain),
9145
+ tokenMetadata: outputTokenMetadata
9092
9146
  }),
9093
9147
  outputAmount: assetAmount(
9094
9148
  formatAmount(built.receiveOutputAmount, locale),
@@ -9226,8 +9280,6 @@ function executionErrorMessage(error) {
9226
9280
  switch (error.step) {
9227
9281
  case "quote-expired":
9228
9282
  return "That quote expired. Get a new one to place your order.";
9229
- case "spender-mismatch":
9230
- return "This quote does not match the approval you gave. Get a new one.";
9231
9283
  case "swap":
9232
9284
  switch (error.cause.type) {
9233
9285
  case "user_rejected":
@@ -9421,6 +9473,7 @@ function useOndoSidebarViewModel({
9421
9473
  offer,
9422
9474
  ondoSymbol,
9423
9475
  chain,
9476
+ tokenMetadata,
9424
9477
  priceState,
9425
9478
  tradingStatusState
9426
9479
  }) {
@@ -9428,7 +9481,8 @@ function useOndoSidebarViewModel({
9428
9481
  const state = {
9429
9482
  asset: CheckoutAssetUi.fromOffer(offer, {
9430
9483
  symbol: ondoSymbol,
9431
- networkName: getNetworkName(chain)
9484
+ networkName: getNetworkName(chain),
9485
+ tokenMetadata
9432
9486
  }),
9433
9487
  // No frontline endpoint carries any of these today, and the detail list
9434
9488
  // drops a null row rather than dashing it.
@@ -9618,6 +9672,99 @@ function toConfirmedWalletUi(wallets, wallet) {
9618
9672
  };
9619
9673
  }
9620
9674
 
9675
+ // src/client/hooks/shared/useTokenMetadata.ts
9676
+ var import_react22 = require("react");
9677
+ var DISABLED_STATE = { type: "DISABLED" };
9678
+ var LOADING_STATE = { type: "LOADING" };
9679
+ function useTokenMetadata(options) {
9680
+ const { chain, address, data, enabled = true } = options;
9681
+ const { coinlist, isReady } = useCoinList();
9682
+ const log = useLogger("useTokenMetadata");
9683
+ const [state, setState] = (0, import_react22.useState)(
9684
+ () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE
9685
+ );
9686
+ const [refetchCount, setRefetchCount] = (0, import_react22.useState)(0);
9687
+ const refetch = (0, import_react22.useCallback)(() => {
9688
+ setRefetchCount((count) => count + 1);
9689
+ }, []);
9690
+ (0, import_react22.useEffect)(() => {
9691
+ let isCancelled = false;
9692
+ const seedActive = data !== void 0 && refetchCount === 0;
9693
+ if (!isReady || !enabled || seedActive) {
9694
+ return () => {
9695
+ isCancelled = true;
9696
+ };
9697
+ }
9698
+ setState(LOADING_STATE);
9699
+ coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
9700
+ if (!isCancelled) {
9701
+ log.debug(() => ({
9702
+ msg: "settled",
9703
+ fields: {
9704
+ state: "CONTENT",
9705
+ listed: tokenMetadata !== null,
9706
+ symbol: tokenMetadata?.symbol ?? null
9707
+ }
9708
+ }));
9709
+ setState({ type: "CONTENT", tokenMetadata });
9710
+ }
9711
+ }).catch((error) => {
9712
+ if (!isCancelled) {
9713
+ log.failure(
9714
+ () => ({
9715
+ msg: "settled",
9716
+ fields: { state: "ERROR", reason: "generic-error" }
9717
+ }),
9718
+ error
9719
+ );
9720
+ setState({ type: "ERROR", reason: "generic-error" });
9721
+ }
9722
+ });
9723
+ return () => {
9724
+ isCancelled = true;
9725
+ };
9726
+ }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
9727
+ return {
9728
+ // LOADING would be a lie while disabled: nothing is in flight and nothing
9729
+ // will replace it. Settled states (a seed, a previous answer) survive.
9730
+ state: !enabled && state.type === "LOADING" ? DISABLED_STATE : state,
9731
+ refetch
9732
+ };
9733
+ }
9734
+
9735
+ // src/client/hooks/checkout/shared/data/useCheckoutOfferTokenMetadata.ts
9736
+ var NO_TOKEN_ADDRESS = EvmContractAddress(
9737
+ "0x0000000000000000000000000000000000000000"
9738
+ );
9739
+ function offerTokenIdentifier(offer, chain) {
9740
+ const byChain = offer.tokens.filter((token) => token.chain === chain);
9741
+ const asset = byChain.find((token) => token.role === "swap") ?? byChain.find((token) => token.role === "distribution");
9742
+ return asset === void 0 ? null : { chain, address: asset.address };
9743
+ }
9744
+ function tokenMetadataOf(state) {
9745
+ return state.type === "CONTENT" ? state.tokenMetadata : null;
9746
+ }
9747
+ function useCheckoutOfferTokenMetadata({
9748
+ offer,
9749
+ chain,
9750
+ data,
9751
+ enabled = true
9752
+ }) {
9753
+ const identifier = offerTokenIdentifier(offer, chain);
9754
+ const { state } = useTokenMetadata({
9755
+ // Primitive keys, not the identifier object: the underlying hook re-fetches
9756
+ // only when `(chain, address)` changes, so a host that rebuilds the offer
9757
+ // object per render does not refetch the registry per render.
9758
+ chain: identifier?.chain ?? chain,
9759
+ address: identifier?.address ?? NO_TOKEN_ADDRESS,
9760
+ // Nothing to look up when the offer lists no token here: seed "not
9761
+ // listed" and never fire a request against the placeholder address.
9762
+ enabled: enabled && identifier !== null,
9763
+ data: data !== void 0 ? data : identifier === null ? null : void 0
9764
+ });
9765
+ return { state };
9766
+ }
9767
+
9621
9768
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
9622
9769
  function useOndoBuyCheckoutViewModel({
9623
9770
  offer,
@@ -9628,9 +9775,10 @@ function useOndoBuyCheckoutViewModel({
9628
9775
  onOrderConfirmed
9629
9776
  }) {
9630
9777
  const locale = useLocale();
9631
- const [step, setStep] = (0, import_react22.useState)({ type: "wallet" });
9632
- const [orderConfirmed, setOrderConfirmed] = (0, import_react22.useState)({ type: "hidden" });
9633
- const live = enabled && ondoSwapContractAddress(chain) !== null;
9778
+ const [step, setStep] = (0, import_react23.useState)({ type: "wallet" });
9779
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react23.useState)(null);
9780
+ const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
9781
+ const live = enabled && swappableHere;
9634
9782
  const { state: priceState } = useOndoPrice({
9635
9783
  symbol: ondoSymbol,
9636
9784
  side: "buy",
@@ -9644,6 +9792,20 @@ function useOndoBuyCheckoutViewModel({
9644
9792
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
9645
9793
  enabled: live
9646
9794
  });
9795
+ const { state: outputTokenMetadataState } = useCheckoutOfferTokenMetadata({
9796
+ offer,
9797
+ chain,
9798
+ enabled: live
9799
+ });
9800
+ const outputTokenMetadata = tokenMetadataOf(outputTokenMetadataState);
9801
+ const orderConfirmedUi = (order) => order === null ? { type: "hidden" } : toOrderConfirmedUi({
9802
+ order,
9803
+ chain,
9804
+ locale,
9805
+ offer,
9806
+ ondoSymbol,
9807
+ outputTokenMetadata
9808
+ });
9647
9809
  const { state: walletState, onEvent: onWalletEvent } = useOndoWalletSelectViewModel({
9648
9810
  stepInput: walletStepInput(step),
9649
9811
  wallets,
@@ -9658,6 +9820,7 @@ function useOndoBuyCheckoutViewModel({
9658
9820
  }),
9659
9821
  ondoSymbol,
9660
9822
  chain,
9823
+ swapContracts: offer.swapContracts,
9661
9824
  enabled: live,
9662
9825
  // Both transitions read the step through the updater rather than the one
9663
9826
  // this render closed over. Preparing an amount takes an approval to mine,
@@ -9689,11 +9852,10 @@ function useOndoBuyCheckoutViewModel({
9689
9852
  ondoSymbol,
9690
9853
  chain,
9691
9854
  offer,
9855
+ outputTokenMetadata,
9692
9856
  enabled: live,
9693
9857
  onComplete: (order) => {
9694
- setOrderConfirmed(
9695
- toOrderConfirmedUi({ order, chain, locale, offer, ondoSymbol })
9696
- );
9858
+ setOrderConfirmed(order);
9697
9859
  setStep({ type: "wallet" });
9698
9860
  onOrderConfirmed?.(order);
9699
9861
  }
@@ -9702,16 +9864,17 @@ function useOndoBuyCheckoutViewModel({
9702
9864
  offer,
9703
9865
  ondoSymbol,
9704
9866
  chain,
9867
+ tokenMetadata: outputTokenMetadata,
9705
9868
  priceState,
9706
9869
  tradingStatusState
9707
9870
  });
9708
- const state = ondoSwapContractAddress(chain) === null ? { type: "error", reason: "unsupported-chain" } : {
9871
+ const state = !swappableHere ? { type: "error", reason: "unsupported-chain" } : {
9709
9872
  type: "content",
9710
9873
  wallet: walletState,
9711
9874
  amount: amountState,
9712
9875
  review: reviewState,
9713
9876
  sidebar: sidebarState,
9714
- orderConfirmed
9877
+ orderConfirmed: orderConfirmedUi(orderConfirmed)
9715
9878
  };
9716
9879
  const onEvent = (event) => {
9717
9880
  switch (event.type) {
@@ -9735,7 +9898,7 @@ function useOndoBuyCheckoutViewModel({
9735
9898
  onReviewEvent(event);
9736
9899
  return;
9737
9900
  case "ON_CLOSE_ORDER_CONFIRMED":
9738
- setOrderConfirmed({ type: "hidden" });
9901
+ setOrderConfirmed(null);
9739
9902
  return;
9740
9903
  default: {
9741
9904
  const exhaustive = event;
@@ -9789,14 +9952,16 @@ function toOrderConfirmedUi({
9789
9952
  chain,
9790
9953
  locale,
9791
9954
  offer,
9792
- ondoSymbol
9955
+ ondoSymbol,
9956
+ outputTokenMetadata
9793
9957
  }) {
9794
9958
  const inputSymbol = TOKEN_REGISTRY.erc20(order.inputAsset).symbol;
9795
9959
  return {
9796
9960
  type: "visible",
9797
9961
  outputAsset: CheckoutAssetUi.fromOffer(offer, {
9798
9962
  symbol: ondoSymbol,
9799
- networkName: getNetworkName(chain)
9963
+ networkName: getNetworkName(chain),
9964
+ tokenMetadata: outputTokenMetadata
9800
9965
  }),
9801
9966
  outputAmount: assetAmount(
9802
9967
  formatAmount(order.transaction.receiveOutputAmount, locale),
@@ -9816,13 +9981,13 @@ function toOrderConfirmedUi({
9816
9981
  }
9817
9982
 
9818
9983
  // src/client/hooks/checkout/ondo/sell/useOndoSellCheckoutViewModel.ts
9819
- var import_react27 = require("react");
9984
+ var import_react28 = require("react");
9820
9985
 
9821
9986
  // src/client/hooks/checkout/ondo/sell/amount/useOndoSellAmountViewModel.ts
9822
- var import_react24 = require("react");
9987
+ var import_react25 = require("react");
9823
9988
 
9824
9989
  // src/client/hooks/shared/erc20/useErc20Balance.ts
9825
- var import_react23 = require("react");
9990
+ var import_react24 = require("react");
9826
9991
  function useErc20Balance(options) {
9827
9992
  const {
9828
9993
  tokenAddress,
@@ -9833,12 +9998,12 @@ function useErc20Balance(options) {
9833
9998
  } = options;
9834
9999
  const { coinlist, isReady } = useCoinList();
9835
10000
  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)(() => {
10001
+ const [balance, setBalance] = (0, import_react24.useState)(null);
10002
+ const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
10003
+ const fetchIdRef = (0, import_react24.useRef)(0);
10004
+ const isFetchingRef = (0, import_react24.useRef)(false);
10005
+ const hasReadRef = (0, import_react24.useRef)(false);
10006
+ (0, import_react24.useEffect)(() => {
9842
10007
  if (!isReady) return;
9843
10008
  setBalance(null);
9844
10009
  hasReadRef.current = false;
@@ -9915,16 +10080,17 @@ function useOndoSellAmountViewModel({
9915
10080
  ondoSymbol,
9916
10081
  chain,
9917
10082
  offer,
10083
+ inputTokenMetadata,
9918
10084
  enabled = true,
9919
10085
  onComplete,
9920
10086
  onEdit
9921
10087
  }) {
9922
10088
  const { coinlist } = useCoinList();
9923
10089
  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);
10090
+ const [amountInput, setAmountInput] = (0, import_react25.useState)("");
10091
+ const [error, setError] = (0, import_react25.useState)(null);
10092
+ const [phase, setPhase] = (0, import_react25.useState)(null);
10093
+ const preparationIdRef = (0, import_react25.useRef)(0);
9928
10094
  const isActive = stepInput.type === "active";
9929
10095
  const networkName = getNetworkName(chain);
9930
10096
  const sellAsset2 = isActive ? stepInput.sellAsset : null;
@@ -9935,7 +10101,7 @@ function useOndoSellAmountViewModel({
9935
10101
  chain,
9936
10102
  enabled: enabled && isActive && sellAsset2 !== null
9937
10103
  });
9938
- (0, import_react24.useEffect)(() => {
10104
+ (0, import_react25.useEffect)(() => {
9939
10105
  if (stepInput.type === "incomplete") {
9940
10106
  ++preparationIdRef.current;
9941
10107
  setAmountInput("");
@@ -9961,7 +10127,8 @@ function useOndoSellAmountViewModel({
9961
10127
  type: "complete",
9962
10128
  asset: CheckoutAssetUi.fromOffer(offer, {
9963
10129
  symbol: stepInput.inputAsset,
9964
- networkName
10130
+ networkName,
10131
+ tokenMetadata: inputTokenMetadata
9965
10132
  }),
9966
10133
  amountFormatted: assetAmount(
9967
10134
  formatAmount(stepInput.amount, locale),
@@ -9983,7 +10150,8 @@ function useOndoSellAmountViewModel({
9983
10150
  return {
9984
10151
  asset: CheckoutAssetUi.fromOffer(offer, {
9985
10152
  symbol: ondoSymbol,
9986
- networkName
10153
+ networkName,
10154
+ tokenMetadata: inputTokenMetadata
9987
10155
  }),
9988
10156
  balance: assetAmount(formatAmount(amount, locale), ondoSymbol),
9989
10157
  rawBalance: balance
@@ -10019,6 +10187,7 @@ function useOndoSellAmountViewModel({
10019
10187
  wallet: stepInput.wallet,
10020
10188
  symbol: ondoSymbol,
10021
10189
  chain,
10190
+ swapContracts: offer.swapContracts,
10022
10191
  // The asset, not a stablecoin: a sell spends what it is selling, so this
10023
10192
  // is the contract the swap contract has to be allowed to pull from.
10024
10193
  tokenAddress: asset.address,
@@ -10169,15 +10338,15 @@ function preparationErrorMessage2(error) {
10169
10338
  }
10170
10339
 
10171
10340
  // src/client/hooks/checkout/ondo/sell/review/useOndoSellReviewViewModel.ts
10172
- var import_react26 = require("react");
10341
+ var import_react27 = require("react");
10173
10342
 
10174
10343
  // src/client/hooks/checkout/ondo/sell/data/useOndoSellTransaction.ts
10175
- var import_react25 = require("react");
10344
+ var import_react26 = require("react");
10176
10345
  function useOndoSellTransaction(options) {
10177
10346
  const { request, data, enabled } = options;
10178
10347
  const { coinlist, isReady } = useCoinList();
10179
10348
  const log = useLogger("useOndoSellTransaction");
10180
- const [state, setState] = (0, import_react25.useState)(
10349
+ const [state, setState] = (0, import_react26.useState)(
10181
10350
  () => data === void 0 ? { type: "LOADING" } : {
10182
10351
  type: "CONTENT",
10183
10352
  transaction: data,
@@ -10185,12 +10354,12 @@ function useOndoSellTransaction(options) {
10185
10354
  refreshError: null
10186
10355
  }
10187
10356
  );
10188
- const fetchIdRef = (0, import_react25.useRef)(0);
10189
- const isFetchingRef = (0, import_react25.useRef)(false);
10357
+ const fetchIdRef = (0, import_react26.useRef)(0);
10358
+ const isFetchingRef = (0, import_react26.useRef)(false);
10190
10359
  const requestKey = request === null ? null : stableKey2(request);
10191
- const requestRef = (0, import_react25.useRef)(request);
10360
+ const requestRef = (0, import_react26.useRef)(request);
10192
10361
  requestRef.current = request;
10193
- const build = (0, import_react25.useCallback)(async () => {
10362
+ const build = (0, import_react26.useCallback)(async () => {
10194
10363
  const params = requestRef.current;
10195
10364
  if (!isReady || !enabled || params === null) return;
10196
10365
  if (isFetchingRef.current) return;
@@ -10226,7 +10395,7 @@ function useOndoSellTransaction(options) {
10226
10395
  isFetchingRef.current = false;
10227
10396
  }
10228
10397
  }, [coinlist, isReady, enabled, log]);
10229
- (0, import_react25.useEffect)(() => {
10398
+ (0, import_react26.useEffect)(() => {
10230
10399
  if (data === void 0) return;
10231
10400
  ++fetchIdRef.current;
10232
10401
  setState({
@@ -10237,14 +10406,14 @@ function useOndoSellTransaction(options) {
10237
10406
  });
10238
10407
  }, [data]);
10239
10408
  const hasSeed = data !== void 0;
10240
- (0, import_react25.useEffect)(() => {
10409
+ (0, import_react26.useEffect)(() => {
10241
10410
  if (hasSeed || requestKey === null) return;
10242
10411
  build();
10243
10412
  return () => {
10244
10413
  ++fetchIdRef.current;
10245
10414
  };
10246
10415
  }, [build, requestKey, hasSeed]);
10247
- const refetch = (0, import_react25.useCallback)(() => {
10416
+ const refetch = (0, import_react26.useCallback)(() => {
10248
10417
  build();
10249
10418
  }, [build]);
10250
10419
  return { state, refetch };
@@ -10269,8 +10438,8 @@ function useOndoSellReviewViewModel({
10269
10438
  }) {
10270
10439
  const { coinlist } = useCoinList();
10271
10440
  const locale = useLocale();
10272
- const [phase, setPhase] = (0, import_react26.useState)(null);
10273
- const [error, setError] = (0, import_react26.useState)(null);
10441
+ const [phase, setPhase] = (0, import_react27.useState)(null);
10442
+ const [error, setError] = (0, import_react27.useState)(null);
10274
10443
  const isActive = stepInput.type === "active";
10275
10444
  const { state: transactionState, refetch } = useOndoSellTransaction({
10276
10445
  request: isActive ? {
@@ -10282,8 +10451,8 @@ function useOndoSellReviewViewModel({
10282
10451
  data: isActive ? stepInput.transaction : void 0,
10283
10452
  enabled: enabled && isActive
10284
10453
  });
10285
- const executionIdRef = (0, import_react26.useRef)(0);
10286
- (0, import_react26.useEffect)(() => {
10454
+ const executionIdRef = (0, import_react27.useRef)(0);
10455
+ (0, import_react27.useEffect)(() => {
10287
10456
  if (stepInput.type === "incomplete") {
10288
10457
  ++executionIdRef.current;
10289
10458
  setError(null);
@@ -10460,8 +10629,6 @@ function executionErrorMessage2(error) {
10460
10629
  switch (error.step) {
10461
10630
  case "quote-expired":
10462
10631
  return "That quote expired. Get a new one to place your order.";
10463
- case "spender-mismatch":
10464
- return "This quote does not match the approval you gave. Get a new one.";
10465
10632
  case "swap":
10466
10633
  switch (error.cause.type) {
10467
10634
  case "user_rejected":
@@ -10495,13 +10662,14 @@ function useOndoSellCheckoutViewModel({
10495
10662
  onOrderConfirmed
10496
10663
  }) {
10497
10664
  const locale = useLocale();
10498
- const [initialStep] = (0, import_react27.useState)(
10665
+ const [initialStep] = (0, import_react28.useState)(
10499
10666
  () => wallets.preselected === null ? { type: "wallet" } : { type: "amount", wallet: wallets.preselected }
10500
10667
  );
10501
- const [step, setStep] = (0, import_react27.useState)(initialStep);
10668
+ const [step, setStep] = (0, import_react28.useState)(initialStep);
10502
10669
  const hasWalletStep = initialStep.type === "wallet";
10503
- const [orderConfirmed, setOrderConfirmed] = (0, import_react27.useState)({ type: "hidden" });
10504
- const live = enabled && ondoSwapContractAddress(chain) !== null;
10670
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react28.useState)(null);
10671
+ const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
10672
+ const live = enabled && swappableHere;
10505
10673
  const { state: priceState } = useOndoPrice({
10506
10674
  symbol: ondoSymbol,
10507
10675
  side: "sell",
@@ -10515,6 +10683,20 @@ function useOndoSellCheckoutViewModel({
10515
10683
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
10516
10684
  enabled: live
10517
10685
  });
10686
+ const { state: inputTokenMetadataState } = useCheckoutOfferTokenMetadata({
10687
+ offer,
10688
+ chain,
10689
+ enabled: live
10690
+ });
10691
+ const inputTokenMetadata = tokenMetadataOf(inputTokenMetadataState);
10692
+ const orderConfirmedUi = (order) => order === null ? { type: "hidden" } : toOrderConfirmedUi2({
10693
+ order,
10694
+ chain,
10695
+ locale,
10696
+ offer,
10697
+ ondoSymbol,
10698
+ inputTokenMetadata
10699
+ });
10518
10700
  const { state: walletState, onEvent: onWalletEvent } = useOndoWalletSelectViewModel({
10519
10701
  stepInput: walletStepInput2(step),
10520
10702
  wallets,
@@ -10531,6 +10713,7 @@ function useOndoSellCheckoutViewModel({
10531
10713
  ondoSymbol,
10532
10714
  chain,
10533
10715
  offer,
10716
+ inputTokenMetadata,
10534
10717
  enabled: live,
10535
10718
  // Both transitions read the step through the updater rather than the one
10536
10719
  // this render closed over. Preparing an amount takes an approval to mine,
@@ -10563,9 +10746,7 @@ function useOndoSellCheckoutViewModel({
10563
10746
  chain,
10564
10747
  enabled: live,
10565
10748
  onComplete: (order) => {
10566
- setOrderConfirmed(
10567
- toOrderConfirmedUi2({ order, chain, locale, offer, ondoSymbol })
10568
- );
10749
+ setOrderConfirmed(order);
10569
10750
  setStep(initialStep);
10570
10751
  onOrderConfirmed?.(order);
10571
10752
  }
@@ -10574,16 +10755,17 @@ function useOndoSellCheckoutViewModel({
10574
10755
  offer,
10575
10756
  ondoSymbol,
10576
10757
  chain,
10758
+ tokenMetadata: inputTokenMetadata,
10577
10759
  priceState,
10578
10760
  tradingStatusState
10579
10761
  });
10580
- const state = ondoSwapContractAddress(chain) === null ? { type: "error", reason: "unsupported-chain" } : {
10762
+ const state = !swappableHere ? { type: "error", reason: "unsupported-chain" } : {
10581
10763
  type: "content",
10582
10764
  wallet: hasWalletStep ? walletState : null,
10583
10765
  amount: amountState,
10584
10766
  review: reviewState,
10585
10767
  sidebar: sidebarState,
10586
- orderConfirmed
10768
+ orderConfirmed: orderConfirmedUi(orderConfirmed)
10587
10769
  };
10588
10770
  const onEvent = (event) => {
10589
10771
  switch (event.type) {
@@ -10607,7 +10789,7 @@ function useOndoSellCheckoutViewModel({
10607
10789
  onReviewEvent(event);
10608
10790
  return;
10609
10791
  case "ON_CLOSE_SELL_ORDER_CONFIRMED":
10610
- setOrderConfirmed({ type: "hidden" });
10792
+ setOrderConfirmed(null);
10611
10793
  return;
10612
10794
  default: {
10613
10795
  const exhaustive = event;
@@ -10675,14 +10857,16 @@ function toOrderConfirmedUi2({
10675
10857
  chain,
10676
10858
  locale,
10677
10859
  offer,
10678
- ondoSymbol
10860
+ ondoSymbol,
10861
+ inputTokenMetadata
10679
10862
  }) {
10680
10863
  const settlementSymbol = TOKEN_REGISTRY.erc20(ONDO_SETTLEMENT_ASSET).symbol;
10681
10864
  return {
10682
10865
  type: "visible",
10683
10866
  soldAsset: CheckoutAssetUi.fromOffer(offer, {
10684
10867
  symbol: ondoSymbol,
10685
- networkName: getNetworkName(chain)
10868
+ networkName: getNetworkName(chain),
10869
+ tokenMetadata: inputTokenMetadata
10686
10870
  }),
10687
10871
  soldAmount: assetAmount(
10688
10872
  formatAmount(order.transaction.spendInputAmount, locale),
@@ -10706,10 +10890,10 @@ function toOrderConfirmedUi2({
10706
10890
  }
10707
10891
 
10708
10892
  // src/client/hooks/checkout/superstate/swap/useSuperstateSwapCheckoutViewModel.ts
10709
- var import_react33 = require("react");
10893
+ var import_react34 = require("react");
10710
10894
 
10711
10895
  // src/client/hooks/checkout/superstate/swap/amount/useSuperstateAmountViewModel.ts
10712
- var import_react28 = require("react");
10896
+ var import_react29 = require("react");
10713
10897
  var NO_WALLET3 = EvmWalletAddress(
10714
10898
  "0x0000000000000000000000000000000000000000"
10715
10899
  );
@@ -10723,11 +10907,11 @@ function useSuperstateAmountViewModel({
10723
10907
  enabled = true
10724
10908
  }) {
10725
10909
  const locale = useLocale();
10726
- const [amountInput, setAmountInput] = (0, import_react28.useState)("");
10727
- const [selectedAsset, setSelectedAsset] = (0, import_react28.useState)(
10910
+ const [amountInput, setAmountInput] = (0, import_react29.useState)("");
10911
+ const [selectedAsset, setSelectedAsset] = (0, import_react29.useState)(
10728
10912
  SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]
10729
10913
  );
10730
- const [error, setError] = (0, import_react28.useState)(null);
10914
+ const [error, setError] = (0, import_react29.useState)(null);
10731
10915
  const isActive = stepInput.type === "active";
10732
10916
  const networkName = getNetworkName(chain);
10733
10917
  const { balances, isLoading: balancesLoading } = useErc20TokenBalances({
@@ -10740,7 +10924,7 @@ function useSuperstateAmountViewModel({
10740
10924
  // on this step satisfies the first and not the second.
10741
10925
  enabled: enabled && isActive
10742
10926
  });
10743
- (0, import_react28.useEffect)(() => {
10927
+ (0, import_react29.useEffect)(() => {
10744
10928
  if (stepInput.type === "incomplete") {
10745
10929
  setAmountInput("");
10746
10930
  setSelectedAsset(SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]);
@@ -10911,20 +11095,20 @@ function toInputAssetUi2({
10911
11095
  }
10912
11096
 
10913
11097
  // src/client/hooks/checkout/superstate/swap/data/useSwapOutputToken.ts
10914
- var import_react29 = require("react");
10915
- var LOADING_STATE = { type: "LOADING" };
11098
+ var import_react30 = require("react");
11099
+ var LOADING_STATE2 = { type: "LOADING" };
10916
11100
  function useSwapOutputToken(options) {
10917
11101
  const { contractAddress, chain, enabled } = options;
10918
11102
  const { coinlist, isReady } = useCoinList();
10919
11103
  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);
11104
+ const [outputTokenState, setOutputTokenState] = (0, import_react30.useState)(LOADING_STATE2);
11105
+ const [retryCount, setRetryCount] = (0, import_react30.useState)(0);
11106
+ const fetchIdRef = (0, import_react30.useRef)(0);
11107
+ const refetch = (0, import_react30.useCallback)(() => {
11108
+ setOutputTokenState(LOADING_STATE2);
10925
11109
  setRetryCount((count) => count + 1);
10926
11110
  }, []);
10927
- (0, import_react29.useEffect)(() => {
11111
+ (0, import_react30.useEffect)(() => {
10928
11112
  if (!enabled || !isReady) return;
10929
11113
  const currentFetchId = ++fetchIdRef.current;
10930
11114
  const load = async () => {
@@ -10957,7 +11141,7 @@ function useSwapOutputToken(options) {
10957
11141
  }
10958
11142
 
10959
11143
  // src/client/hooks/checkout/superstate/swap/data/useSwapQuote.ts
10960
- var import_react30 = require("react");
11144
+ var import_react31 = require("react");
10961
11145
  function useSwapQuote(options) {
10962
11146
  const {
10963
11147
  contractAddress,
@@ -10970,13 +11154,13 @@ function useSwapQuote(options) {
10970
11154
  } = options;
10971
11155
  const { coinlist, isReady } = useCoinList();
10972
11156
  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)(() => {
11157
+ const [quote, setQuote] = (0, import_react31.useState)(null);
11158
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
11159
+ const [isRefreshing, setIsRefreshing] = (0, import_react31.useState)(false);
11160
+ const isFetchingRef = (0, import_react31.useRef)(false);
11161
+ const hasQuoteRef = (0, import_react31.useRef)(false);
11162
+ const fetchIdRef = (0, import_react31.useRef)(0);
11163
+ (0, import_react31.useEffect)(() => {
10980
11164
  if (!isReady) return;
10981
11165
  if (!enabled) {
10982
11166
  setIsLoading(false);
@@ -11046,7 +11230,7 @@ function useSwapQuote(options) {
11046
11230
  }
11047
11231
 
11048
11232
  // src/client/hooks/checkout/superstate/swap/review/useSuperstateReviewViewModel.ts
11049
- var import_react31 = require("react");
11233
+ var import_react32 = require("react");
11050
11234
  function useSuperstateReviewViewModel({
11051
11235
  stepInput,
11052
11236
  contractAddress,
@@ -11056,11 +11240,11 @@ function useSuperstateReviewViewModel({
11056
11240
  }) {
11057
11241
  const { coinlist, isReady } = useCoinList();
11058
11242
  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)(() => {
11243
+ const [slippageBps, setSlippageBps] = (0, import_react32.useState)(DEFAULT_SLIPPAGE_BPS);
11244
+ const [slippageExpanded, setSlippageExpanded] = (0, import_react32.useState)(false);
11245
+ const [phase, setPhase] = (0, import_react32.useState)(null);
11246
+ const [error, setError] = (0, import_react32.useState)(null);
11247
+ (0, import_react32.useEffect)(() => {
11064
11248
  if (stepInput.type === "incomplete") {
11065
11249
  setSlippageBps(DEFAULT_SLIPPAGE_BPS);
11066
11250
  setSlippageExpanded(false);
@@ -11389,7 +11573,7 @@ function priceUi(quote, outputToken, locale) {
11389
11573
  }
11390
11574
 
11391
11575
  // src/client/hooks/checkout/superstate/swap/wallet/useSuperstateWalletViewModel.ts
11392
- var import_react32 = require("react");
11576
+ var import_react33 = require("react");
11393
11577
  var CONNECT_FAILED2 = "Could not connect that wallet. Please try again.";
11394
11578
  function useSuperstateWalletViewModel({
11395
11579
  stepInput,
@@ -11402,12 +11586,12 @@ function useSuperstateWalletViewModel({
11402
11586
  }) {
11403
11587
  const { coinlist, isReady } = useCoinList();
11404
11588
  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);
11589
+ const [selected, setSelected] = (0, import_react33.useState)(null);
11590
+ const [phase, setPhase] = (0, import_react33.useState)(null);
11591
+ const [error, setError] = (0, import_react33.useState)(null);
11408
11592
  const networkName = getNetworkName(chain);
11409
11593
  const selectedWallet = resolveWallet2(wallets, selected);
11410
- (0, import_react32.useEffect)(() => {
11594
+ (0, import_react33.useEffect)(() => {
11411
11595
  if (stepInput.type === "completed") {
11412
11596
  setPhase(null);
11413
11597
  setError(null);
@@ -11626,12 +11810,20 @@ function useSuperstateSwapCheckoutViewModel({
11626
11810
  }) {
11627
11811
  const locale = useLocale();
11628
11812
  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" });
11813
+ const [step, setStep] = (0, import_react34.useState)({ type: "wallet" });
11814
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react34.useState)(null);
11632
11815
  const { inputAmount, inputTokenAddress } = quoteInput(step, chain);
11633
11816
  const live = enabled && contractAddress !== null;
11634
11817
  const contract = contractAddress ?? NO_CONTRACT;
11818
+ const { state: offerTokenMetadataState } = useCheckoutOfferTokenMetadata({
11819
+ offer,
11820
+ chain,
11821
+ enabled: live
11822
+ });
11823
+ const assetIconUrl = offerAssetIconUrl(
11824
+ offer,
11825
+ tokenMetadataOf(offerTokenMetadataState)
11826
+ );
11635
11827
  const { outputTokenState, refetch: refetchOutputToken } = useSwapOutputToken({
11636
11828
  contractAddress: contract,
11637
11829
  chain,
@@ -11688,9 +11880,7 @@ function useSuperstateSwapCheckoutViewModel({
11688
11880
  chain,
11689
11881
  assetIconUrl,
11690
11882
  onComplete: (order) => {
11691
- setOrderConfirmed(
11692
- toOrderConfirmedUi3({ order, chain, locale, assetIconUrl })
11693
- );
11883
+ setOrderConfirmed(order);
11694
11884
  setStep({ type: "wallet" });
11695
11885
  onOrderConfirmed?.(order);
11696
11886
  }
@@ -11716,7 +11906,15 @@ function useSuperstateSwapCheckoutViewModel({
11716
11906
  amount: amountState,
11717
11907
  review: reviewState,
11718
11908
  sidebar: sidebarState,
11719
- orderConfirmed
11909
+ // Derived here rather than in the review completion callback, so a
11910
+ // registry lookup that settles while the order is being placed still
11911
+ // reaches the dialog instead of the fallback icon that closure captured.
11912
+ orderConfirmed: orderConfirmed === null ? { type: "hidden" } : toOrderConfirmedUi3({
11913
+ order: orderConfirmed,
11914
+ chain,
11915
+ locale,
11916
+ assetIconUrl
11917
+ })
11720
11918
  };
11721
11919
  };
11722
11920
  const onEvent = (event) => {
@@ -11741,7 +11939,7 @@ function useSuperstateSwapCheckoutViewModel({
11741
11939
  onReviewEvent(event);
11742
11940
  return;
11743
11941
  case "ON_CLOSE_ORDER_CONFIRMED":
11744
- setOrderConfirmed({ type: "hidden" });
11942
+ setOrderConfirmed(null);
11745
11943
  return;
11746
11944
  case "ON_RETRY_LOAD":
11747
11945
  refetchOutputToken();
@@ -11856,7 +12054,7 @@ function CheckoutContainer({
11856
12054
  enabled = true,
11857
12055
  className
11858
12056
  }) {
11859
- const [side] = (0, import_react34.useState)(() => config["ondo::swap"].side());
12057
+ const [side] = (0, import_react35.useState)(() => config["ondo::swap"].side());
11860
12058
  const isOndo = offer.type === "ondo::swap";
11861
12059
  const ondoSymbol = config["ondo::swap"].symbol(offer);
11862
12060
  const ondoBuy = useOndoBuyCheckoutViewModel({
@@ -12429,23 +12627,23 @@ function EmptyState() {
12429
12627
  }
12430
12628
 
12431
12629
  // src/client/hooks/offers/grid/useOffersGridViewModel.ts
12432
- var import_react36 = require("react");
12630
+ var import_react37 = require("react");
12433
12631
 
12434
12632
  // src/client/hooks/offers/data/useOffers.ts
12435
- var import_react35 = require("react");
12436
- var LOADING_STATE2 = { type: "LOADING" };
12633
+ var import_react36 = require("react");
12634
+ var LOADING_STATE3 = { type: "LOADING" };
12437
12635
  function useOffers(options = {}) {
12438
12636
  const { coinlist, isReady } = useCoinList();
12439
12637
  const log = useLogger("useOffers");
12440
12638
  const { data: serverOffers } = options;
12441
- const [offersState, setOffersState] = (0, import_react35.useState)(
12442
- serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE2
12639
+ const [offersState, setOffersState] = (0, import_react36.useState)(
12640
+ serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE3
12443
12641
  );
12444
- (0, import_react35.useEffect)(() => {
12642
+ (0, import_react36.useEffect)(() => {
12445
12643
  let isCancelled = false;
12446
12644
  if (!isReady) {
12447
12645
  if (serverOffers === void 0) {
12448
- setOffersState(LOADING_STATE2);
12646
+ setOffersState(LOADING_STATE3);
12449
12647
  }
12450
12648
  return () => {
12451
12649
  isCancelled = true;
@@ -12456,7 +12654,7 @@ function useOffers(options = {}) {
12456
12654
  isCancelled = true;
12457
12655
  };
12458
12656
  }
12459
- setOffersState(LOADING_STATE2);
12657
+ setOffersState(LOADING_STATE3);
12460
12658
  coinlist.offers.list().then((offers) => {
12461
12659
  if (!isCancelled) {
12462
12660
  log.debug(() => ({
@@ -12507,11 +12705,11 @@ var GENERIC_ERROR_MESSAGE = "Unable to load offers right now. Please try again."
12507
12705
  function useOffersGridViewModel(options = {}) {
12508
12706
  const { data, onOfferClick } = options;
12509
12707
  const { offersState } = useOffers({ data });
12510
- const state = (0, import_react36.useMemo)(
12708
+ const state = (0, import_react37.useMemo)(
12511
12709
  () => toUiState(offersState, onOfferClick !== void 0),
12512
12710
  [offersState, onOfferClick]
12513
12711
  );
12514
- const onEvent = (0, import_react36.useCallback)(
12712
+ const onEvent = (0, import_react37.useCallback)(
12515
12713
  (event) => {
12516
12714
  switch (event.type) {
12517
12715
  case "ON_OFFER_CLICK": {
@@ -12571,14 +12769,14 @@ function OffersGridContainer({
12571
12769
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(OffersGridView, { state, onEvent, ...viewProps });
12572
12770
  }
12573
12771
 
12574
- // src/client/components/requirements/checklist/ConnectedWalletList.tsx
12575
- var import_react37 = require("react");
12772
+ // src/client/components/requirements/ConnectedWalletList.tsx
12773
+ var import_react38 = require("react");
12576
12774
  var import_jsx_runtime56 = require("react/jsx-runtime");
12577
12775
  function ConnectedWalletRow({
12578
12776
  wallet,
12579
12777
  onRemove
12580
12778
  }) {
12581
- const [state, setState] = (0, import_react37.useState)("idle");
12779
+ const [state, setState] = (0, import_react38.useState)("idle");
12582
12780
  const remove = async () => {
12583
12781
  if (!onRemove) return;
12584
12782
  setState("removing");
@@ -12687,12 +12885,228 @@ function ConnectedWalletListBody({
12687
12885
  );
12688
12886
  }
12689
12887
 
12690
- // src/client/components/requirements/checklist/RequirementItem.tsx
12888
+ // src/client/components/requirements/identity-verification/IdentityVerificationView.tsx
12889
+ var import_websdk_react = __toESM(require("@sumsub/websdk-react"), 1);
12890
+ var import_jsx_runtime57 = require("react/jsx-runtime");
12891
+ function IdentityVerificationView(props) {
12892
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(IdentityVerificationViewBody, { ...props }) });
12893
+ }
12894
+ function IdentityVerificationViewBody({
12895
+ state,
12896
+ onEvent,
12897
+ className
12898
+ }) {
12899
+ switch (state.type) {
12900
+ case "loading":
12901
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
12902
+ "output",
12903
+ {
12904
+ "aria-live": "polite",
12905
+ className: cn(
12906
+ "clcosdk:flex clcosdk:min-h-40 clcosdk:items-center clcosdk:justify-center",
12907
+ className
12908
+ ),
12909
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading identity verification..." })
12910
+ }
12911
+ );
12912
+ case "error":
12913
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
12914
+ "div",
12915
+ {
12916
+ className: cn(
12917
+ "clcosdk:flex clcosdk:flex-col clcosdk:gap-4",
12918
+ className
12919
+ ),
12920
+ children: [
12921
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AlertBanner, { variant: "error", icon: true, content: state.message }),
12922
+ state.retryable && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ClButton, { size: "sm", onClick: () => onEvent({ type: "ON_RETRY" }), children: "Try again" })
12923
+ ]
12924
+ }
12925
+ );
12926
+ case "ready":
12927
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: cn("clcosdk:w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
12928
+ import_websdk_react.default,
12929
+ {
12930
+ accessToken: state.accessToken,
12931
+ expirationHandler: state.refreshToken,
12932
+ config: state.locale === void 0 ? {} : { lang: state.locale },
12933
+ options: { addViewportTag: false, adaptIframeHeight: true },
12934
+ onMessage: (type, payload) => {
12935
+ onSumsubMessage(type, payload, onEvent);
12936
+ },
12937
+ onError: (error) => {
12938
+ onEvent({ type: "ON_ERROR", error: toError(error) });
12939
+ }
12940
+ }
12941
+ ) });
12942
+ default: {
12943
+ const exhaustive = state;
12944
+ return exhaustive;
12945
+ }
12946
+ }
12947
+ }
12948
+ function onSumsubMessage(type, payload, onEvent) {
12949
+ switch (type) {
12950
+ case "idCheck.onApplicantSubmitted":
12951
+ onEvent({ type: "ON_SUBMITTED" });
12952
+ return;
12953
+ case "idCheck.onError": {
12954
+ const message = payload?.message ?? "Verification error";
12955
+ onEvent({ type: "ON_ERROR", error: new Error(message) });
12956
+ return;
12957
+ }
12958
+ default:
12959
+ return;
12960
+ }
12961
+ }
12962
+ function toError(error) {
12963
+ return error instanceof Error ? error : new Error("Verification error");
12964
+ }
12965
+
12966
+ // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
12967
+ var import_react40 = require("react");
12968
+
12969
+ // src/client/hooks/requirements/data/useKycToken.ts
12970
+ var import_react39 = require("react");
12971
+ var IDLE_STATE = { type: "IDLE" };
12972
+ var LOADING_STATE4 = { type: "LOADING" };
12973
+ function useKycToken(levelName, reset) {
12974
+ const { coinlist } = useCoinList();
12975
+ const log = useLogger("useKycToken");
12976
+ const [kycTokenState, setKycTokenState] = (0, import_react39.useState)(IDLE_STATE);
12977
+ const resetPendingRef = (0, import_react39.useRef)(reset === true);
12978
+ const tokenIssuedRef = (0, import_react39.useRef)(false);
12979
+ (0, import_react39.useEffect)(() => {
12980
+ if (!tokenIssuedRef.current) {
12981
+ resetPendingRef.current = reset === true;
12982
+ }
12983
+ }, [reset]);
12984
+ const fetchToken = (0, import_react39.useCallback)(async () => {
12985
+ setKycTokenState(LOADING_STATE4);
12986
+ try {
12987
+ const kycToken = await coinlist.requirements.createKycToken({
12988
+ levelName,
12989
+ reset: resetPendingRef.current
12990
+ });
12991
+ resetPendingRef.current = false;
12992
+ tokenIssuedRef.current = true;
12993
+ log.debug(() => ({
12994
+ msg: "settled",
12995
+ fields: { state: "CONTENT" }
12996
+ }));
12997
+ setKycTokenState({ type: "CONTENT", token: kycToken.token });
12998
+ return kycToken.token;
12999
+ } catch (error) {
13000
+ const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
13001
+ log.failure(
13002
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
13003
+ error
13004
+ );
13005
+ setKycTokenState({ type: "ERROR", reason });
13006
+ throw error;
13007
+ }
13008
+ }, [coinlist, levelName, log]);
13009
+ return { kycTokenState, fetchToken };
13010
+ }
13011
+
13012
+ // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
13013
+ var NOT_AUTHENTICATED_MESSAGE2 = "Sign in to verify your identity.";
13014
+ var GENERIC_ERROR_MESSAGE2 = "Unable to start identity verification right now. Please try again.";
13015
+ function useIdentityVerificationViewModel(options = {}) {
13016
+ const { levelName, reset, locale, onSubmitted, onError } = options;
13017
+ const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
13018
+ const fetchedRef = (0, import_react40.useRef)(false);
13019
+ (0, import_react40.useEffect)(() => {
13020
+ if (fetchedRef.current) {
13021
+ return;
13022
+ }
13023
+ fetchedRef.current = true;
13024
+ fetchToken().catch(() => {
13025
+ });
13026
+ }, [fetchToken]);
13027
+ const state = (0, import_react40.useMemo)(() => {
13028
+ switch (kycTokenState.type) {
13029
+ case "IDLE":
13030
+ case "LOADING":
13031
+ return { type: "loading" };
13032
+ case "ERROR": {
13033
+ const notAuthenticated = kycTokenState.reason === "not-authenticated";
13034
+ return {
13035
+ type: "error",
13036
+ message: notAuthenticated ? NOT_AUTHENTICATED_MESSAGE2 : GENERIC_ERROR_MESSAGE2,
13037
+ retryable: !notAuthenticated
13038
+ };
13039
+ }
13040
+ case "CONTENT":
13041
+ return {
13042
+ type: "ready",
13043
+ accessToken: kycTokenState.token,
13044
+ locale,
13045
+ refreshToken: fetchToken
13046
+ };
13047
+ default: {
13048
+ const exhaustive = kycTokenState;
13049
+ return exhaustive;
13050
+ }
13051
+ }
13052
+ }, [kycTokenState, locale, fetchToken]);
13053
+ const onEvent = (0, import_react40.useCallback)(
13054
+ (event) => {
13055
+ switch (event.type) {
13056
+ case "ON_RETRY":
13057
+ fetchToken().catch(() => {
13058
+ });
13059
+ return;
13060
+ case "ON_SUBMITTED":
13061
+ onSubmitted?.();
13062
+ return;
13063
+ case "ON_ERROR":
13064
+ onError?.(event.error);
13065
+ return;
13066
+ default: {
13067
+ const exhaustive = event;
13068
+ return exhaustive;
13069
+ }
13070
+ }
13071
+ },
13072
+ [fetchToken, onSubmitted, onError]
13073
+ );
13074
+ return { state, onEvent };
13075
+ }
13076
+
13077
+ // src/client/components/requirements/identity-verification/IdentityVerificationContainer.tsx
13078
+ var import_jsx_runtime58 = require("react/jsx-runtime");
13079
+ function IdentityVerificationContainer({
13080
+ levelName,
13081
+ reset,
13082
+ locale,
13083
+ onSubmitted,
13084
+ onError,
13085
+ className
13086
+ }) {
13087
+ const { state, onEvent } = useIdentityVerificationViewModel({
13088
+ levelName,
13089
+ reset,
13090
+ locale,
13091
+ onSubmitted,
13092
+ onError
13093
+ });
13094
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13095
+ IdentityVerificationView,
13096
+ {
13097
+ state,
13098
+ onEvent,
13099
+ className
13100
+ }
13101
+ );
13102
+ }
13103
+
13104
+ // src/client/components/requirements/RequirementItem.tsx
12691
13105
  var import_lucide_react15 = require("lucide-react");
12692
13106
 
12693
13107
  // src/client/components/design-system/StepStatusIcon.tsx
12694
13108
  var import_lucide_react14 = require("lucide-react");
12695
- var import_jsx_runtime57 = require("react/jsx-runtime");
13109
+ var import_jsx_runtime59 = require("react/jsx-runtime");
12696
13110
  var statusConfig = {
12697
13111
  required: {
12698
13112
  Icon: import_lucide_react14.Info,
@@ -12717,7 +13131,7 @@ var statusConfig = {
12717
13131
  };
12718
13132
  function StepStatusIcon({ status, className }) {
12719
13133
  const { Icon, colorClass, fillClass } = statusConfig[status];
12720
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13134
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
12721
13135
  Icon,
12722
13136
  {
12723
13137
  className: cn(
@@ -12731,8 +13145,8 @@ function StepStatusIcon({ status, className }) {
12731
13145
  );
12732
13146
  }
12733
13147
 
12734
- // src/client/components/requirements/checklist/RequirementItem.tsx
12735
- var import_jsx_runtime58 = require("react/jsx-runtime");
13148
+ // src/client/components/requirements/RequirementItem.tsx
13149
+ var import_jsx_runtime60 = require("react/jsx-runtime");
12736
13150
  function VerificationActionZone({
12737
13151
  status,
12738
13152
  onAction,
@@ -12741,9 +13155,9 @@ function VerificationActionZone({
12741
13155
  switch (status) {
12742
13156
  case "required":
12743
13157
  if (onAction === null) return null;
12744
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Continue" });
13158
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Continue" });
12745
13159
  case "pending":
12746
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13160
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12747
13161
  AlertBanner,
12748
13162
  {
12749
13163
  variant: "warning",
@@ -12751,16 +13165,16 @@ function VerificationActionZone({
12751
13165
  }
12752
13166
  );
12753
13167
  case "completed":
12754
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(AlertBanner, { variant: "success", content: "Identity verified." });
13168
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(AlertBanner, { variant: "success", content: "Identity verified." });
12755
13169
  case "rejected":
12756
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13170
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12757
13171
  AlertBanner,
12758
13172
  {
12759
13173
  variant: "error",
12760
- content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
13174
+ content: onContactSupport === null ? "Verification rejected." : /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
12761
13175
  "Verification rejected.",
12762
13176
  " ",
12763
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13177
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12764
13178
  "button",
12765
13179
  {
12766
13180
  type: "button",
@@ -12784,8 +13198,8 @@ function WalletActionZone({
12784
13198
  onRemoveWallet
12785
13199
  }) {
12786
13200
  if (multiWallet) {
12787
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
12788
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13201
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
13202
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12789
13203
  ConnectedWalletList,
12790
13204
  {
12791
13205
  wallets: connectedWallets,
@@ -12794,7 +13208,7 @@ function WalletActionZone({
12794
13208
  status: walletsStatus
12795
13209
  }
12796
13210
  ),
12797
- status === "rejected" && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13211
+ status === "rejected" && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12798
13212
  AlertBanner,
12799
13213
  {
12800
13214
  variant: "error",
@@ -12805,21 +13219,21 @@ function WalletActionZone({
12805
13219
  }
12806
13220
  if (status === "completed") {
12807
13221
  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)(
13222
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
13223
+ onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", variant: "secondary", onClick: onAction, children: "Change wallet" }),
13224
+ walletsStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12811
13225
  AlertBanner,
12812
13226
  {
12813
13227
  variant: "info",
12814
13228
  content: "Loading your connected wallet\u2026"
12815
13229
  }
12816
- ) : walletsStatus === "error" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13230
+ ) : walletsStatus === "error" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12817
13231
  AlertBanner,
12818
13232
  {
12819
13233
  variant: "error",
12820
13234
  content: "Couldn't load your connected wallet."
12821
13235
  }
12822
- ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13236
+ ) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12823
13237
  AlertBanner,
12824
13238
  {
12825
13239
  variant: "success",
@@ -12829,9 +13243,9 @@ function WalletActionZone({
12829
13243
  ] });
12830
13244
  }
12831
13245
  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)(
13246
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
13247
+ onAction !== null && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" }),
13248
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12835
13249
  AlertBanner,
12836
13250
  {
12837
13251
  variant: "error",
@@ -12841,7 +13255,7 @@ function WalletActionZone({
12841
13255
  ] });
12842
13256
  }
12843
13257
  if (onAction === null) return null;
12844
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" });
13258
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ClButton, { size: "sm", onClick: onAction, children: "Connect wallet" });
12845
13259
  }
12846
13260
  function RequirementItem({
12847
13261
  ui,
@@ -12853,7 +13267,7 @@ function RequirementItem({
12853
13267
  walletsStatus,
12854
13268
  onContactSupport
12855
13269
  }) {
12856
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
13270
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
12857
13271
  "div",
12858
13272
  {
12859
13273
  className: cn(
@@ -12861,7 +13275,7 @@ function RequirementItem({
12861
13275
  className
12862
13276
  ),
12863
13277
  children: [
12864
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
13278
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
12865
13279
  "button",
12866
13280
  {
12867
13281
  type: "button",
@@ -12869,9 +13283,9 @@ function RequirementItem({
12869
13283
  "aria-expanded": expanded,
12870
13284
  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
13285
  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)(
13286
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "clcosdk:flex clcosdk:items-center clcosdk:gap-3", children: [
13287
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(StepStatusIcon, { status: ui.status }),
13288
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12875
13289
  "span",
12876
13290
  {
12877
13291
  className: cn(
@@ -12882,7 +13296,7 @@ function RequirementItem({
12882
13296
  }
12883
13297
  )
12884
13298
  ] }),
12885
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13299
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12886
13300
  import_lucide_react15.ChevronRight,
12887
13301
  {
12888
13302
  className: cn(
@@ -12895,15 +13309,15 @@ function RequirementItem({
12895
13309
  ]
12896
13310
  }
12897
13311
  ),
12898
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13312
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12899
13313
  "div",
12900
13314
  {
12901
13315
  className: cn(
12902
13316
  "clcosdk:grid clcosdk:transition-[grid-template-rows] clcosdk:duration-300 clcosdk:ease-in-out",
12903
13317
  expanded ? "clcosdk:grid-rows-[1fr]" : "clcosdk:grid-rows-[0fr]"
12904
13318
  ),
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)(
13319
+ 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: [
13320
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12907
13321
  "p",
12908
13322
  {
12909
13323
  className: cn(
@@ -12913,14 +13327,14 @@ function RequirementItem({
12913
13327
  children: ui.description
12914
13328
  }
12915
13329
  ),
12916
- ui.variant === "verification" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13330
+ ui.variant === "verification" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12917
13331
  VerificationActionZone,
12918
13332
  {
12919
13333
  status: ui.status,
12920
13334
  onAction,
12921
13335
  onContactSupport
12922
13336
  }
12923
- ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
13337
+ ) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
12924
13338
  WalletActionZone,
12925
13339
  {
12926
13340
  status: ui.status,
@@ -12939,10 +13353,10 @@ function RequirementItem({
12939
13353
  ) });
12940
13354
  }
12941
13355
 
12942
- // src/client/components/requirements/checklist/RequirementsChecklistView.tsx
12943
- var import_jsx_runtime59 = require("react/jsx-runtime");
13356
+ // src/client/components/requirements/RequirementsChecklistView.tsx
13357
+ var import_jsx_runtime61 = require("react/jsx-runtime");
12944
13358
  function RequirementsChecklistView(props) {
12945
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RequirementsChecklistViewBody, { ...props }) });
13359
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(RequirementsChecklistViewBody, { ...props }) });
12946
13360
  }
12947
13361
  function RequirementsChecklistViewBody({
12948
13362
  state,
@@ -12954,11 +13368,11 @@ function RequirementsChecklistViewBody({
12954
13368
  }) {
12955
13369
  switch (state.type) {
12956
13370
  case "loading":
12957
- return loading ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(LoadingState2, {});
13371
+ return loading ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(LoadingState2, {});
12958
13372
  case "not-authenticated":
12959
13373
  return unauthenticatedState ?? null;
12960
13374
  case "error":
12961
- return error ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13375
+ return error ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
12962
13376
  AlertBanner,
12963
13377
  {
12964
13378
  variant: "error",
@@ -12968,7 +13382,7 @@ function RequirementsChecklistViewBody({
12968
13382
  }
12969
13383
  );
12970
13384
  case "content":
12971
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
13385
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(
12972
13386
  "div",
12973
13387
  {
12974
13388
  className: cn(
@@ -12976,11 +13390,11 @@ function RequirementsChecklistViewBody({
12976
13390
  className
12977
13391
  ),
12978
13392
  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 })
13393
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13394
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: state.title }),
13395
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: state.description })
12982
13396
  ] }),
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)(
13397
+ /* @__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
13398
  RequirementItem,
12985
13399
  {
12986
13400
  ui: row.item,
@@ -12999,7 +13413,7 @@ function RequirementsChecklistViewBody({
12999
13413
  },
13000
13414
  row.id
13001
13415
  )) }),
13002
- state.ineligible && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13416
+ state.ineligible && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13003
13417
  AlertBanner,
13004
13418
  {
13005
13419
  variant: "error",
@@ -13007,7 +13421,7 @@ function RequirementsChecklistViewBody({
13007
13421
  content: "You are not eligible to participate."
13008
13422
  }
13009
13423
  ),
13010
- state.continueAction && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
13424
+ state.continueAction && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13011
13425
  ClButton,
13012
13426
  {
13013
13427
  fullWidth: true,
@@ -13023,270 +13437,21 @@ function RequirementsChecklistViewBody({
13023
13437
  const exhaustive = state;
13024
13438
  return exhaustive;
13025
13439
  }
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,
13440
+ }
13441
+ }
13442
+ function LoadingState2() {
13443
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
13444
+ "output",
13280
13445
  {
13281
- state,
13282
- onEvent,
13283
- className
13446
+ "aria-live": "polite",
13447
+ 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",
13448
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: cn(typeClasses.body, "clcosdk:text-text-secondary"), children: "Loading requirements..." })
13284
13449
  }
13285
13450
  );
13286
13451
  }
13287
13452
 
13288
13453
  // src/client/components/requirements/tax-document/TaxDocumentModalView.tsx
13289
- var import_jsx_runtime63 = require("react/jsx-runtime");
13454
+ var import_jsx_runtime62 = require("react/jsx-runtime");
13290
13455
  function TaxDocumentModalView({
13291
13456
  state,
13292
13457
  onEvent,
@@ -13295,7 +13460,7 @@ function TaxDocumentModalView({
13295
13460
  if (state.type === "hidden") {
13296
13461
  return null;
13297
13462
  }
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)(
13463
+ 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
13464
  "div",
13300
13465
  {
13301
13466
  className: cn(
@@ -13303,11 +13468,11 @@ function TaxDocumentModalView({
13303
13468
  className
13304
13469
  ),
13305
13470
  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" }) })
13471
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:items-start clcosdk:justify-between clcosdk:gap-4", children: [
13472
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h3", { className: cn(typeClasses.h3, "clcosdk:text-text-primary"), children: state.title }),
13473
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(CloseButton, { onClick: () => onEvent({ type: "ON_CLOSE" }) })
13309
13474
  ] }),
13310
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Screen, { screen: state.screen, onEvent })
13475
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(Screen, { screen: state.screen, onEvent })
13311
13476
  ]
13312
13477
  }
13313
13478
  ) }) });
@@ -13318,11 +13483,11 @@ function Screen({
13318
13483
  }) {
13319
13484
  switch (screen.type) {
13320
13485
  case "loading":
13321
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(LoadingScreen, {});
13486
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(LoadingScreen, {});
13322
13487
  case "error":
13323
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(AlertBanner, { variant: "error", icon: true, content: screen.message });
13488
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AlertBanner, { variant: "error", icon: true, content: screen.message });
13324
13489
  case "review":
13325
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13490
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13326
13491
  ReviewScreen,
13327
13492
  {
13328
13493
  fields: screen.fields,
@@ -13333,9 +13498,9 @@ function Screen({
13333
13498
  }
13334
13499
  );
13335
13500
  case "editing":
13336
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(EditScreen, { fields: screen.fields, onEvent });
13501
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(EditScreen, { fields: screen.fields, onEvent });
13337
13502
  case "sign-only":
13338
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13503
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13339
13504
  SignOnlyScreen,
13340
13505
  {
13341
13506
  signing: screen.signing,
@@ -13350,14 +13515,14 @@ function Screen({
13350
13515
  }
13351
13516
  }
13352
13517
  function LoadingScreen() {
13353
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13518
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13354
13519
  "output",
13355
13520
  {
13356
13521
  "aria-live": "polite",
13357
13522
  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" })
13523
+ 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: [
13524
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:h-3 clcosdk:w-28 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" }),
13525
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "clcosdk:h-5 clcosdk:w-48 clcosdk:animate-pulse clcosdk:rounded clcosdk:bg-surface" })
13361
13526
  ] }, row))
13362
13527
  }
13363
13528
  );
@@ -13369,9 +13534,9 @@ function ReviewScreen({
13369
13534
  signError,
13370
13535
  onEvent
13371
13536
  }) {
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)(
13537
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13538
+ /* @__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." }),
13539
+ piiUnavailable && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13375
13540
  AlertBanner,
13376
13541
  {
13377
13542
  variant: "info",
@@ -13379,27 +13544,27 @@ function ReviewScreen({
13379
13544
  content: "We don't have this information on file yet \u2014 please fill it in below."
13380
13545
  }
13381
13546
  ),
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)(
13547
+ /* @__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
13548
  "div",
13384
13549
  {
13385
13550
  className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
13386
13551
  children: [
13387
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13552
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13388
13553
  "span",
13389
13554
  {
13390
13555
  className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
13391
13556
  children: label
13392
13557
  }
13393
13558
  ),
13394
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: displayValue })
13559
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: cn(typeClasses.body, "clcosdk:text-text-primary"), children: displayValue })
13395
13560
  ]
13396
13561
  },
13397
13562
  field
13398
13563
  )) }),
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)(
13564
+ /* @__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." }),
13565
+ signError && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AlertBanner, { variant: "error", icon: true, content: signError }),
13566
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13567
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13403
13568
  ClButton,
13404
13569
  {
13405
13570
  fullWidth: true,
@@ -13409,7 +13574,7 @@ function ReviewScreen({
13409
13574
  children: "Sign W-8BEN"
13410
13575
  }
13411
13576
  ),
13412
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13577
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13413
13578
  ClButton,
13414
13579
  {
13415
13580
  fullWidth: true,
@@ -13426,20 +13591,20 @@ function EditScreen({
13426
13591
  fields,
13427
13592
  onEvent
13428
13593
  }) {
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)(
13594
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13595
+ /* @__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
13596
  "label",
13432
13597
  {
13433
13598
  className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-1",
13434
13599
  children: [
13435
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13600
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13436
13601
  "span",
13437
13602
  {
13438
13603
  className: cn(typeClasses.label, "clcosdk:text-text-secondary"),
13439
13604
  children: label
13440
13605
  }
13441
13606
  ),
13442
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13607
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13443
13608
  "input",
13444
13609
  {
13445
13610
  type: "text",
@@ -13460,9 +13625,9 @@ function EditScreen({
13460
13625
  },
13461
13626
  field
13462
13627
  )) }),
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)(
13628
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-2", children: [
13629
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(ClButton, { fullWidth: true, onClick: () => onEvent({ type: "ON_SAVE_EDIT" }), children: "Save & review" }),
13630
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13466
13631
  ClButton,
13467
13632
  {
13468
13633
  fullWidth: true,
@@ -13479,10 +13644,10 @@ function SignOnlyScreen({
13479
13644
  signError,
13480
13645
  onEvent
13481
13646
  }) {
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)(
13647
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-6", children: [
13648
+ /* @__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." }),
13649
+ signError && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(AlertBanner, { variant: "error", icon: true, content: signError }),
13650
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
13486
13651
  ClButton,
13487
13652
  {
13488
13653
  fullWidth: true,
@@ -13496,12 +13661,12 @@ function SignOnlyScreen({
13496
13661
  }
13497
13662
 
13498
13663
  // src/client/hooks/requirements/tax-document/useTaxDocumentModalViewModel.ts
13499
- var import_react41 = require("react");
13664
+ var import_react42 = require("react");
13500
13665
 
13501
13666
  // src/client/hooks/requirements/data/useTaxDocument.ts
13502
- var import_react40 = require("react");
13667
+ var import_react41 = require("react");
13503
13668
  var IDLE_SIGN = { type: "idle", error: null };
13504
- var LOADING_STATE4 = { type: "LOADING" };
13669
+ var LOADING_STATE5 = { type: "LOADING" };
13505
13670
  var SIGN_FAILED_MESSAGE = "Unable to sign document. Please try again.";
13506
13671
  var DOB_INVALID_MESSAGE = "Enter your date of birth as MM/DD/YYYY.";
13507
13672
  var FIELD_KEYS = {
@@ -13574,8 +13739,8 @@ function useTaxDocument({
13574
13739
  }) {
13575
13740
  const { coinlist, isReady } = useCoinList();
13576
13741
  const log = useLogger("useTaxDocument");
13577
- const [state, setState] = (0, import_react40.useState)(LOADING_STATE4);
13578
- (0, import_react40.useEffect)(() => {
13742
+ const [state, setState] = (0, import_react41.useState)(LOADING_STATE5);
13743
+ (0, import_react41.useEffect)(() => {
13579
13744
  let isCancelled = false;
13580
13745
  if (!isOpen) {
13581
13746
  return () => {
@@ -13583,12 +13748,12 @@ function useTaxDocument({
13583
13748
  };
13584
13749
  }
13585
13750
  if (!isReady) {
13586
- setState(LOADING_STATE4);
13751
+ setState(LOADING_STATE5);
13587
13752
  return () => {
13588
13753
  isCancelled = true;
13589
13754
  };
13590
13755
  }
13591
- setState(LOADING_STATE4);
13756
+ setState(LOADING_STATE5);
13592
13757
  coinlist.requirements.getPii().then((pii) => {
13593
13758
  if (isCancelled) return;
13594
13759
  if (pii.kind === "company") {
@@ -13616,7 +13781,7 @@ function useTaxDocument({
13616
13781
  isCancelled = true;
13617
13782
  };
13618
13783
  }, [coinlist, isReady, isOpen, log]);
13619
- const onEditField = (0, import_react40.useCallback)(
13784
+ const onEditField = (0, import_react41.useCallback)(
13620
13785
  (field, value) => {
13621
13786
  setState(
13622
13787
  (prev) => prev.type === "EDITING" ? { ...prev, fields: { ...prev.fields, [field]: value } } : prev
@@ -13624,7 +13789,7 @@ function useTaxDocument({
13624
13789
  },
13625
13790
  []
13626
13791
  );
13627
- const onStartEdit = (0, import_react40.useCallback)(() => {
13792
+ const onStartEdit = (0, import_react41.useCallback)(() => {
13628
13793
  setState(
13629
13794
  (prev) => prev.type === "REVIEW" ? {
13630
13795
  type: "EDITING",
@@ -13635,7 +13800,7 @@ function useTaxDocument({
13635
13800
  } : prev
13636
13801
  );
13637
13802
  }, []);
13638
- const onSaveEdit = (0, import_react40.useCallback)(() => {
13803
+ const onSaveEdit = (0, import_react41.useCallback)(() => {
13639
13804
  setState(
13640
13805
  (prev) => prev.type === "EDITING" ? {
13641
13806
  type: "REVIEW",
@@ -13646,7 +13811,7 @@ function useTaxDocument({
13646
13811
  } : prev
13647
13812
  );
13648
13813
  }, []);
13649
- const onCancelEdit = (0, import_react40.useCallback)(() => {
13814
+ const onCancelEdit = (0, import_react41.useCallback)(() => {
13650
13815
  setState(
13651
13816
  (prev) => prev.type === "EDITING" ? {
13652
13817
  type: "REVIEW",
@@ -13657,7 +13822,7 @@ function useTaxDocument({
13657
13822
  } : prev
13658
13823
  );
13659
13824
  }, []);
13660
- const onSign = (0, import_react40.useCallback)(() => {
13825
+ const onSign = (0, import_react41.useCallback)(() => {
13661
13826
  if (state.type !== "REVIEW" && state.type !== "SIGN_ONLY") return;
13662
13827
  if (state.type === "REVIEW" && state.fields.dob.trim() !== "" && !isValidUsDate(state.fields.dob)) {
13663
13828
  setState({
@@ -13699,19 +13864,19 @@ function useTaxDocumentModalViewModel({
13699
13864
  onSubmitted
13700
13865
  }) {
13701
13866
  const { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign } = useTaxDocument({ isOpen });
13702
- (0, import_react41.useEffect)(() => {
13867
+ (0, import_react42.useEffect)(() => {
13703
13868
  if (state.type === "SUBMITTED") {
13704
13869
  onSubmitted?.(state.submission);
13705
13870
  onClose();
13706
13871
  }
13707
13872
  }, [state]);
13708
- const uiState = (0, import_react41.useMemo)(() => {
13873
+ const uiState = (0, import_react42.useMemo)(() => {
13709
13874
  if (!isOpen || state.type === "SUBMITTED") {
13710
13875
  return { type: "hidden" };
13711
13876
  }
13712
13877
  return { type: "content", title: toTitle(state), screen: toScreen(state) };
13713
13878
  }, [isOpen, state]);
13714
- const onEvent = (0, import_react41.useCallback)(
13879
+ const onEvent = (0, import_react42.useCallback)(
13715
13880
  (event) => {
13716
13881
  switch (event.type) {
13717
13882
  case "ON_CLOSE":
@@ -13794,7 +13959,7 @@ function toFieldsUi(fields) {
13794
13959
  }
13795
13960
 
13796
13961
  // src/client/components/requirements/tax-document/TaxDocumentModalContainer.tsx
13797
- var import_jsx_runtime64 = require("react/jsx-runtime");
13962
+ var import_jsx_runtime63 = require("react/jsx-runtime");
13798
13963
  function TaxDocumentModalContainer({
13799
13964
  isOpen,
13800
13965
  onClose,
@@ -13806,7 +13971,7 @@ function TaxDocumentModalContainer({
13806
13971
  onClose,
13807
13972
  onSubmitted
13808
13973
  });
13809
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
13974
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
13810
13975
  TaxDocumentModalView,
13811
13976
  {
13812
13977
  state,
@@ -13816,15 +13981,48 @@ function TaxDocumentModalContainer({
13816
13981
  );
13817
13982
  }
13818
13983
 
13984
+ // src/client/components/requirements/VerificationOverlay.tsx
13985
+ var import_jsx_runtime64 = require("react/jsx-runtime");
13986
+ function VerificationOverlay({
13987
+ onClose,
13988
+ children
13989
+ }) {
13990
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(VerificationOverlayBody, { onClose, children }) });
13991
+ }
13992
+ function VerificationOverlayBody({
13993
+ onClose,
13994
+ children
13995
+ }) {
13996
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
13997
+ "div",
13998
+ {
13999
+ role: "dialog",
14000
+ "aria-modal": "true",
14001
+ "aria-label": "Identity verification",
14002
+ className: "clcosdk:fixed clcosdk:inset-0 clcosdk:z-50 clcosdk:flex clcosdk:items-center clcosdk:justify-center clcosdk:bg-overlay clcosdk:p-4",
14003
+ 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: [
14004
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
14005
+ CloseButton,
14006
+ {
14007
+ onClick: onClose,
14008
+ className: "clcosdk:absolute clcosdk:top-4 clcosdk:right-4"
14009
+ }
14010
+ ),
14011
+ children
14012
+ ] })
14013
+ }
14014
+ );
14015
+ }
14016
+
13819
14017
  // src/client/components/requirements/wallet/ConnectWalletModalView.tsx
13820
- var import_react42 = require("react");
14018
+ var import_react43 = require("react");
13821
14019
  var import_jsx_runtime65 = require("react/jsx-runtime");
13822
14020
  function ConnectWalletModalView({
13823
14021
  state,
13824
14022
  onEvent,
13825
14023
  className
13826
14024
  }) {
13827
- const titleId = (0, import_react42.useId)();
14025
+ const titleId = (0, import_react43.useId)();
13828
14026
  if (state.type === "hidden") {
13829
14027
  return null;
13830
14028
  }
@@ -13927,10 +14125,10 @@ function Screen2({
13927
14125
  }
13928
14126
 
13929
14127
  // src/client/hooks/requirements/wallet/useConnectWalletModalViewModel.ts
13930
- var import_react44 = require("react");
14128
+ var import_react45 = require("react");
13931
14129
 
13932
14130
  // src/client/hooks/requirements/data/useConnectWallet.ts
13933
- var import_react43 = require("react");
14131
+ var import_react44 = require("react");
13934
14132
 
13935
14133
  // src/client/core/wallets/connect-external-wallet.ts
13936
14134
  var DEFAULT_STATEMENT = "Sign this message to prove you own this wallet. This does not cost gas or move funds.";
@@ -14061,24 +14259,24 @@ function useConnectWallet({
14061
14259
  statement
14062
14260
  }) {
14063
14261
  const { coinlist } = useCoinList();
14064
- const [state, setState] = (0, import_react43.useState)(
14262
+ const [state, setState] = (0, import_react44.useState)(
14065
14263
  () => wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
14066
14264
  );
14067
- const attempt = (0, import_react43.useRef)(0);
14068
- (0, import_react43.useEffect)(() => {
14265
+ const attempt = (0, import_react44.useRef)(0);
14266
+ (0, import_react44.useEffect)(() => {
14069
14267
  attempt.current += 1;
14070
14268
  if (!isOpen) return;
14071
14269
  setState(
14072
14270
  wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
14073
14271
  );
14074
14272
  }, [isOpen, wallet?.address]);
14075
- (0, import_react43.useEffect)(
14273
+ (0, import_react44.useEffect)(
14076
14274
  () => () => {
14077
14275
  attempt.current += 1;
14078
14276
  },
14079
14277
  []
14080
14278
  );
14081
- const onSign = (0, import_react43.useCallback)(() => {
14279
+ const onSign = (0, import_react44.useCallback)(() => {
14082
14280
  if (!wallet || state.type !== "READY") return;
14083
14281
  attempt.current += 1;
14084
14282
  const gen = attempt.current;
@@ -14140,13 +14338,13 @@ function useConnectWalletModalViewModel({
14140
14338
  challengeType,
14141
14339
  statement
14142
14340
  });
14143
- (0, import_react44.useEffect)(() => {
14341
+ (0, import_react45.useEffect)(() => {
14144
14342
  if (state.type === "CONNECTED") {
14145
14343
  onConnected?.(state.binding);
14146
14344
  onClose();
14147
14345
  }
14148
14346
  }, [state]);
14149
- const uiState = (0, import_react44.useMemo)(() => {
14347
+ const uiState = (0, import_react45.useMemo)(() => {
14150
14348
  if (!isOpen || state.type === "CONNECTED") {
14151
14349
  return { type: "hidden" };
14152
14350
  }
@@ -14171,7 +14369,7 @@ function useConnectWalletModalViewModel({
14171
14369
  canRequestConnect
14172
14370
  };
14173
14371
  }, [isOpen, state, onRequestConnect]);
14174
- const onEvent = (0, import_react44.useCallback)(
14372
+ const onEvent = (0, import_react45.useCallback)(
14175
14373
  (event) => {
14176
14374
  switch (event.type) {
14177
14375
  case "ON_CLOSE":
@@ -14211,63 +14409,12 @@ function ConnectWalletModalContainer({
14211
14409
  );
14212
14410
  }
14213
14411
 
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
- };
14412
+ // src/client/hooks/requirements/useRequirementsChecklistViewModel.ts
14413
+ var import_react48 = require("react");
14267
14414
 
14268
14415
  // src/client/hooks/requirements/data/useOptionAddresses.ts
14269
- var import_react45 = require("react");
14270
- var LOADING_STATE5 = { type: "LOADING" };
14416
+ var import_react46 = require("react");
14417
+ var LOADING_STATE6 = { type: "LOADING" };
14271
14418
  var EMPTY_STATE = {
14272
14419
  type: "CONTENT",
14273
14420
  addresses: []
@@ -14276,19 +14423,19 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14276
14423
  const { coinlist, isReady } = useCoinList();
14277
14424
  const log = useLogger("useOptionAddresses");
14278
14425
  const { data, enabled = true } = options;
14279
- const [addressesState, setAddressesState] = (0, import_react45.useState)(
14280
- data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE5
14426
+ const [addressesState, setAddressesState] = (0, import_react46.useState)(
14427
+ data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE6
14281
14428
  );
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)(
14429
+ const [fetchKey, setFetchKey] = (0, import_react46.useState)(0);
14430
+ const refetch = (0, import_react46.useCallback)(() => setFetchKey((k) => k + 1), []);
14431
+ const disconnect = (0, import_react46.useCallback)(
14285
14432
  async (addressId) => {
14286
14433
  await coinlist.wallets.remove({ offerId, addressId });
14287
14434
  refetch();
14288
14435
  },
14289
14436
  [coinlist, offerId, refetch]
14290
14437
  );
14291
- (0, import_react45.useEffect)(() => {
14438
+ (0, import_react46.useEffect)(() => {
14292
14439
  let isCancelled = false;
14293
14440
  if (!enabled) {
14294
14441
  setAddressesState(
@@ -14300,7 +14447,7 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14300
14447
  }
14301
14448
  if (!isReady) {
14302
14449
  if (data === void 0) {
14303
- setAddressesState(LOADING_STATE5);
14450
+ setAddressesState(LOADING_STATE6);
14304
14451
  }
14305
14452
  return () => {
14306
14453
  isCancelled = true;
@@ -14317,7 +14464,7 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14317
14464
  isCancelled = true;
14318
14465
  };
14319
14466
  }
14320
- setAddressesState(LOADING_STATE5);
14467
+ setAddressesState(LOADING_STATE6);
14321
14468
  coinlist.wallets.list({ offerId, offerOptionId }).then((addresses) => {
14322
14469
  if (!isCancelled) {
14323
14470
  log.debug(() => ({
@@ -14344,22 +14491,22 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14344
14491
  }
14345
14492
 
14346
14493
  // src/client/hooks/requirements/data/useRequirements.ts
14347
- var import_react46 = require("react");
14348
- var LOADING_STATE6 = { type: "LOADING" };
14494
+ var import_react47 = require("react");
14495
+ var LOADING_STATE7 = { type: "LOADING" };
14349
14496
  function useRequirements(offerId, options = {}) {
14350
14497
  const { coinlist, isReady } = useCoinList();
14351
14498
  const log = useLogger("useRequirements");
14352
14499
  const { data } = options;
14353
- const [requirementsState, setRequirementsState] = (0, import_react46.useState)(
14354
- data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE6
14500
+ const [requirementsState, setRequirementsState] = (0, import_react47.useState)(
14501
+ data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE7
14355
14502
  );
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)(() => {
14503
+ const [fetchKey, setFetchKey] = (0, import_react47.useState)(0);
14504
+ const refetch = (0, import_react47.useCallback)(() => setFetchKey((k) => k + 1), []);
14505
+ (0, import_react47.useEffect)(() => {
14359
14506
  let isCancelled = false;
14360
14507
  if (!isReady) {
14361
14508
  if (data === void 0) {
14362
- setRequirementsState(LOADING_STATE6);
14509
+ setRequirementsState(LOADING_STATE7);
14363
14510
  }
14364
14511
  return () => {
14365
14512
  isCancelled = true;
@@ -14376,7 +14523,7 @@ function useRequirements(offerId, options = {}) {
14376
14523
  isCancelled = true;
14377
14524
  };
14378
14525
  }
14379
- setRequirementsState(LOADING_STATE6);
14526
+ setRequirementsState(LOADING_STATE7);
14380
14527
  Promise.all([
14381
14528
  coinlist.requirements.forOffer(offerId),
14382
14529
  coinlist.requirements.statuses(offerId)
@@ -14413,7 +14560,58 @@ function useRequirements(offerId, options = {}) {
14413
14560
  return { requirementsState, refetch };
14414
14561
  }
14415
14562
 
14416
- // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
14563
+ // src/client/hooks/requirements/useRequirementsChecklistViewModel.types.ts
14564
+ var RequirementItemUi = {
14565
+ fromDomain(req, statusInfo, label, description2, addresses = []) {
14566
+ return {
14567
+ variant: RequirementVariant.fromType(req.type),
14568
+ status: statusInfo ? RequirementStatus.fromStatusValue(statusInfo.status) : "required",
14569
+ label,
14570
+ description: description2,
14571
+ multiWallet: req.type === "whitelisted_wallet",
14572
+ connectedWallets: addresses.map((address) => ({
14573
+ id: address.id,
14574
+ address: address.address,
14575
+ shortAddress: shortenAddress(address.address)
14576
+ }))
14577
+ };
14578
+ }
14579
+ };
14580
+ var RequirementVariant = {
14581
+ fromType(type) {
14582
+ switch (type) {
14583
+ case "external_wallet":
14584
+ case "whitelisted_wallet":
14585
+ return "wallet";
14586
+ default:
14587
+ return "verification";
14588
+ }
14589
+ }
14590
+ };
14591
+ var RequirementStatus = {
14592
+ fromStatusValue(status) {
14593
+ switch (status) {
14594
+ case "not_started":
14595
+ case "action_needed":
14596
+ return "required";
14597
+ case "in_progress":
14598
+ return "pending";
14599
+ case "completed":
14600
+ return "completed";
14601
+ case "rejected":
14602
+ return "rejected";
14603
+ }
14604
+ }
14605
+ };
14606
+ var ChecklistStatus = {
14607
+ derive(statuses) {
14608
+ if (statuses.some((s) => s.status === "rejected")) return "ineligible";
14609
+ if (statuses.every((s) => s.status === "completed")) return "eligible";
14610
+ return "inProgress";
14611
+ }
14612
+ };
14613
+
14614
+ // src/client/hooks/requirements/useRequirementsChecklistViewModel.ts
14417
14615
  var DEFAULT_LABELS = {
14418
14616
  kyc_approved: "KYC Verification",
14419
14617
  external_wallet: "External Wallet",
@@ -14455,19 +14653,19 @@ function useRequirementsChecklistViewModel(options) {
14455
14653
  const log = useLogger("useRequirementsChecklistViewModel");
14456
14654
  const { coinlist } = useCoinList();
14457
14655
  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)(() => {
14656
+ const [expandedId, setExpandedId] = (0, import_react48.useState)(null);
14657
+ const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react48.useState)(false);
14658
+ const [connectWalletOpen, setConnectWalletOpen] = (0, import_react48.useState)(false);
14659
+ const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react48.useState)(null);
14660
+ const isMountedRef = (0, import_react48.useRef)(true);
14661
+ (0, import_react48.useEffect)(() => {
14464
14662
  isMountedRef.current = true;
14465
14663
  return () => {
14466
14664
  isMountedRef.current = false;
14467
14665
  };
14468
14666
  }, []);
14469
- const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react47.useState)(false);
14470
- (0, import_react47.useEffect)(() => {
14667
+ const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react48.useState)(false);
14668
+ (0, import_react48.useEffect)(() => {
14471
14669
  if (requirementsState.type === "CONTENT") {
14472
14670
  setHasWalletRequirement(
14473
14671
  (requirementsState.requirements[optionId] ?? []).some(
@@ -14483,14 +14681,14 @@ function useRequirementsChecklistViewModel(options) {
14483
14681
  } = useOptionAddresses(offerId, optionId, {
14484
14682
  enabled: hasWalletRequirement
14485
14683
  });
14486
- const removeWallet = (0, import_react47.useCallback)(
14684
+ const removeWallet = (0, import_react48.useCallback)(
14487
14685
  async (addressId) => {
14488
14686
  await disconnect(OfferOptionAddressId(addressId));
14489
14687
  refetch();
14490
14688
  },
14491
14689
  [disconnect, refetch]
14492
14690
  );
14493
- const awaitVerificationResult = (0, import_react47.useCallback)(
14691
+ const awaitVerificationResult = (0, import_react48.useCallback)(
14494
14692
  (requirementId, statusBeforeSubmit) => {
14495
14693
  void (async () => {
14496
14694
  const deadline = Date.now() + VERIFICATION_POLL_TIMEOUT_MS;
@@ -14517,11 +14715,11 @@ function useRequirementsChecklistViewModel(options) {
14517
14715
  },
14518
14716
  [coinlist, offerId, refetch, log]
14519
14717
  );
14520
- const requirements = (0, import_react47.useMemo)(
14718
+ const requirements = (0, import_react48.useMemo)(
14521
14719
  () => requirementsState.type === "CONTENT" ? requirementsState.requirements[optionId] ?? [] : [],
14522
14720
  [requirementsState, optionId]
14523
14721
  );
14524
- const statusById = (0, import_react47.useMemo)(() => {
14722
+ const statusById = (0, import_react48.useMemo)(() => {
14525
14723
  if (requirementsState.type !== "CONTENT") {
14526
14724
  return /* @__PURE__ */ new Map();
14527
14725
  }
@@ -14530,7 +14728,7 @@ function useRequirementsChecklistViewModel(options) {
14530
14728
  requirementsState.statuses.filter((s) => ids.has(s.id)).map((s) => [s.id, s])
14531
14729
  );
14532
14730
  }, [requirementsState, requirements]);
14533
- const state = (0, import_react47.useMemo)(() => {
14731
+ const state = (0, import_react48.useMemo)(() => {
14534
14732
  switch (requirementsState.type) {
14535
14733
  case "LOADING":
14536
14734
  return { type: "loading" };
@@ -14599,7 +14797,7 @@ function useRequirementsChecklistViewModel(options) {
14599
14797
  identityVerificationOptions,
14600
14798
  removeWallet
14601
14799
  ]);
14602
- const handleRequirementAction = (0, import_react47.useCallback)(
14800
+ const handleRequirementAction = (0, import_react48.useCallback)(
14603
14801
  (requirement) => {
14604
14802
  const inlineVerification = statusById.get(requirement.id)?.kycLevel !== void 0 && onRequirementActionOverride === void 0;
14605
14803
  if (inlineVerification) {
@@ -14631,7 +14829,7 @@ function useRequirementsChecklistViewModel(options) {
14631
14829
  coinlist
14632
14830
  ]
14633
14831
  );
14634
- const onEvent = (0, import_react47.useCallback)(
14832
+ const onEvent = (0, import_react48.useCallback)(
14635
14833
  (event) => {
14636
14834
  switch (event.type) {
14637
14835
  case "ON_TOGGLE_ITEM":
@@ -14728,7 +14926,7 @@ function toVerificationUi(verifyingRequirementId, statusById, identityVerificati
14728
14926
  };
14729
14927
  }
14730
14928
 
14731
- // src/client/components/requirements/checklist/RequirementsChecklistContainer.tsx
14929
+ // src/client/components/requirements/RequirementsChecklistContainer.tsx
14732
14930
  var import_jsx_runtime67 = require("react/jsx-runtime");
14733
14931
  function RequirementsChecklistContainer({
14734
14932
  loading,
@@ -14794,10 +14992,10 @@ function RequirementsChecklistContainer({
14794
14992
  ] });
14795
14993
  }
14796
14994
 
14797
- // src/client/core/observability/pino-client-logger.ts
14995
+ // src/client/core/shared/observability/pino-client-logger.ts
14798
14996
  var import_pino = require("pino");
14799
14997
 
14800
- // src/shared/core/observability/pino-logger.ts
14998
+ // src/universal/core/shared/observability/pino-logger.ts
14801
14999
  function toPinoRecord(event) {
14802
15000
  try {
14803
15001
  const record = {};
@@ -14923,7 +15121,7 @@ function reportRenderFailure(sink, error) {
14923
15121
  }
14924
15122
  }
14925
15123
 
14926
- // src/client/core/observability/pino-client-logger.ts
15124
+ // src/client/core/shared/observability/pino-client-logger.ts
14927
15125
  function pinoClientLogger(options) {
14928
15126
  return loggerOverPino(
14929
15127
  // `name` as a child binding rather than pino's `name` option: the option
@@ -14939,18 +15137,18 @@ function pinoClientLogger(options) {
14939
15137
  }
14940
15138
 
14941
15139
  // src/client/hooks/auth/useCompleteOAuth.ts
14942
- var import_react48 = require("react");
15140
+ var import_react49 = require("react");
14943
15141
  function useCompleteOAuth(options) {
14944
15142
  const { coinlist } = useCoinList();
14945
15143
  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);
15144
+ const postOAuthCompleteRef = (0, import_react49.useRef)(options.postOAuthComplete);
15145
+ const onFailureRef = (0, import_react49.useRef)(options.onFailure);
15146
+ const onSuccessRef = (0, import_react49.useRef)(options.onSuccess);
14949
15147
  postOAuthCompleteRef.current = options.postOAuthComplete;
14950
15148
  onFailureRef.current = options.onFailure;
14951
15149
  onSuccessRef.current = options.onSuccess;
14952
- const hasStartedExchangeRef = (0, import_react48.useRef)(false);
14953
- (0, import_react48.useEffect)(() => {
15150
+ const hasStartedExchangeRef = (0, import_react49.useRef)(false);
15151
+ (0, import_react49.useEffect)(() => {
14954
15152
  if (typeof window === "undefined") return;
14955
15153
  const params = new URLSearchParams(window.location.search);
14956
15154
  if (!params.has("code") && !params.has("error")) return;
@@ -15014,20 +15212,20 @@ function useCompleteOAuth(options) {
15014
15212
  }
15015
15213
 
15016
15214
  // src/client/hooks/checkout/coin-list/token-sale/data/useParticipations.ts
15017
- var import_react49 = require("react");
15018
- var LOADING_STATE7 = { type: "LOADING" };
15215
+ var import_react50 = require("react");
15216
+ var LOADING_STATE8 = { type: "LOADING" };
15019
15217
  function useParticipations(offerId, options = {}) {
15020
15218
  const { coinlist, isReady } = useCoinList();
15021
15219
  const log = useLogger("useParticipations");
15022
15220
  const { data } = options;
15023
- const [participationsState, setParticipationsState] = (0, import_react49.useState)(
15024
- data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE7
15221
+ const [participationsState, setParticipationsState] = (0, import_react50.useState)(
15222
+ data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE8
15025
15223
  );
15026
- (0, import_react49.useEffect)(() => {
15224
+ (0, import_react50.useEffect)(() => {
15027
15225
  let isCancelled = false;
15028
15226
  if (!isReady) {
15029
15227
  if (data === void 0) {
15030
- setParticipationsState(LOADING_STATE7);
15228
+ setParticipationsState(LOADING_STATE8);
15031
15229
  }
15032
15230
  return () => {
15033
15231
  isCancelled = true;
@@ -15038,7 +15236,7 @@ function useParticipations(offerId, options = {}) {
15038
15236
  isCancelled = true;
15039
15237
  };
15040
15238
  }
15041
- setParticipationsState(LOADING_STATE7);
15239
+ setParticipationsState(LOADING_STATE8);
15042
15240
  coinlist.tokenSale.list(offerId).then((participations) => {
15043
15241
  if (!isCancelled) {
15044
15242
  log.debug(() => ({
@@ -15065,20 +15263,20 @@ function useParticipations(offerId, options = {}) {
15065
15263
  }
15066
15264
 
15067
15265
  // src/client/hooks/offers/data/useOfferDetails.ts
15068
- var import_react50 = require("react");
15069
- var LOADING_STATE8 = { type: "LOADING" };
15266
+ var import_react51 = require("react");
15267
+ var LOADING_STATE9 = { type: "LOADING" };
15070
15268
  function useOfferDetails(offerId, options = {}) {
15071
15269
  const { coinlist, isReady } = useCoinList();
15072
15270
  const log = useLogger("useOfferDetails");
15073
15271
  const { data } = options;
15074
- const [offerDetailsState, setOfferDetailsState] = (0, import_react50.useState)(
15075
- data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE8
15272
+ const [offerDetailsState, setOfferDetailsState] = (0, import_react51.useState)(
15273
+ data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE9
15076
15274
  );
15077
- (0, import_react50.useEffect)(() => {
15275
+ (0, import_react51.useEffect)(() => {
15078
15276
  let isCancelled = false;
15079
15277
  if (!isReady) {
15080
15278
  if (data === void 0) {
15081
- setOfferDetailsState(LOADING_STATE8);
15279
+ setOfferDetailsState(LOADING_STATE9);
15082
15280
  }
15083
15281
  return () => {
15084
15282
  isCancelled = true;
@@ -15089,7 +15287,7 @@ function useOfferDetails(offerId, options = {}) {
15089
15287
  isCancelled = true;
15090
15288
  };
15091
15289
  }
15092
- setOfferDetailsState(LOADING_STATE8);
15290
+ setOfferDetailsState(LOADING_STATE9);
15093
15291
  coinlist.offers.get(offerId).then((offerDetail) => {
15094
15292
  if (!isCancelled) {
15095
15293
  log.debug(() => ({
@@ -15129,66 +15327,6 @@ var OfferAssetCardUi = {
15129
15327
  })
15130
15328
  };
15131
15329
 
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
15330
  // src/client/ui/format/date.ts
15193
15331
  function formatMonthYear(date, locale) {
15194
15332
  return new Intl.DateTimeFormat(locale, {
@@ -15278,7 +15416,9 @@ function formatMonthYear(date, locale) {
15278
15416
  formatCountdown,
15279
15417
  formatMonthYear,
15280
15418
  formatSaleCardCountdown,
15419
+ offerAssetIconUrl,
15281
15420
  offerIconUrl,
15421
+ offerTokenIdentifier,
15282
15422
  ondoLoadErrorReason,
15283
15423
  pinoClientLogger,
15284
15424
  prepareOndoBuy,
@@ -15287,6 +15427,9 @@ function formatMonthYear(date, locale) {
15287
15427
  quoteOverAsks,
15288
15428
  stablecoinIconUrl,
15289
15429
  submitErc20Approval,
15430
+ tokenLogoUrl,
15431
+ tokenMetadataOf,
15432
+ useCheckoutOfferTokenMetadata,
15290
15433
  useCoinList,
15291
15434
  useCoinListSignInCardViewModel,
15292
15435
  useCompleteOAuth,