@coinlist-co/react 0.11.0 → 0.11.1-rc.8cfcd2a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{chunk-B2HCVPCQ.js → chunk-5KYO7OOX.js} +26 -11
  2. package/dist/chunk-5KYO7OOX.js.map +1 -0
  3. package/dist/chunk-AQIHCFW4.js +279 -0
  4. package/dist/chunk-AQIHCFW4.js.map +1 -0
  5. package/dist/{chunk-UIIXXLA7.js → chunk-ZVB6KWZ2.js} +484 -141
  6. package/dist/chunk-ZVB6KWZ2.js.map +1 -0
  7. package/dist/client/index.cjs +1308 -462
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +216 -211
  10. package/dist/client/index.d.ts +216 -211
  11. package/dist/client/index.js +464 -108
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/collections-DrJFEDHl.d.cts +116 -0
  14. package/dist/collections-pLtrj6fw.d.ts +116 -0
  15. package/dist/{config-B5mwS_2l.d.cts → config-C6vlghJY.d.cts} +713 -22
  16. package/dist/{config-B5mwS_2l.d.ts → config-C6vlghJY.d.ts} +713 -22
  17. package/dist/server/index.cjs +766 -209
  18. package/dist/server/index.cjs.map +1 -1
  19. package/dist/server/index.d.cts +80 -3
  20. package/dist/server/index.d.ts +80 -3
  21. package/dist/server/index.js +120 -51
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/shared/index.cjs +487 -124
  24. package/dist/shared/index.cjs.map +1 -1
  25. package/dist/shared/index.d.cts +18 -5
  26. package/dist/shared/index.d.ts +18 -5
  27. package/dist/shared/index.js +8 -2
  28. package/package.json +3 -2
  29. package/dist/chunk-B2HCVPCQ.js.map +0 -1
  30. package/dist/chunk-KDGNDAHA.js +0 -146
  31. package/dist/chunk-KDGNDAHA.js.map +0 -1
  32. package/dist/chunk-UIIXXLA7.js.map +0 -1
  33. package/dist/collections-BhDkYmzV.d.cts +0 -65
  34. package/dist/collections-CZhHoQHr.d.ts +0 -65
@@ -68,6 +68,7 @@ __export(client_exports, {
68
68
  OndoReviewView: () => OndoReviewView,
69
69
  OndoSidebarView: () => OndoSidebarView,
70
70
  OndoWalletSelectView: () => OndoWalletSelectView,
71
+ RedactedWalletError: () => RedactedWalletError,
71
72
  RequirementItem: () => RequirementItem,
72
73
  RequirementItemUi: () => RequirementItemUi,
73
74
  RequirementStatus: () => RequirementStatus,
@@ -100,6 +101,7 @@ __export(client_exports, {
100
101
  formatMonthYear: () => formatMonthYear,
101
102
  offerIconUrl: () => offerIconUrl,
102
103
  ondoLoadErrorReason: () => ondoLoadErrorReason,
104
+ pinoClientLogger: () => pinoClientLogger,
103
105
  prepareOndoSwap: () => prepareOndoSwap,
104
106
  quoteIsStale: () => quoteIsStale,
105
107
  quoteOverAsks: () => quoteOverAsks,
@@ -145,7 +147,7 @@ __export(client_exports, {
145
147
  module.exports = __toCommonJS(client_exports);
146
148
 
147
149
  // src/client/CoinListProvider.tsx
148
- var import_react2 = require("react");
150
+ var import_react3 = require("react");
149
151
 
150
152
  // src/shared/core/utils/crypto.ts
151
153
  async function sha256(data) {
@@ -218,9 +220,6 @@ var COINLIST_BASE_URL = "https://coinlist.co";
218
220
  var OAUTH_PAGE_PATH = "/oauth/authorize";
219
221
  var SUPPORT_NEW_TICKET_URL = "https://support.coinlist.co/support/tickets/new";
220
222
  var VERIFY_IDENTITY_PATH = "/verify-identity";
221
- var VERIFY_IDENTITY_VERIFIED_PATH = "/verify-identity/identity_verified";
222
- var VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH = "/verify-identity/proof_of_address";
223
- var VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH = "/verify-identity/source_of_funds";
224
223
  var VERIFY_IDENTITY_ACCREDITATION_PATH = "/verify-identity/accreditation_full";
225
224
  var WALLET_PATH = "/wallet";
226
225
 
@@ -251,6 +250,8 @@ var retryAttempt = (attempt) => ({
251
250
  var renewAttempted = (value) => ({
252
251
  renewAttempted: value
253
252
  });
253
+ var requestId = (id) => ({ requestId: id });
254
+ var getRequestId = (attrs) => attrs?.requestId ?? null;
254
255
  var isProtected = (attrs) => attrs?.protected === true;
255
256
  var needUserAgent = (attrs) => attrs?.userAgent === true;
256
257
  var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
@@ -272,7 +273,9 @@ var Attributes = {
272
273
  renewAttempted,
273
274
  wasRenewAttempted,
274
275
  clientCredentials,
275
- getClientCredentials
276
+ getClientCredentials,
277
+ requestId,
278
+ getRequestId
276
279
  };
277
280
 
278
281
  // src/client/core/api/middleware/user-agent.ts
@@ -306,6 +309,16 @@ var HttpError = class extends Error {
306
309
  this.name = "HttpError";
307
310
  this.response = response;
308
311
  }
312
+ /**
313
+ * Correlates this failure with the `[HTTP]` log lines for the same request,
314
+ * which carry the method, the URL, the duration and every retry. `null` when
315
+ * the response did not come from an {@link HttpClient}.
316
+ *
317
+ * Worth quoting in a bug report: it is what makes a log excerpt readable.
318
+ */
319
+ get requestId() {
320
+ return this.response.requestId ?? null;
321
+ }
309
322
  };
310
323
  function apiErrorCode(error) {
311
324
  if (!(error instanceof HttpError)) return null;
@@ -413,11 +426,185 @@ var Request = {
413
426
  concatAttributes
414
427
  };
415
428
 
429
+ // src/shared/types/errors.ts
430
+ var NotImplementedError = class extends Error {
431
+ constructor(message = "Not implemented yet") {
432
+ super(message);
433
+ this.name = "NotImplementedError";
434
+ }
435
+ };
436
+ var NotAuthenticatedError = class extends Error {
437
+ constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
438
+ super(message);
439
+ this.name = "NotAuthenticatedError";
440
+ }
441
+ };
442
+ var ValidationError = class extends Error {
443
+ constructor(message) {
444
+ super(message);
445
+ this.name = "ValidationError";
446
+ }
447
+ };
448
+ var InvariantError = class extends Error {
449
+ constructor(message) {
450
+ super(message);
451
+ this.name = "InvariantError";
452
+ }
453
+ };
454
+
455
+ // src/shared/core/observability/log-cause.ts
456
+ function classifyLogCause(error) {
457
+ if (error instanceof HttpError) {
458
+ return httpCause(error);
459
+ }
460
+ if (error instanceof ValidationError) {
461
+ return { type: "validation", message: error.message };
462
+ }
463
+ if (error instanceof InvariantError) {
464
+ return { type: "invariant", message: error.message };
465
+ }
466
+ if (error instanceof NotAuthenticatedError) {
467
+ return { type: "not-authenticated" };
468
+ }
469
+ if (error instanceof NotImplementedError) {
470
+ return { type: "not-implemented" };
471
+ }
472
+ return { type: "generic-error", name: errorName(error) };
473
+ }
474
+ function describeErrorUnredacted(error) {
475
+ if (error instanceof HttpError) {
476
+ return describeHttpErrorRedacted(error);
477
+ }
478
+ if (error instanceof Error) {
479
+ return `${error.name}: ${error.message}`;
480
+ }
481
+ return `thrown non-error: ${stringifyUnredacted(error)}`;
482
+ }
483
+ function stringifyUnredacted(value) {
484
+ if (value === void 0) return "";
485
+ try {
486
+ return JSON.stringify(
487
+ value,
488
+ (_key, item) => typeof item === "bigint" ? `${item}` : item
489
+ ) ?? String(value);
490
+ } catch (_) {
491
+ return "<unserializable>";
492
+ }
493
+ }
494
+ function describeHttpErrorRedacted(error) {
495
+ const code = apiErrorCode(error);
496
+ const status = error.response.status;
497
+ return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
498
+ }
499
+ function errorName(error) {
500
+ return error instanceof Error ? error.name : `non-error ${typeof error}`;
501
+ }
502
+ function httpCause(error) {
503
+ return {
504
+ type: "http",
505
+ requestId: error.requestId,
506
+ status: error.response.status,
507
+ code: apiErrorCode(error),
508
+ eventId: apiErrorEventId(error)
509
+ };
510
+ }
511
+ function apiErrorEventId(error) {
512
+ const body = error.response.body;
513
+ if (typeof body !== "object" || body === null) return null;
514
+ const eventId = body.event_id;
515
+ return typeof eventId === "string" ? eventId : null;
516
+ }
517
+
518
+ // src/shared/core/observability/internal-logger.ts
519
+ function internalLogger(logger, scope) {
520
+ return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
521
+ }
522
+ var LEVEL_RANK = {
523
+ none: 0,
524
+ error: 1,
525
+ warn: 2,
526
+ info: 3,
527
+ debug: 4
528
+ };
529
+ function scopedLogger(logger, scope, bindings) {
530
+ const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
531
+ const safe = (event) => ({
532
+ msg: event.msg,
533
+ scope,
534
+ bindings,
535
+ fields: event.fields ?? {},
536
+ ...event.cause === void 0 ? {} : { cause: event.cause }
537
+ });
538
+ const unredacted = (event) => ({
539
+ msg: event.msg,
540
+ scope,
541
+ bindings,
542
+ fields: event.fields ?? {}
543
+ });
544
+ const self = {
545
+ child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
546
+ debug: (event) => {
547
+ if (admits("debug")) logger.debug(() => unredacted(event()));
548
+ },
549
+ info: (event) => {
550
+ if (admits("info")) logger.info(() => safe(event()));
551
+ },
552
+ warn: (event) => {
553
+ if (admits("warn")) logger.warn(() => safe(event()));
554
+ },
555
+ error: (event) => {
556
+ if (admits("error")) logger.error(() => safe(event()));
557
+ },
558
+ failure: (event, error) => {
559
+ if (admits("debug"))
560
+ logger.debug(() => unredacted(verbatim(event(), error)));
561
+ if (admits("error")) logger.error(() => safe(classified(event(), error)));
562
+ },
563
+ warning: (event, error) => {
564
+ if (admits("debug"))
565
+ logger.debug(() => unredacted(verbatim(event(), error)));
566
+ if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
567
+ },
568
+ wrap: async (op, params, run) => {
569
+ const opLog = self.child({ op });
570
+ opLog.debug(() => ({ msg: "call", fields: { params } }));
571
+ try {
572
+ return await run();
573
+ } catch (error) {
574
+ opLog.failure(() => ({ msg: "call failed" }), error);
575
+ throw error;
576
+ }
577
+ }
578
+ };
579
+ return self;
580
+ }
581
+ function verbatim(event, error) {
582
+ return {
583
+ msg: event.msg,
584
+ fields: { ...event.fields, error: describeErrorUnredacted(error) }
585
+ };
586
+ }
587
+ function classified(event, error) {
588
+ return { ...event, cause: event.cause ?? classifyLogCause(error) };
589
+ }
590
+ var noopInternalLogger = {
591
+ child: () => noopInternalLogger,
592
+ debug: () => void 0,
593
+ info: () => void 0,
594
+ warn: () => void 0,
595
+ error: () => void 0,
596
+ failure: () => void 0,
597
+ warning: () => void 0,
598
+ wrap: (_op, _params, run) => run()
599
+ };
600
+
416
601
  // src/shared/api/http-client.ts
417
602
  var HttpClient = class {
418
- constructor(config, middleware = {}) {
603
+ constructor(config, middleware = {}, logger = null, options = {}) {
419
604
  this.config = config;
420
605
  this.middleware = middleware;
606
+ this.log = internalLogger(logger, "HTTP");
607
+ this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
421
608
  }
422
609
  async send(request) {
423
610
  return this.runRequestWithAfterMiddleware(request);
@@ -453,7 +640,13 @@ var HttpClient = class {
453
640
  return {
454
641
  ...request,
455
642
  url,
456
- headers
643
+ headers,
644
+ // Only when absent: a retry or a post-renewal re-send arrives with the
645
+ // first attempt's id already on it, and keeping it is the whole point.
646
+ attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
647
+ request.attributes ?? Attributes.empty,
648
+ Attributes.requestId(this.makeRequestId())
649
+ ) : request.attributes
457
650
  };
458
651
  }
459
652
  /**
@@ -477,10 +670,89 @@ var HttpClient = class {
477
670
  }
478
671
  return request;
479
672
  }
480
- executeRequest(request) {
481
- return makeRequest(request);
673
+ /**
674
+ * One physical attempt, logged as one line.
675
+ *
676
+ * A non-2xx is a `warn` rather than an `error` because the wire does not
677
+ * know whether it is a failure: the retry middleware may turn a 503 into a
678
+ * success, and the token registry reads a 404 as "not listed". The namespace
679
+ * above decides, and logs the `error` when it does.
680
+ */
681
+ async executeRequest(request) {
682
+ const requestId2 = Attributes.getRequestId(request.attributes);
683
+ const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
684
+ const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
685
+ const startedAt = Date.now();
686
+ log.debug(() => ({
687
+ msg: "request sent",
688
+ fields: describeRequestUnredacted(request)
689
+ }));
690
+ try {
691
+ const response = await makeRequest(request);
692
+ const elapsed = Date.now() - startedAt;
693
+ const outcome = () => ({
694
+ msg: "request completed",
695
+ fields: {
696
+ ...identifyRequest(request),
697
+ "http.response.status_code": response.status,
698
+ duration_ms: elapsed,
699
+ attempt
700
+ }
701
+ });
702
+ if (response.status >= 200 && response.status < 300) {
703
+ log.info(outcome);
704
+ } else {
705
+ log.warn(outcome);
706
+ }
707
+ log.debug(() => ({
708
+ msg: "response received",
709
+ fields: { body: response.body }
710
+ }));
711
+ return requestId2 === null ? response : { ...response, requestId: requestId2 };
712
+ } catch (error) {
713
+ const elapsed = Date.now() - startedAt;
714
+ log.warning(
715
+ () => ({
716
+ msg: "request threw",
717
+ fields: {
718
+ ...identifyRequest(request),
719
+ duration_ms: elapsed,
720
+ attempt
721
+ }
722
+ }),
723
+ error
724
+ );
725
+ throw error;
726
+ }
482
727
  }
483
728
  };
729
+ function identifyRequest(request) {
730
+ const { host, path } = splitUrl(request.url);
731
+ return {
732
+ "http.request.method": request.method,
733
+ "server.address": host,
734
+ "url.path": path
735
+ };
736
+ }
737
+ function splitUrl(url) {
738
+ try {
739
+ const parsed = new URL(url);
740
+ return { host: parsed.host, path: parsed.pathname };
741
+ } catch (_) {
742
+ return { host: null, path: url };
743
+ }
744
+ }
745
+ function defaultMakeRequestId() {
746
+ return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
747
+ }
748
+ function describeRequestUnredacted(request) {
749
+ return {
750
+ "http.request.method": request.method,
751
+ "url.full": buildUrlWithQueryParams(request.url, request.queryParams),
752
+ headers: request.headers,
753
+ ...request.method === "POST" ? { body: request.body } : {}
754
+ };
755
+ }
484
756
 
485
757
  // src/shared/api/middleware/attach-session-middleware.ts
486
758
  function attachSessionMiddleware(fetchAccessToken) {
@@ -588,18 +860,22 @@ function renewSessionMiddleware(fetchAccessToken) {
588
860
 
589
861
  // src/shared/api/authenticated-api-client.ts
590
862
  var AuthenticatedApiClient = class {
591
- constructor(config, fetchAccessToken, additionalBeforeRequest = []) {
592
- this.httpClient = new HttpClient(config, {
593
- beforeRequest: [
594
- attachSessionMiddleware(fetchAccessToken),
595
- ...additionalBeforeRequest,
596
- idempotencyKeyMiddleware
597
- ],
598
- afterRequest: [
599
- renewSessionMiddleware(fetchAccessToken),
600
- requestRetryMiddleware
601
- ]
602
- });
863
+ constructor(config, fetchAccessToken, additionalBeforeRequest = [], logger = null) {
864
+ this.httpClient = new HttpClient(
865
+ config,
866
+ {
867
+ beforeRequest: [
868
+ attachSessionMiddleware(fetchAccessToken),
869
+ ...additionalBeforeRequest,
870
+ idempotencyKeyMiddleware
871
+ ],
872
+ afterRequest: [
873
+ renewSessionMiddleware(fetchAccessToken),
874
+ requestRetryMiddleware
875
+ ]
876
+ },
877
+ logger
878
+ );
603
879
  }
604
880
  async send(request) {
605
881
  const response = await this.httpClient.send(request);
@@ -613,10 +889,13 @@ var AuthenticatedApiClient = class {
613
889
 
614
890
  // src/client/core/api/api-client.ts
615
891
  var ApiClient = class {
616
- constructor(config, fetchAccessToken) {
617
- this.client = new AuthenticatedApiClient(config, fetchAccessToken, [
618
- userAgentMiddleware
619
- ]);
892
+ constructor(config, fetchAccessToken, logger = null) {
893
+ this.client = new AuthenticatedApiClient(
894
+ config,
895
+ fetchAccessToken,
896
+ [userAgentMiddleware],
897
+ logger
898
+ );
620
899
  }
621
900
  async send(request) {
622
901
  return this.client.send(request);
@@ -653,11 +932,15 @@ var ClientAuthNamespaceImpl = class {
653
932
  constructor(config, session) {
654
933
  this.config = config;
655
934
  this.session = session;
935
+ this.log = internalLogger(config.logger ?? null, "AUTH");
656
936
  }
657
937
  getState() {
658
938
  return this.session.getState();
659
939
  }
660
940
  async startOAuth() {
941
+ return this.log.wrap("startOAuth", void 0, () => this.redirectToOAuth());
942
+ }
943
+ async redirectToOAuth() {
661
944
  const pkceParams = await generatePKCEParams(this.config);
662
945
  sessionStorage.setItem(OAUTH_STATE_KEY, pkceParams.state);
663
946
  sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, pkceParams.codeVerifier);
@@ -670,9 +953,37 @@ var ClientAuthNamespaceImpl = class {
670
953
  state: pkceParams.state
671
954
  });
672
955
  const baseUrl = this.config.coinlistBaseUrl ?? COINLIST_BASE_URL;
956
+ this.log.child({ op: "startOAuth" }).info(() => ({ msg: "redirecting to CoinList", fields: { baseUrl } }));
673
957
  window.location.href = `${baseUrl}${OAUTH_PAGE_PATH}?${params.toString()}`;
674
958
  }
959
+ /**
960
+ * Every failure here is silent from the browser's side - a state mismatch
961
+ * and a missing verifier both just leave the user logged out - so the
962
+ * reason is logged rather than left for the host to infer from a callback.
963
+ */
675
964
  completeOAuth() {
965
+ const result = this.readOauthCallback();
966
+ switch (result.type) {
967
+ case "error":
968
+ this.log.child({ op: "completeOAuth" }).error(() => ({
969
+ msg: "oauth callback rejected",
970
+ fields: { reason: result.reason }
971
+ }));
972
+ return result;
973
+ case "ok":
974
+ this.log.child({ op: "completeOAuth" }).info(() => ({ msg: "authorization code received" }));
975
+ return result;
976
+ default: {
977
+ const _exhaustive = result;
978
+ return result;
979
+ }
980
+ }
981
+ }
982
+ logout() {
983
+ this.log.child({ op: "logout" }).info(() => ({ msg: "access token cleared" }));
984
+ this.session.clearAccessToken();
985
+ }
986
+ readOauthCallback() {
676
987
  const params = new URLSearchParams(window.location.search);
677
988
  const coinlistError = params.get("error");
678
989
  if (coinlistError) {
@@ -700,28 +1011,36 @@ var ClientAuthNamespaceImpl = class {
700
1011
  codeVerifier: CodeVerifier(codeVerifierValue)
701
1012
  };
702
1013
  }
703
- logout() {
704
- this.session.clearAccessToken();
705
- }
706
1014
  };
707
1015
 
708
1016
  // src/client/core/blockchain/wallet-error.ts
709
1017
  var import_viem = require("viem");
710
1018
  function classifyWalletError(error, ctx) {
711
- if (error instanceof import_viem.UserRejectedRequestError) {
1019
+ if (causeOf(error, import_viem.UserRejectedRequestError)) {
712
1020
  return { type: "user_rejected" };
713
1021
  }
714
- if (error instanceof import_viem.InsufficientFundsError) {
1022
+ if (causeOf(error, import_viem.InsufficientFundsError)) {
715
1023
  return { type: "insufficient_funds" };
716
1024
  }
717
- if (error instanceof import_viem.ContractFunctionRevertedError) {
718
- return { type: "contract_reverted", reason: error.reason ?? error.message };
1025
+ const reverted = causeOf(error, import_viem.ContractFunctionRevertedError);
1026
+ if (reverted) {
1027
+ return { type: "contract_reverted", reason: revertReason(reverted) };
719
1028
  }
720
- if (error instanceof import_viem.WaitForTransactionReceiptTimeoutError && ctx?.hash) {
1029
+ if (causeOf(error, import_viem.WaitForTransactionReceiptTimeoutError) && ctx?.hash) {
721
1030
  return { type: "timeout", hash: ctx.hash };
722
1031
  }
723
1032
  return { type: "unknown", cause: error };
724
1033
  }
1034
+ function causeOf(error, errorClass) {
1035
+ if (error instanceof errorClass) return error;
1036
+ if (!(error instanceof import_viem.BaseError)) return null;
1037
+ const found = error.walk((cause) => cause instanceof errorClass);
1038
+ return found instanceof errorClass ? found : null;
1039
+ }
1040
+ function revertReason(error) {
1041
+ if (!error.raw || error.raw === "0x") return null;
1042
+ return error.reason ?? error.data?.errorName ?? error.signature ?? null;
1043
+ }
725
1044
 
726
1045
  // src/shared/core/blockchain/erc20/abi.ts
727
1046
  var ERC20_ABI = [
@@ -833,8 +1152,8 @@ async function ensureErc20Allowance({
833
1152
  spender,
834
1153
  onProgress
835
1154
  }) {
836
- const emit = (phase) => onProgress?.(phase);
837
- emit("checking-allowance");
1155
+ const emit2 = (phase) => onProgress?.(phase);
1156
+ emit2("checking-allowance");
838
1157
  let allowance;
839
1158
  try {
840
1159
  allowance = await erc20.getAllowance({
@@ -856,7 +1175,7 @@ async function ensureErc20Allowance({
856
1175
  value: 0n,
857
1176
  pending: "resetting-allowance",
858
1177
  confirming: "confirming-allowance-reset",
859
- emit
1178
+ emit: emit2
860
1179
  });
861
1180
  if (reset.type === "error") return { type: "error", error: reset.error };
862
1181
  }
@@ -868,7 +1187,7 @@ async function ensureErc20Allowance({
868
1187
  value: amount.raw,
869
1188
  pending: "approving",
870
1189
  confirming: "confirming-approval",
871
- emit
1190
+ emit: emit2
872
1191
  });
873
1192
  if (approve.type === "error") {
874
1193
  return { type: "error", error: approve.error };
@@ -887,9 +1206,9 @@ async function submitErc20Approval(args) {
887
1206
  value,
888
1207
  pending,
889
1208
  confirming,
890
- emit
1209
+ emit: emit2
891
1210
  } = args;
892
- emit(pending);
1211
+ emit2(pending);
893
1212
  let hash;
894
1213
  try {
895
1214
  hash = await wallet.writeContract({
@@ -905,7 +1224,7 @@ async function submitErc20Approval(args) {
905
1224
  error: { step: "approval", cause: classifyWalletError(error) }
906
1225
  };
907
1226
  }
908
- emit(confirming);
1227
+ emit2(confirming);
909
1228
  let receipt;
910
1229
  try {
911
1230
  receipt = await wallet.awaitTx(hash, chain);
@@ -937,20 +1256,6 @@ async function fetchAllPages(fetchPage, baseParams) {
937
1256
  return items;
938
1257
  }
939
1258
 
940
- // src/shared/types/errors.ts
941
- var NotAuthenticatedError = class extends Error {
942
- constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
943
- super(message);
944
- this.name = "NotAuthenticatedError";
945
- }
946
- };
947
- var ValidationError = class extends Error {
948
- constructor(message) {
949
- super(message);
950
- this.name = "ValidationError";
951
- }
952
- };
953
-
954
1259
  // src/shared/types/blockchain/core.ts
955
1260
  var ETHEREUM_CHAINS = {
956
1261
  ethereum_mainnet: true,
@@ -991,11 +1296,14 @@ var STABLE_DECIMALS = AssetDecimals(6);
991
1296
  var DecimalString = (value) => value;
992
1297
  var MAX_UINT_256 = 2n ** 256n - 1n;
993
1298
  var assertUint256 = (value) => {
994
- if (value < 0n || value > MAX_UINT_256) {
995
- throw new Error(`Value out of uint256 bounds: ${value}`);
996
- }
997
- return value;
1299
+ if (isUint256(value)) return value;
1300
+ throw new InvariantError(`Value out of uint256 bounds: ${value}`);
1301
+ };
1302
+ var parseUint256 = (value, label) => {
1303
+ if (isUint256(value)) return value;
1304
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
998
1305
  };
1306
+ var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
999
1307
  var BlockchainAmount = Object.assign(
1000
1308
  (value) => value,
1001
1309
  {
@@ -1005,13 +1313,13 @@ var BlockchainAmount = Object.assign(
1005
1313
  );
1006
1314
  function combineAmounts(a, b, op) {
1007
1315
  if (a.decimals !== b.decimals) {
1008
- throw new Error(
1316
+ throw new InvariantError(
1009
1317
  `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
1010
1318
  );
1011
1319
  }
1012
1320
  const raw = op(a.raw, b.raw);
1013
1321
  if (raw < 0n || raw > MAX_UINT_256) {
1014
- throw new Error(`BlockchainAmount out of uint256 bounds: ${raw}`);
1322
+ throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
1015
1323
  }
1016
1324
  return BlockchainAmount({ raw, decimals: a.decimals });
1017
1325
  }
@@ -1082,25 +1390,31 @@ var SwapAuthorization = {
1082
1390
  };
1083
1391
  var SwapPreview = {
1084
1392
  fromDto: (dto) => ({
1085
- inputAmount: assertUint256(BigInt(dto.pay_input_amount)),
1086
- fee: assertUint256(BigInt(dto.fee)),
1087
- outputAmount: assertUint256(BigInt(dto.receive_output_amount))
1393
+ inputAmount: parseUint256(
1394
+ BigInt(dto.pay_input_amount),
1395
+ "SwapPreview.pay_input_amount"
1396
+ ),
1397
+ fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
1398
+ outputAmount: parseUint256(
1399
+ BigInt(dto.receive_output_amount),
1400
+ "SwapPreview.receive_output_amount"
1401
+ )
1088
1402
  })
1089
1403
  };
1090
1404
  var SwapStatus = {
1091
1405
  fromDto: (dto) => ({
1092
- stopped: assertUint256(BigInt(dto.stopped)),
1093
- swapLevel: assertUint256(BigInt(dto.swap_level))
1406
+ stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
1407
+ swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
1094
1408
  })
1095
1409
  };
1096
1410
  var TokenAllowance = {
1097
1411
  fromDto: (dto) => ({
1098
- allowance: assertUint256(BigInt(dto.allowance))
1412
+ allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
1099
1413
  })
1100
1414
  };
1101
1415
  var TokenBalance = {
1102
1416
  fromDto: (dto) => ({
1103
- balance: assertUint256(BigInt(dto.balance))
1417
+ balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
1104
1418
  })
1105
1419
  };
1106
1420
  var AllowWalletResponse = {
@@ -1229,14 +1543,19 @@ function toErc20Asset(dto) {
1229
1543
  var Erc20NamespaceImpl = class {
1230
1544
  constructor(ctx) {
1231
1545
  this.ctx = ctx;
1546
+ this.log = internalLogger(ctx.logger, "ERC20");
1232
1547
  }
1233
1548
  async getAllowance(params) {
1234
- await this.ctx.ensureUserAuthenticated();
1235
- return getTokenAllowance(this.ctx.api, params);
1549
+ return this.log.wrap("getAllowance", params, async () => {
1550
+ await this.ctx.ensureUserAuthenticated();
1551
+ return getTokenAllowance(this.ctx.api, params);
1552
+ });
1236
1553
  }
1237
1554
  async getBalance(params) {
1238
- await this.ctx.ensureUserAuthenticated();
1239
- return getTokenBalance(this.ctx.api, params);
1555
+ return this.log.wrap("getBalance", params, async () => {
1556
+ await this.ctx.ensureUserAuthenticated();
1557
+ return getTokenBalance(this.ctx.api, params);
1558
+ });
1240
1559
  }
1241
1560
  };
1242
1561
 
@@ -1420,7 +1739,7 @@ var TOKEN_REGISTRY = {
1420
1739
  case "USDT":
1421
1740
  return USDT;
1422
1741
  default:
1423
- throw new Error(`Unknown asset symbol: ${symbol}`);
1742
+ throw new InvariantError(`Unknown asset symbol: ${symbol}`);
1424
1743
  }
1425
1744
  },
1426
1745
  contractAddress: (symbol, chain) => {
@@ -1430,7 +1749,7 @@ var TOKEN_REGISTRY = {
1430
1749
  case "USDT":
1431
1750
  return USDT_ADDRESSES[chain];
1432
1751
  default:
1433
- throw new Error(`Unknown asset symbol: ${symbol}`);
1752
+ throw new InvariantError(`Unknown asset symbol: ${symbol}`);
1434
1753
  }
1435
1754
  }
1436
1755
  };
@@ -1476,15 +1795,30 @@ var Asset = {
1476
1795
  var OfferId = (value) => value;
1477
1796
  var OfferSlug = (value) => value;
1478
1797
  var Offer = {
1798
+ fromDto: (dto) => {
1799
+ if (!Array.isArray(dto.tokens)) {
1800
+ throw new ValidationError(
1801
+ `Offer.tokens: expected an array, got ${typeof dto.tokens}`
1802
+ );
1803
+ }
1804
+ return {
1805
+ id: OfferId(dto.id),
1806
+ slug: OfferSlug(dto.slug),
1807
+ type: dto.type,
1808
+ tagline: dto.tagline,
1809
+ bannerUrl: dto.banner_url,
1810
+ logoUrl: dto.logo_url,
1811
+ startsAt: new Date(dto.starts_at),
1812
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1813
+ tokens: dto.tokens.map(OfferToken.fromDto)
1814
+ };
1815
+ }
1816
+ };
1817
+ var OfferToken = {
1479
1818
  fromDto: (dto) => ({
1480
- id: OfferId(dto.id),
1481
- slug: OfferSlug(dto.slug),
1482
- type: dto.type,
1483
- tagline: dto.tagline,
1484
- bannerUrl: dto.banner_url,
1485
- logoUrl: dto.logo_url,
1486
- startsAt: new Date(dto.starts_at),
1487
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null
1819
+ role: dto.role,
1820
+ chain: Chain(dto.chain),
1821
+ address: EvmContractAddress(dto.address)
1488
1822
  })
1489
1823
  };
1490
1824
 
@@ -1494,25 +1828,39 @@ var OfferOptionSlug = (value) => value;
1494
1828
  var OfferDetail = {
1495
1829
  fromDto: (dto) => {
1496
1830
  if (!Array.isArray(dto.funding_assets)) {
1497
- throw new Error(`funding_assets must be an array`);
1831
+ throw new ValidationError(
1832
+ `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
1833
+ );
1498
1834
  }
1499
1835
  if (!Array.isArray(dto.options)) {
1500
- throw new Error(`options must be an array`);
1836
+ throw new ValidationError(
1837
+ `OfferDetail.options: expected an array, got ${typeof dto.options}`
1838
+ );
1501
1839
  }
1502
1840
  if (!Array.isArray(dto.terms)) {
1503
- throw new Error(`terms must be an array`);
1841
+ throw new ValidationError(
1842
+ `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
1843
+ );
1504
1844
  }
1505
1845
  if (!Array.isArray(dto.links)) {
1506
- throw new Error(`links must be an array`);
1846
+ throw new ValidationError(
1847
+ `OfferDetail.links: expected an array, got ${typeof dto.links}`
1848
+ );
1507
1849
  }
1508
1850
  if (!Array.isArray(dto.faqs)) {
1509
- throw new Error(`faqs must be an array`);
1851
+ throw new ValidationError(
1852
+ `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
1853
+ );
1510
1854
  }
1511
1855
  if (!Array.isArray(dto.milestones)) {
1512
- throw new Error(`milestones must be an array`);
1856
+ throw new ValidationError(
1857
+ `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
1858
+ );
1513
1859
  }
1514
1860
  if (!Array.isArray(dto.tokens)) {
1515
- throw new Error(`tokens must be an array`);
1861
+ throw new ValidationError(
1862
+ `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1863
+ );
1516
1864
  }
1517
1865
  return {
1518
1866
  id: OfferId(dto.id),
@@ -1574,13 +1922,6 @@ var Milestone = {
1574
1922
  status: dto.status
1575
1923
  })
1576
1924
  };
1577
- var OfferToken = {
1578
- fromDto: (dto) => ({
1579
- role: dto.role,
1580
- chain: Chain(dto.chain),
1581
- address: EvmContractAddress(dto.address)
1582
- })
1583
- };
1584
1925
 
1585
1926
  // src/shared/types/providers/coin-list/token-sale.ts
1586
1927
  var ParticipationId = (value) => value;
@@ -1667,29 +2008,38 @@ async function createParticipation(api, params) {
1667
2008
  var CoinListTokenSaleNamespaceImpl = class {
1668
2009
  constructor(ctx) {
1669
2010
  this.ctx = ctx;
2011
+ this.log = internalLogger(ctx.logger, "TOKEN_SALE");
1670
2012
  }
1671
2013
  async list(offerId) {
1672
- await this.ctx.ensureUserAuthenticated();
1673
- return fetchParticipations(this.ctx.api, offerId);
2014
+ return this.log.wrap("list", offerId, async () => {
2015
+ await this.ctx.ensureUserAuthenticated();
2016
+ return fetchParticipations(this.ctx.api, offerId);
2017
+ });
1674
2018
  }
1675
2019
  async listPage(params) {
1676
- await this.ctx.ensureUserAuthenticated();
1677
- return fetchParticipationsPage(this.ctx.api, params);
2020
+ return this.log.wrap("listPage", params, async () => {
2021
+ await this.ctx.ensureUserAuthenticated();
2022
+ return fetchParticipationsPage(this.ctx.api, params);
2023
+ });
1678
2024
  }
1679
2025
  async get(id) {
1680
- await this.ctx.ensureUserAuthenticated();
1681
- return fetchParticipation(this.ctx.api, id);
2026
+ return this.log.wrap("get", id, async () => {
2027
+ await this.ctx.ensureUserAuthenticated();
2028
+ return fetchParticipation(this.ctx.api, id);
2029
+ });
1682
2030
  }
1683
2031
  async createParticipation(params) {
1684
- await this.ctx.ensureUserAuthenticated();
1685
- return createParticipation(this.ctx.api, params);
2032
+ return this.log.wrap("createParticipation", params, async () => {
2033
+ await this.ctx.ensureUserAuthenticated();
2034
+ return createParticipation(this.ctx.api, params);
2035
+ });
1686
2036
  }
1687
2037
  };
1688
2038
 
1689
2039
  // src/shared/core/checkout/ondo/constants.ts
1690
2040
  var ONDO_SWAP_CONTRACT_ADDRESSES = {
1691
2041
  ethereum_sepolia: EvmContractAddress(
1692
- "0xFF9c5Ade32d9B4102469Bd5F3817CB0061b25feC"
2042
+ "0x7014019ed51Edab984a71D30F2707D2dB2316A7A"
1693
2043
  )
1694
2044
  };
1695
2045
  function ondoSwapContractAddress(chain) {
@@ -1888,18 +2238,25 @@ function sizeParam(params) {
1888
2238
  var OndoNamespaceImpl = class {
1889
2239
  constructor(ctx) {
1890
2240
  this.ctx = ctx;
2241
+ this.log = internalLogger(ctx.logger, "ONDO");
1891
2242
  }
1892
2243
  async getTradingStatus(params) {
1893
- await this.ctx.ensureUserAuthenticated();
1894
- return getOndoTradingStatus(this.ctx.api, params);
2244
+ return this.log.wrap("getTradingStatus", params, async () => {
2245
+ await this.ctx.ensureUserAuthenticated();
2246
+ return getOndoTradingStatus(this.ctx.api, params);
2247
+ });
1895
2248
  }
1896
2249
  async getQuote(params) {
1897
- await this.ctx.ensureUserAuthenticated();
1898
- return getOndoQuote(this.ctx.api, params);
2250
+ return this.log.wrap("getQuote", params, async () => {
2251
+ await this.ctx.ensureUserAuthenticated();
2252
+ return getOndoQuote(this.ctx.api, params);
2253
+ });
1899
2254
  }
1900
2255
  async buildSwapTransaction(params) {
1901
- await this.ctx.ensureUserAuthenticated();
1902
- return buildOndoSwapTransaction(this.ctx.api, params);
2256
+ return this.log.wrap("buildSwapTransaction", params, async () => {
2257
+ await this.ctx.ensureUserAuthenticated();
2258
+ return buildOndoSwapTransaction(this.ctx.api, params);
2259
+ });
1903
2260
  }
1904
2261
  };
1905
2262
 
@@ -2213,26 +2570,37 @@ function formattedPricePerShare(quote, locale) {
2213
2570
  var SuperstateSwapNamespaceImpl = class {
2214
2571
  constructor(ctx) {
2215
2572
  this.ctx = ctx;
2573
+ this.log = internalLogger(ctx.logger, "SUPERSTATE");
2216
2574
  }
2217
2575
  async getAuthorization(params) {
2218
- await this.ctx.ensureUserAuthenticated();
2219
- return getSwapAuthorization(this.ctx.api, params);
2576
+ return this.log.wrap("getAuthorization", params, async () => {
2577
+ await this.ctx.ensureUserAuthenticated();
2578
+ return getSwapAuthorization(this.ctx.api, params);
2579
+ });
2220
2580
  }
2221
2581
  async getPreview(params) {
2222
- await this.ctx.ensureUserAuthenticated();
2223
- return getSwapPreview(this.ctx.api, params);
2582
+ return this.log.wrap("getPreview", params, async () => {
2583
+ await this.ctx.ensureUserAuthenticated();
2584
+ return getSwapPreview(this.ctx.api, params);
2585
+ });
2224
2586
  }
2225
2587
  async getStatus(params) {
2226
- await this.ctx.ensureUserAuthenticated();
2227
- return getSwapStatus(this.ctx.api, params);
2588
+ return this.log.wrap("getStatus", params, async () => {
2589
+ await this.ctx.ensureUserAuthenticated();
2590
+ return getSwapStatus(this.ctx.api, params);
2591
+ });
2228
2592
  }
2229
2593
  async getOutputToken(params) {
2230
- await this.ctx.ensureUserAuthenticated();
2231
- return getSwapOutputToken(this.ctx.api, params);
2594
+ return this.log.wrap("getOutputToken", params, async () => {
2595
+ await this.ctx.ensureUserAuthenticated();
2596
+ return getSwapOutputToken(this.ctx.api, params);
2597
+ });
2232
2598
  }
2233
2599
  async allowWallet(params) {
2234
- await this.ctx.ensureUserAuthenticated();
2235
- return allowWallet(this.ctx.api, params);
2600
+ return this.log.wrap("allowWallet", params, async () => {
2601
+ await this.ctx.ensureUserAuthenticated();
2602
+ return allowWallet(this.ctx.api, params);
2603
+ });
2236
2604
  }
2237
2605
  };
2238
2606
 
@@ -2269,18 +2637,25 @@ async function fetchOfferDetails(api, id, clientCreds) {
2269
2637
  var OffersNamespaceImpl = class {
2270
2638
  constructor(ctx) {
2271
2639
  this.ctx = ctx;
2640
+ this.log = internalLogger(ctx.logger, "OFFERS");
2272
2641
  }
2273
2642
  async list() {
2274
- await this.ctx.ensureUserAuthenticated();
2275
- return fetchOffers(this.ctx.api, void 0);
2643
+ return this.log.wrap("list", void 0, async () => {
2644
+ await this.ctx.ensureUserAuthenticated();
2645
+ return fetchOffers(this.ctx.api, void 0);
2646
+ });
2276
2647
  }
2277
2648
  async listPage(params) {
2278
- await this.ctx.ensureUserAuthenticated();
2279
- return fetchOffersPage(this.ctx.api, params, void 0);
2649
+ return this.log.wrap("listPage", params, async () => {
2650
+ await this.ctx.ensureUserAuthenticated();
2651
+ return fetchOffersPage(this.ctx.api, params, void 0);
2652
+ });
2280
2653
  }
2281
2654
  async get(id) {
2282
- await this.ctx.ensureUserAuthenticated();
2283
- return fetchOfferDetails(this.ctx.api, id, void 0);
2655
+ return this.log.wrap("get", id, async () => {
2656
+ await this.ctx.ensureUserAuthenticated();
2657
+ return fetchOfferDetails(this.ctx.api, id, void 0);
2658
+ });
2284
2659
  }
2285
2660
  };
2286
2661
 
@@ -2413,38 +2788,49 @@ async function fetchRequirementStatuses(api, offerId) {
2413
2788
  var RequirementsNamespaceImpl = class {
2414
2789
  constructor(ctx) {
2415
2790
  this.ctx = ctx;
2791
+ this.log = internalLogger(ctx.logger, "REQUIREMENTS");
2416
2792
  }
2417
2793
  async forOffer(offerId) {
2418
- await this.ctx.ensureUserAuthenticated();
2419
- return fetchOfferRequirements(
2420
- this.ctx.api,
2421
- offerId,
2422
- void 0
2423
- );
2794
+ return this.log.wrap("forOffer", offerId, async () => {
2795
+ await this.ctx.ensureUserAuthenticated();
2796
+ return fetchOfferRequirements(
2797
+ this.ctx.api,
2798
+ offerId,
2799
+ void 0
2800
+ );
2801
+ });
2424
2802
  }
2425
2803
  async statuses(offerId) {
2426
- await this.ctx.ensureUserAuthenticated();
2427
- return fetchRequirementStatuses(this.ctx.api, offerId);
2804
+ return this.log.wrap("statuses", offerId, async () => {
2805
+ await this.ctx.ensureUserAuthenticated();
2806
+ return fetchRequirementStatuses(this.ctx.api, offerId);
2807
+ });
2428
2808
  }
2429
2809
  async createKycToken(params) {
2430
- await this.ctx.ensureUserAuthenticated();
2431
- return createKycToken(
2432
- this.ctx.api,
2433
- params?.levelName,
2434
- params?.reset
2435
- );
2810
+ return this.log.wrap("createKycToken", params, async () => {
2811
+ await this.ctx.ensureUserAuthenticated();
2812
+ return createKycToken(
2813
+ this.ctx.api,
2814
+ params?.levelName,
2815
+ params?.reset
2816
+ );
2817
+ });
2436
2818
  }
2437
2819
  async getPii() {
2438
- await this.ctx.ensureUserAuthenticated();
2439
- return fetchPii(this.ctx.api);
2820
+ return this.log.wrap("getPii", void 0, async () => {
2821
+ await this.ctx.ensureUserAuthenticated();
2822
+ return fetchPii(this.ctx.api);
2823
+ });
2440
2824
  }
2441
2825
  async submitDocument(params) {
2442
- await this.ctx.ensureUserAuthenticated();
2443
- return submitDocument(
2444
- this.ctx.api,
2445
- params.documentType,
2446
- params.fields
2447
- );
2826
+ return this.log.wrap("submitDocument", params, async () => {
2827
+ await this.ctx.ensureUserAuthenticated();
2828
+ return submitDocument(
2829
+ this.ctx.api,
2830
+ params.documentType,
2831
+ params.fields
2832
+ );
2833
+ });
2448
2834
  }
2449
2835
  };
2450
2836
 
@@ -2515,8 +2901,8 @@ var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
2515
2901
  );
2516
2902
 
2517
2903
  // src/shared/api/nabu/tokens.ts
2518
- function createNabuApiClient(baseUrl) {
2519
- return new HttpClient({ baseUrl });
2904
+ function createNabuApiClient(baseUrl, logger = null) {
2905
+ return new HttpClient({ baseUrl }, {}, logger);
2520
2906
  }
2521
2907
  async function fetchTokenMetadata(client, token) {
2522
2908
  const address = checksummed(token.address);
@@ -2589,14 +2975,23 @@ var TokensNamespaceImpl = class {
2589
2975
  * registry is unauthenticated and on its own host, so the frontline sender
2590
2976
  * and the auth check would both be dead weight here.
2591
2977
  */
2592
- constructor(baseUrl) {
2593
- this.api = createNabuApiClient(baseUrl);
2978
+ constructor(baseUrl, logger = null) {
2979
+ this.api = createNabuApiClient(baseUrl, logger);
2980
+ this.log = internalLogger(logger, "TOKENS");
2594
2981
  }
2595
2982
  get(token) {
2596
- return fetchTokenMetadata(this.api, token);
2983
+ return this.log.wrap(
2984
+ "get",
2985
+ token,
2986
+ () => fetchTokenMetadata(this.api, token)
2987
+ );
2597
2988
  }
2598
2989
  list(chain) {
2599
- return fetchTokensMetadata(this.api, chain);
2990
+ return this.log.wrap(
2991
+ "list",
2992
+ chain,
2993
+ () => fetchTokensMetadata(this.api, chain)
2994
+ );
2600
2995
  }
2601
2996
  };
2602
2997
 
@@ -2702,36 +3097,50 @@ async function removeOptionAddress(api, offerId, addressId) {
2702
3097
  var WalletsNamespaceImpl = class {
2703
3098
  constructor(ctx) {
2704
3099
  this.ctx = ctx;
3100
+ this.log = internalLogger(ctx.logger, "WALLETS");
2705
3101
  }
2706
3102
  async createOwnershipChallenge(params) {
2707
- await this.ctx.ensureUserAuthenticated();
2708
- return createWalletOwnershipChallenge(
2709
- this.ctx.api,
2710
- params
2711
- );
3103
+ return this.log.wrap("createOwnershipChallenge", params, async () => {
3104
+ await this.ctx.ensureUserAuthenticated();
3105
+ return createWalletOwnershipChallenge(
3106
+ this.ctx.api,
3107
+ params
3108
+ );
3109
+ });
2712
3110
  }
2713
3111
  async connectExternal(params) {
2714
- await this.ctx.ensureUserAuthenticated();
2715
- return connectExternalWallet(this.ctx.api, params);
3112
+ return this.log.wrap("connectExternal", params, async () => {
3113
+ await this.ctx.ensureUserAuthenticated();
3114
+ return connectExternalWallet(this.ctx.api, params);
3115
+ });
2716
3116
  }
2717
3117
  async list(params) {
2718
- await this.ctx.ensureUserAuthenticated();
2719
- return listOptionAddresses(
2720
- this.ctx.api,
2721
- params.offerId,
2722
- params.offerOptionId
2723
- );
3118
+ return this.log.wrap("list", params, async () => {
3119
+ await this.ctx.ensureUserAuthenticated();
3120
+ return listOptionAddresses(
3121
+ this.ctx.api,
3122
+ params.offerId,
3123
+ params.offerOptionId
3124
+ );
3125
+ });
2724
3126
  }
2725
3127
  async remove(params) {
2726
- await this.ctx.ensureUserAuthenticated();
2727
- return removeOptionAddress(
2728
- this.ctx.api,
2729
- params.offerId,
2730
- params.addressId
2731
- );
3128
+ return this.log.wrap("remove", params, async () => {
3129
+ await this.ctx.ensureUserAuthenticated();
3130
+ return removeOptionAddress(
3131
+ this.ctx.api,
3132
+ params.offerId,
3133
+ params.addressId
3134
+ );
3135
+ });
2732
3136
  }
2733
3137
  };
2734
3138
 
3139
+ // src/shared/types/blockchain/wallet-error.ts
3140
+ var RedactedWalletError = {
3141
+ fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
3142
+ };
3143
+
2735
3144
  // src/client/core/checkout/coin-list/token-sale-flows.ts
2736
3145
  async function executeTokenSale(params) {
2737
3146
  const {
@@ -2747,8 +3156,8 @@ async function executeTokenSale(params) {
2747
3156
  amount,
2748
3157
  onProgress
2749
3158
  } = params;
2750
- const emit = (phase) => onProgress?.(phase);
2751
- emit("checking-allowance");
3159
+ const emit2 = (phase) => onProgress?.(phase);
3160
+ emit2("checking-allowance");
2752
3161
  let currentAllowance;
2753
3162
  try {
2754
3163
  const allowance = await erc20.getAllowance({
@@ -2770,7 +3179,7 @@ async function executeTokenSale(params) {
2770
3179
  value: 0n,
2771
3180
  pending: "resetting-allowance",
2772
3181
  confirming: "confirming-allowance-reset",
2773
- emit
3182
+ emit: emit2
2774
3183
  });
2775
3184
  if (reset.type === "error") {
2776
3185
  return {
@@ -2787,13 +3196,13 @@ async function executeTokenSale(params) {
2787
3196
  value: amount.raw,
2788
3197
  pending: "approving",
2789
3198
  confirming: "confirming-approval",
2790
- emit
3199
+ emit: emit2
2791
3200
  });
2792
3201
  if (approve.type === "error") {
2793
3202
  return { type: "error", error: approve.error };
2794
3203
  }
2795
3204
  const approvalTxHash = approve.txHash;
2796
- emit("recording-participation");
3205
+ emit2("recording-participation");
2797
3206
  let participation;
2798
3207
  try {
2799
3208
  participation = await tokenSale.createParticipation({
@@ -2811,6 +3220,72 @@ async function executeTokenSale(params) {
2811
3220
  return { type: "success", participation, approvalTxHash };
2812
3221
  }
2813
3222
 
3223
+ // src/client/core/observability/flow-logging.ts
3224
+ async function withFlowLogging(log, flow, onProgress, run) {
3225
+ const flowLog = log.child({ flow });
3226
+ flowLog.info(() => ({ msg: "flow started" }));
3227
+ try {
3228
+ const result = await run((phase) => {
3229
+ flowLog.info(() => ({ msg: "flow advanced", fields: { phase } }));
3230
+ onProgress?.(phase);
3231
+ });
3232
+ logOutcome(flowLog, result);
3233
+ return result;
3234
+ } catch (error) {
3235
+ flowLog.failure(
3236
+ () => ({ msg: "flow threw instead of returning a step" }),
3237
+ error
3238
+ );
3239
+ throw error;
3240
+ }
3241
+ }
3242
+ function logOutcome(log, outcome) {
3243
+ switch (outcome.type) {
3244
+ case "success":
3245
+ log.info(() => ({ msg: "flow succeeded" }));
3246
+ return;
3247
+ case "error":
3248
+ log.debug(() => ({
3249
+ msg: "flow failed",
3250
+ fields: {
3251
+ step: outcome.error.step,
3252
+ error: describeErrorUnredacted(outcome.error.cause)
3253
+ }
3254
+ }));
3255
+ log.error(() => ({
3256
+ msg: "flow failed",
3257
+ fields: { step: outcome.error.step },
3258
+ ...walletCause(outcome.error.cause)
3259
+ }));
3260
+ return;
3261
+ default: {
3262
+ const _exhaustive = outcome;
3263
+ return;
3264
+ }
3265
+ }
3266
+ }
3267
+ function walletCause(cause) {
3268
+ if (!isWalletError(cause)) return {};
3269
+ return {
3270
+ cause: {
3271
+ type: "wallet",
3272
+ error: RedactedWalletError.fromWalletError(cause)
3273
+ }
3274
+ };
3275
+ }
3276
+ var WALLET_ERROR_TYPES = /* @__PURE__ */ new Set([
3277
+ "user_rejected",
3278
+ "insufficient_funds",
3279
+ "contract_reverted",
3280
+ "timeout",
3281
+ "unknown"
3282
+ ]);
3283
+ function isWalletError(value) {
3284
+ if (typeof value !== "object" || value === null) return false;
3285
+ const type = value.type;
3286
+ return typeof type === "string" && WALLET_ERROR_TYPES.has(type);
3287
+ }
3288
+
2814
3289
  // src/client/core/checkout/coin-list/client-token-sale-namespace.ts
2815
3290
  var ClientCoinListTokenSaleNamespaceImpl = class extends CoinListTokenSaleNamespaceImpl {
2816
3291
  constructor(ctx, erc20) {
@@ -2818,7 +3293,17 @@ var ClientCoinListTokenSaleNamespaceImpl = class extends CoinListTokenSaleNamesp
2818
3293
  this.erc20 = erc20;
2819
3294
  }
2820
3295
  execute(params) {
2821
- return executeTokenSale({ ...params, erc20: this.erc20, tokenSale: this });
3296
+ return withFlowLogging(
3297
+ this.log,
3298
+ "execute",
3299
+ params.onProgress,
3300
+ (onProgress) => executeTokenSale({
3301
+ ...params,
3302
+ onProgress,
3303
+ erc20: this.erc20,
3304
+ tokenSale: this
3305
+ })
3306
+ );
2822
3307
  }
2823
3308
  };
2824
3309
 
@@ -2844,7 +3329,7 @@ async function prepareOndoSwap(params) {
2844
3329
  amount,
2845
3330
  onProgress
2846
3331
  } = params;
2847
- const emit = (phase) => onProgress?.(phase);
3332
+ const emit2 = (phase) => onProgress?.(phase);
2848
3333
  const spender = ondoSwapContractAddress(chain);
2849
3334
  if (spender === null) {
2850
3335
  return { type: "error", error: { step: "unsupported-chain", chain } };
@@ -2856,10 +3341,10 @@ async function prepareOndoSwap(params) {
2856
3341
  amount,
2857
3342
  wallet,
2858
3343
  spender,
2859
- onProgress: emit
3344
+ onProgress: emit2
2860
3345
  });
2861
3346
  if (allowance.type === "error") return allowance;
2862
- emit("building-transaction");
3347
+ emit2("building-transaction");
2863
3348
  try {
2864
3349
  const transaction = await ondo.buildSwapTransaction({
2865
3350
  symbol,
@@ -2878,7 +3363,7 @@ async function prepareOndoSwap(params) {
2878
3363
  var INSUFFICIENT_ALLOWANCE_CODE = "insufficient_allowance";
2879
3364
  async function executeOndoSwap(params) {
2880
3365
  const { wallet, transaction, chain, now = /* @__PURE__ */ new Date(), onProgress } = params;
2881
- const emit = (phase) => onProgress?.(phase);
3366
+ const emit2 = (phase) => onProgress?.(phase);
2882
3367
  if (now.getTime() >= transaction.expiresAt.getTime()) {
2883
3368
  return { type: "error", error: { step: "quote-expired" } };
2884
3369
  }
@@ -2892,7 +3377,7 @@ async function executeOndoSwap(params) {
2892
3377
  }
2893
3378
  };
2894
3379
  }
2895
- emit("broadcasting-swap");
3380
+ emit2("broadcasting-swap");
2896
3381
  let txHash;
2897
3382
  try {
2898
3383
  txHash = await wallet.broadcastRawTx({
@@ -2906,7 +3391,7 @@ async function executeOndoSwap(params) {
2906
3391
  error: { step: "swap", cause: classifyWalletError(error) }
2907
3392
  };
2908
3393
  }
2909
- emit("confirming-swap");
3394
+ emit2("confirming-swap");
2910
3395
  let receipt;
2911
3396
  try {
2912
3397
  receipt = await wallet.awaitTx(txHash, chain);
@@ -2932,10 +3417,25 @@ var ClientOndoNamespaceImpl = class extends OndoNamespaceImpl {
2932
3417
  this.erc20 = erc20;
2933
3418
  }
2934
3419
  prepareSwap(params) {
2935
- return prepareOndoSwap({ ...params, ondo: this, erc20: this.erc20 });
3420
+ return withFlowLogging(
3421
+ this.log,
3422
+ "prepareSwap",
3423
+ params.onProgress,
3424
+ (onProgress) => prepareOndoSwap({
3425
+ ...params,
3426
+ onProgress,
3427
+ ondo: this,
3428
+ erc20: this.erc20
3429
+ })
3430
+ );
2936
3431
  }
2937
3432
  executeSwap(params) {
2938
- return executeOndoSwap(params);
3433
+ return withFlowLogging(
3434
+ this.log,
3435
+ "executeSwap",
3436
+ params.onProgress,
3437
+ (onProgress) => executeOndoSwap({ ...params, onProgress })
3438
+ );
2939
3439
  }
2940
3440
  };
2941
3441
 
@@ -2952,10 +3452,10 @@ async function executeSwap(params) {
2952
3452
  slippageBps,
2953
3453
  onProgress
2954
3454
  } = params;
2955
- const emit = (phase) => onProgress?.(phase);
3455
+ const emit2 = (phase) => onProgress?.(phase);
2956
3456
  const inputAmount = BlockchainAmount.add(quote.inputTokenAmount, quote.fee);
2957
3457
  const minOut = computeSlip(quote.outputTokenAmount, slippageBps).raw;
2958
- emit("checking-status");
3458
+ emit2("checking-status");
2959
3459
  let status;
2960
3460
  try {
2961
3461
  status = await swap.getStatus({ contractAddress, chain });
@@ -2972,12 +3472,12 @@ async function executeSwap(params) {
2972
3472
  amount: inputAmount,
2973
3473
  wallet,
2974
3474
  spender: contractAddress,
2975
- onProgress: emit
3475
+ onProgress: emit2
2976
3476
  });
2977
3477
  if (allowanceRes.type === "error") {
2978
3478
  return allowanceRes;
2979
3479
  }
2980
- emit("swapping");
3480
+ emit2("swapping");
2981
3481
  let swapTxHash;
2982
3482
  try {
2983
3483
  swapTxHash = await wallet.writeContract({
@@ -2993,7 +3493,7 @@ async function executeSwap(params) {
2993
3493
  error: { step: "swap", cause: classifyWalletError(error) }
2994
3494
  };
2995
3495
  }
2996
- emit("confirming-swap");
3496
+ emit2("confirming-swap");
2997
3497
  let receipt;
2998
3498
  try {
2999
3499
  receipt = await wallet.awaitTx(swapTxHash, chain);
@@ -3028,9 +3528,9 @@ async function executeSwap(params) {
3028
3528
  }
3029
3529
  async function authorizeWallet(params) {
3030
3530
  const { swap, wallets, wallet, offerId, contractAddress, chain, onProgress } = params;
3031
- const emit = (phase) => onProgress?.(phase);
3531
+ const emit2 = (phase) => onProgress?.(phase);
3032
3532
  const walletAddress = wallet.address;
3033
- emit("checking-authorization");
3533
+ emit2("checking-authorization");
3034
3534
  let auth;
3035
3535
  try {
3036
3536
  auth = await swap.getAuthorization({
@@ -3042,7 +3542,7 @@ async function authorizeWallet(params) {
3042
3542
  return { type: "error", error: { step: "authorization-check" } };
3043
3543
  }
3044
3544
  if (auth.authorized) return { type: "success" };
3045
- emit("requesting-challenge");
3545
+ emit2("requesting-challenge");
3046
3546
  let challenge;
3047
3547
  try {
3048
3548
  challenge = await wallets.createOwnershipChallenge({
@@ -3053,7 +3553,7 @@ async function authorizeWallet(params) {
3053
3553
  } catch {
3054
3554
  return { type: "error", error: { step: "challenge-request" } };
3055
3555
  }
3056
- emit("signing-message");
3556
+ emit2("signing-message");
3057
3557
  let signature;
3058
3558
  try {
3059
3559
  signature = await wallet.signMessage(challenge.message);
@@ -3063,7 +3563,7 @@ async function authorizeWallet(params) {
3063
3563
  error: { step: "signing", cause: classifyWalletError(error) }
3064
3564
  };
3065
3565
  }
3066
- emit("submitting-signature");
3566
+ emit2("submitting-signature");
3067
3567
  let allow;
3068
3568
  try {
3069
3569
  allow = await swap.allowWallet({
@@ -3076,7 +3576,7 @@ async function authorizeWallet(params) {
3076
3576
  return { type: "error", error: { step: "allow-wallet" } };
3077
3577
  }
3078
3578
  if (allow.action === "broadcast_transaction") {
3079
- emit("broadcasting-transaction");
3579
+ emit2("broadcasting-transaction");
3080
3580
  let hash;
3081
3581
  try {
3082
3582
  hash = await wallet.broadcastRawTx({
@@ -3090,7 +3590,7 @@ async function authorizeWallet(params) {
3090
3590
  error: { step: "broadcast", cause: classifyWalletError(error) }
3091
3591
  };
3092
3592
  }
3093
- emit("awaiting-confirmation");
3593
+ emit2("awaiting-confirmation");
3094
3594
  try {
3095
3595
  await wallet.awaitTx(hash, chain);
3096
3596
  } catch (error) {
@@ -3103,7 +3603,7 @@ async function authorizeWallet(params) {
3103
3603
  };
3104
3604
  }
3105
3605
  }
3106
- emit("verifying-authorization");
3606
+ emit2("verifying-authorization");
3107
3607
  let reCheck;
3108
3608
  try {
3109
3609
  reCheck = await swap.getAuthorization({
@@ -3128,10 +3628,25 @@ var ClientSuperstateSwapNamespaceImpl = class extends SuperstateSwapNamespaceImp
3128
3628
  this.wallets = wallets;
3129
3629
  }
3130
3630
  execute(params) {
3131
- return executeSwap({ ...params, swap: this, erc20: this.erc20 });
3631
+ return withFlowLogging(
3632
+ this.log,
3633
+ "execute",
3634
+ params.onProgress,
3635
+ (onProgress) => executeSwap({ ...params, onProgress, swap: this, erc20: this.erc20 })
3636
+ );
3132
3637
  }
3133
3638
  authorizeWallet(params) {
3134
- return authorizeWallet({ ...params, swap: this, wallets: this.wallets });
3639
+ return withFlowLogging(
3640
+ this.log,
3641
+ "authorizeWallet",
3642
+ params.onProgress,
3643
+ (onProgress) => authorizeWallet({
3644
+ ...params,
3645
+ onProgress,
3646
+ swap: this,
3647
+ wallets: this.wallets
3648
+ })
3649
+ );
3135
3650
  }
3136
3651
  };
3137
3652
 
@@ -3157,12 +3672,6 @@ function requirementPath(requirement) {
3157
3672
  switch (requirement.type) {
3158
3673
  case "kyc_approved":
3159
3674
  return VERIFY_IDENTITY_PATH;
3160
- case "identity_verified":
3161
- return VERIFY_IDENTITY_VERIFIED_PATH;
3162
- case "proof_of_address":
3163
- return VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH;
3164
- case "source_of_funds":
3165
- return VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH;
3166
3675
  case "accreditation":
3167
3676
  return VERIFY_IDENTITY_ACCREDITATION_PATH;
3168
3677
  case "external_wallet":
@@ -3187,7 +3696,14 @@ function requirementPath(requirement) {
3187
3696
 
3188
3697
  // src/client/core/support/client-support-namespace.ts
3189
3698
  var ClientSupportNamespaceImpl = class {
3699
+ constructor(logger = null) {
3700
+ this.log = internalLogger(logger, "SUPPORT");
3701
+ }
3190
3702
  contact() {
3703
+ this.log.child({ op: "contact" }).info(() => ({
3704
+ msg: "opening the support ticket page",
3705
+ fields: { supportUrl: SUPPORT_NEW_TICKET_URL }
3706
+ }));
3191
3707
  openInNewTab(SUPPORT_NEW_TICKET_URL);
3192
3708
  }
3193
3709
  };
@@ -3201,15 +3717,18 @@ var CoinListClientImpl = class {
3201
3717
  this._config = _config;
3202
3718
  /** Cached access token: undefined = loading, null = no token, AccessToken = logged in */
3203
3719
  this._accessToken = void 0;
3720
+ const logger = _config.logger ?? null;
3204
3721
  this.api = new ApiClient(
3205
3722
  {
3206
3723
  baseUrl: _config.baseUrl || PUBLIC_API_BASE_URL,
3207
3724
  xApiVersion: API_VERSION
3208
3725
  },
3209
- this.fetchAccessToken.bind(this)
3726
+ this.fetchAccessToken.bind(this),
3727
+ logger
3210
3728
  );
3211
3729
  const ctx = {
3212
3730
  api: this.api,
3731
+ logger,
3213
3732
  ensureUserAuthenticated: async () => this.ensureAuthenticated()
3214
3733
  };
3215
3734
  this.auth = new ClientAuthNamespaceImpl(_config, {
@@ -3233,9 +3752,10 @@ var CoinListClientImpl = class {
3233
3752
  );
3234
3753
  this.ondo = new ClientOndoNamespaceImpl(ctx, this.erc20);
3235
3754
  this.tokens = new TokensNamespaceImpl(
3236
- _config.tokensBaseUrl ?? NABU_BASE_URL
3755
+ _config.tokensBaseUrl ?? NABU_BASE_URL,
3756
+ logger
3237
3757
  );
3238
- this.support = new ClientSupportNamespaceImpl();
3758
+ this.support = new ClientSupportNamespaceImpl(logger);
3239
3759
  }
3240
3760
  async init() {
3241
3761
  await this.fetchAccessToken(true);
@@ -3276,17 +3796,28 @@ function useLocale() {
3276
3796
  return (0, import_react.useContext)(CoinListLocaleContext);
3277
3797
  }
3278
3798
 
3799
+ // src/client/hooks/shared/useLogger.ts
3800
+ var import_react2 = require("react");
3801
+ var CoinListLoggerContext = (0, import_react2.createContext)(null);
3802
+ function useLogger(hook) {
3803
+ const logger = (0, import_react2.useContext)(CoinListLoggerContext);
3804
+ return (0, import_react2.useMemo)(
3805
+ () => internalLogger(logger, "HOOKS").child({ hook }),
3806
+ [logger, hook]
3807
+ );
3808
+ }
3809
+
3279
3810
  // src/client/CoinListProvider.tsx
3280
3811
  var import_jsx_runtime = require("react/jsx-runtime");
3281
- var CoinListContext = (0, import_react2.createContext)(null);
3812
+ var CoinListContext = (0, import_react3.createContext)(null);
3282
3813
  function CoinListContextProvider({
3283
3814
  config,
3284
3815
  locale,
3285
3816
  children
3286
3817
  }) {
3287
- const [isReady, setIsReady] = (0, import_react2.useState)(false);
3288
- const coinlist = (0, import_react2.useMemo)(() => createCoinListClient(config), [config]);
3289
- (0, import_react2.useEffect)(() => {
3818
+ const [isReady, setIsReady] = (0, import_react3.useState)(false);
3819
+ const coinlist = (0, import_react3.useMemo)(() => createCoinListClient(config), [config]);
3820
+ (0, import_react3.useEffect)(() => {
3290
3821
  let isCancelled = false;
3291
3822
  if (coinlist.auth.getState() === "unknown") {
3292
3823
  coinlist.init().then(() => {
@@ -3305,22 +3836,23 @@ function CoinListContextProvider({
3305
3836
  isCancelled = true;
3306
3837
  };
3307
3838
  }, [coinlist]);
3308
- const value = (0, import_react2.useMemo)(() => ({ coinlist, isReady }), [coinlist, isReady]);
3309
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoinListContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoinListLocaleContext.Provider, { value: locale ?? DEFAULT_LOCALE, children }) });
3839
+ const value = (0, import_react3.useMemo)(() => ({ coinlist, isReady }), [coinlist, isReady]);
3840
+ const logger = config.logger ?? null;
3841
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoinListContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoinListLocaleContext.Provider, { value: locale ?? DEFAULT_LOCALE, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoinListLoggerContext.Provider, { value: logger, children }) }) });
3310
3842
  }
3311
3843
  var CoinListProvider = CoinListContextProvider;
3312
3844
 
3313
3845
  // src/client/CoinListStyleScope.tsx
3314
- var import_react3 = require("react");
3846
+ var import_react4 = require("react");
3315
3847
 
3316
3848
  // src/client/generated/sdk-styles.gen.ts
3317
3849
  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-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--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}}}@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-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}@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}}@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-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\\:-bottom-0\\.5{bottom:calc(var(--clcosdk-spacing) * -.5)}.clcosdk\\:bottom-full{bottom:100%}.clcosdk\\:left-1\\/2{left:50%}.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\\:mb-2{margin-bottom:calc(var(--clcosdk-spacing) * 2)}.clcosdk\\:mb-6{margin-bottom:calc(var(--clcosdk-spacing) * 6)}.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-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-28{height:calc(var(--clcosdk-spacing) * 28)}.clcosdk\\:h-52{height:calc(var(--clcosdk-spacing) * 52)}.clcosdk\\:h-\\[18px\\]{height:18px}.clcosdk\\:h-\\[54px\\]{height:54px}.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-\\[2\\.4rem\\]{min-height:2.4rem}.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-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-\\[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-\\[22rem\\]{max-width:22rem}.clcosdk\\:max-w-\\[28rem\\]{max-width:28rem}.clcosdk\\:max-w-\\[30rem\\]{max-width:30rem}.clcosdk\\:max-w-\\[760px\\]{max-width:760px}.clcosdk\\:max-w-\\[1200px\\]{max-width:1200px}.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\\: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-cols-2{grid-template-columns:repeat(2,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-3{gap:calc(var(--clcosdk-spacing) * 3)}.clcosdk\\:gap-4{gap:calc(var(--clcosdk-spacing) * 4)}.clcosdk\\:gap-5{gap:calc(var(--clcosdk-spacing) * 5)}.clcosdk\\:gap-6{gap:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:gap-8{gap:calc(var(--clcosdk-spacing) * 8)}.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-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-dashed{--tw-border-style:dashed;border-style:dashed}.clcosdk\\:border-accent\\/50{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-accent\\/50{border-color:color-mix(in oklab, var(--color-accent) 50%, transparent)}}.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,.clcosdk\\:border-border\\/60{border-color:var(--color-border)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:border-border\\/60{border-color:color-mix(in oklab, var(--color-border) 60%, transparent)}}.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-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-accent\\/10{background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:bg-accent\\/10{background-color:color-mix(in oklab, var(--color-accent) 10%, transparent)}}.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-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-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.clcosdk\\:bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.clcosdk\\:bg-\\[image\\:var\\(--btn-primary-gradient\\)\\]{background-image:var(--btn-primary-gradient)}.clcosdk\\:from-surface{--tw-gradient-from:var(--color-surface);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:from-transparent{--tw-gradient-from:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:via-section{--tw-gradient-via:var(--color-section);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.clcosdk\\:via-transparent{--tw-gradient-via:transparent;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.clcosdk\\:to-background{--tw-gradient-to:var(--color-background);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.clcosdk\\:to-overlay\\/35{--tw-gradient-to:var(--color-overlay)}@supports (color:color-mix(in lab, red, red)){.clcosdk\\:to-overlay\\/35{--tw-gradient-to:color-mix(in oklab, var(--color-overlay) 35%, transparent)}}.clcosdk\\:to-overlay\\/35{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.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-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-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-\\[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-\\[110\\%\\]{--tw-leading:110%;line-height:110%}.clcosdk\\:leading-\\[120\\%\\]{--tw-leading:120%;line-height:120%}.clcosdk\\:leading-\\[125\\%\\]{--tw-leading:125%;line-height:125%}.clcosdk\\:leading-\\[130\\%\\]{--tw-leading:130%;line-height:130%}.clcosdk\\:leading-\\[135\\%\\]{--tw-leading:135%;line-height:135%}.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-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\\: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-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.18\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f62e);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-\\[0_0_0_3px_rgba\\(59\\,130\\,246\\,0\\.25\\)\\]{--tw-shadow:0 0 0 3px var(--tw-shadow-color,#3b82f640);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-\\[0_10px_24px_rgba\\(0\\,0\\,0\\,0\\.18\\)\\]{--tw-shadow:0 10px 24px var(--tw-shadow-color,#0000002e);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-\\[0_10px_24px_rgba\\(0\\,0\\,0\\,0\\.25\\)\\]{--tw-shadow:0 10px 24px var(--tw-shadow-color,#00000040);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-\\[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-all{transition-property:all;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\\:ease-in-out{--tw-ease:var(--clcosdk-ease-in-out);transition-timing-function:var(--clcosdk-ease-in-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\\:opacity-100:is(:where(.clcosdk\\:group):hover *){opacity:1}}.clcosdk\\:placeholder\\:text-text-disabled::placeholder{color:var(--color-text-disabled)}@media (hover:hover){.clcosdk\\:hover\\:-translate-y-0\\.5:hover{--tw-translate-y:calc(var(--clcosdk-spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.clcosdk\\:hover\\:border-divider:hover{border-color:var(--color-divider)}.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\\:hover\\:shadow-\\[0px_14px_32px_-10px_rgba\\(0\\,0\\,0\\,0\\.35\\)\\]:hover{--tw-shadow:0px 14px 32px -10px var(--tw-shadow-color,#00000059);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-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-accent-focus:focus-visible{--tw-ring-color:var(--color-accent-focus)}.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-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 (min-width:40rem){.clcosdk\\:sm\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:48rem){.clcosdk\\:md\\:order-1{order:1}.clcosdk\\:md\\:order-2{order:2}.clcosdk\\:md\\:hidden{display:none}.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-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-card{border-radius:24px}.clcosdk\\:md\\:rounded-dialog{border-radius:32px}.clcosdk\\:md\\:p-6{padding:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:px-6{padding-inline:calc(var(--clcosdk-spacing) * 6)}.clcosdk\\:md\\:px-8{padding-inline:calc(var(--clcosdk-spacing) * 8)}}@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-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@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}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}';
3318
3850
 
3319
3851
  // src/client/CoinListStyleScope.tsx
3320
3852
  var import_jsx_runtime2 = require("react/jsx-runtime");
3321
- var ScopeContext = (0, import_react3.createContext)(false);
3853
+ var ScopeContext = (0, import_react4.createContext)(false);
3322
3854
  function CoinListStyleScope({ children }) {
3323
- const alreadyScoped = (0, import_react3.useContext)(ScopeContext);
3855
+ const alreadyScoped = (0, import_react4.useContext)(ScopeContext);
3324
3856
  if (alreadyScoped) {
3325
3857
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
3326
3858
  }
@@ -3357,7 +3889,7 @@ function CoinListStyleScope({ children }) {
3357
3889
 
3358
3890
  // src/client/components/design-system/ClButton.tsx
3359
3891
  var import_class_variance_authority = require("class-variance-authority");
3360
- var import_react4 = require("react");
3892
+ var import_react5 = require("react");
3361
3893
 
3362
3894
  // src/client/components/design-system/utils.ts
3363
3895
  var import_clsx = require("clsx");
@@ -3424,7 +3956,7 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
3424
3956
  }
3425
3957
  }
3426
3958
  );
3427
- var ClButton = (0, import_react4.forwardRef)(
3959
+ var ClButton = (0, import_react5.forwardRef)(
3428
3960
  ({
3429
3961
  className,
3430
3962
  variant,
@@ -3768,12 +4300,12 @@ function CoinListSignInCardView({
3768
4300
  }
3769
4301
 
3770
4302
  // src/client/hooks/auth/useCoinListSignInCardViewModel.ts
3771
- var import_react6 = require("react");
4303
+ var import_react7 = require("react");
3772
4304
 
3773
4305
  // src/client/hooks/useCoinList.ts
3774
- var import_react5 = require("react");
4306
+ var import_react6 = require("react");
3775
4307
  function useCoinList() {
3776
- const context = (0, import_react5.useContext)(CoinListContext);
4308
+ const context = (0, import_react6.useContext)(CoinListContext);
3777
4309
  if (context === null) {
3778
4310
  throw new CoinListClientInitializationError();
3779
4311
  }
@@ -3794,11 +4326,11 @@ var ERROR_MESSAGE = "Error signing in. Please try again.";
3794
4326
  function useCoinListSignInCardViewModel(options = {}) {
3795
4327
  const { status = "idle", onSignIn, onClose } = options;
3796
4328
  const { coinlist } = useCoinList();
3797
- const state = (0, import_react6.useMemo)(() => {
4329
+ const state = (0, import_react7.useMemo)(() => {
3798
4330
  const closable = onClose !== void 0;
3799
4331
  return status === "error" ? { type: "error", message: ERROR_MESSAGE, closable } : { type: "idle", closable };
3800
4332
  }, [status, onClose]);
3801
- const onEvent = (0, import_react6.useCallback)(
4333
+ const onEvent = (0, import_react7.useCallback)(
3802
4334
  (event) => {
3803
4335
  switch (event.type) {
3804
4336
  case "ON_SIGN_IN":
@@ -3846,7 +4378,7 @@ function CoinListSignInCardContainer({
3846
4378
  }
3847
4379
 
3848
4380
  // src/client/components/checkout/shared/amount/CheckoutAmountInput.tsx
3849
- var import_react7 = require("react");
4381
+ var import_react8 = require("react");
3850
4382
  var import_jsx_runtime12 = require("react/jsx-runtime");
3851
4383
  function CheckoutAmountInput({
3852
4384
  label,
@@ -3856,12 +4388,13 @@ function CheckoutAmountInput({
3856
4388
  invalid = false,
3857
4389
  disabled = false,
3858
4390
  prefix,
3859
- suffix,
4391
+ prefixTone = "primary",
3860
4392
  action,
3861
4393
  className
3862
4394
  }) {
3863
- const inputId = (0, import_react7.useId)();
4395
+ const inputId = (0, import_react8.useId)();
3864
4396
  const toneClass = invalid ? "clcosdk:text-error" : "clcosdk:text-text-primary";
4397
+ const prefixToneClass = prefixTone === "muted" ? "clcosdk:text-text-secondary" : toneClass;
3865
4398
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3866
4399
  "div",
3867
4400
  {
@@ -3891,7 +4424,7 @@ function CheckoutAmountInput({
3891
4424
  className: cn(
3892
4425
  typeClasses.h4,
3893
4426
  "clcosdk:shrink-0 clcosdk:font-medium",
3894
- toneClass
4427
+ prefixToneClass
3895
4428
  ),
3896
4429
  children: prefix
3897
4430
  }
@@ -3915,16 +4448,6 @@ function CheckoutAmountInput({
3915
4448
  toneClass
3916
4449
  )
3917
4450
  }
3918
- ),
3919
- suffix && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3920
- "span",
3921
- {
3922
- className: cn(
3923
- typeClasses.h4,
3924
- "clcosdk:shrink-0 clcosdk:font-medium clcosdk:text-text-secondary"
3925
- ),
3926
- children: suffix
3927
- }
3928
4451
  )
3929
4452
  ] }),
3930
4453
  action
@@ -4284,7 +4807,8 @@ function ActiveView({
4284
4807
  placeholder: AMOUNT_PLACEHOLDER,
4285
4808
  invalid: state.error !== null,
4286
4809
  disabled: isLoading,
4287
- suffix: selectedAsset?.symbol,
4810
+ prefix: selectedAsset?.symbol,
4811
+ prefixTone: "muted",
4288
4812
  action: selectedAsset && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4289
4813
  MaxButton,
4290
4814
  {
@@ -4489,13 +5013,13 @@ function CheckoutDetailList({
4489
5013
  }
4490
5014
 
4491
5015
  // src/client/components/design-system/Modal.tsx
4492
- var import_react8 = require("react");
5016
+ var import_react9 = require("react");
4493
5017
  var import_jsx_runtime21 = require("react/jsx-runtime");
4494
5018
  function Modal({ label, onClose, children, className }) {
4495
- const surfaceRef = (0, import_react8.useRef)(null);
4496
- const onCloseRef = (0, import_react8.useRef)(onClose);
5019
+ const surfaceRef = (0, import_react9.useRef)(null);
5020
+ const onCloseRef = (0, import_react9.useRef)(onClose);
4497
5021
  onCloseRef.current = onClose;
4498
- (0, import_react8.useEffect)(() => {
5022
+ (0, import_react9.useEffect)(() => {
4499
5023
  const previouslyFocused = document.activeElement;
4500
5024
  surfaceRef.current?.focus();
4501
5025
  const onKeyDown = (event) => {
@@ -4775,7 +5299,7 @@ function Skeleton({ variant = "text", className }) {
4775
5299
  }
4776
5300
 
4777
5301
  // src/client/components/design-system/Tooltip.tsx
4778
- var import_react9 = require("react");
5302
+ var import_react10 = require("react");
4779
5303
  var import_jsx_runtime26 = require("react/jsx-runtime");
4780
5304
  var positionClasses = {
4781
5305
  top: "clcosdk:bottom-full clcosdk:mb-2",
@@ -4787,7 +5311,7 @@ function Tooltip({
4787
5311
  children,
4788
5312
  className
4789
5313
  }) {
4790
- const tooltipId = (0, import_react9.useId)();
5314
+ const tooltipId = (0, import_react10.useId)();
4791
5315
  return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4792
5316
  "span",
4793
5317
  {
@@ -4919,7 +5443,8 @@ function ActiveView2({
4919
5443
  }
4920
5444
  )
4921
5445
  ] }),
4922
- state.error ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(QuoteLine, { tone: "error", children: state.error }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(QuoteStatusLine, { quote: state.quote, onEvent }),
5446
+ state.error !== null && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(QuoteLine, { tone: "error", children: state.error }),
5447
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(QuoteStatusLine, { quote: state.quote, onEvent }),
4923
5448
  /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4924
5449
  ClButton,
4925
5450
  {
@@ -5143,7 +5668,7 @@ function StatusIndicator({ status, className }) {
5143
5668
 
5144
5669
  // src/client/components/checkout/shared/sidebar/CheckoutSidebarCard.tsx
5145
5670
  var import_lucide_react5 = require("lucide-react");
5146
- var import_react10 = require("react");
5671
+ var import_react11 = require("react");
5147
5672
 
5148
5673
  // src/client/components/checkout/shared/common/CheckoutCard.tsx
5149
5674
  var import_jsx_runtime29 = require("react/jsx-runtime");
@@ -5173,8 +5698,8 @@ function CheckoutSidebarCard({
5173
5698
  hideDetailsLabel,
5174
5699
  className
5175
5700
  }) {
5176
- const [expanded, setExpanded] = (0, import_react10.useState)(false);
5177
- const rowsId = (0, import_react10.useId)();
5701
+ const [expanded, setExpanded] = (0, import_react11.useState)(false);
5702
+ const rowsId = (0, import_react11.useId)();
5178
5703
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
5179
5704
  CheckoutCard,
5180
5705
  {
@@ -5321,7 +5846,7 @@ function PriceCaption({ price }) {
5321
5846
  var import_lucide_react6 = require("lucide-react");
5322
5847
 
5323
5848
  // src/client/components/checkout/shared/selection/SelectableOptionRow.tsx
5324
- var import_react11 = require("react");
5849
+ var import_react12 = require("react");
5325
5850
  var import_jsx_runtime32 = require("react/jsx-runtime");
5326
5851
  function SelectableOptionRow({
5327
5852
  selected,
@@ -5405,10 +5930,10 @@ function RadioCircle({ selected }) {
5405
5930
  );
5406
5931
  }
5407
5932
  function OptionMetaRow({ children }) {
5408
- const items = import_react11.Children.toArray(children).filter(Boolean);
5933
+ const items = import_react12.Children.toArray(children).filter(Boolean);
5409
5934
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "clcosdk:flex clcosdk:min-w-0 clcosdk:items-center clcosdk:gap-1.5", children: items.map((item, index) => (
5410
5935
  // biome-ignore lint/suspicious/noArrayIndexKey: positional separators, and the list is caller-authored JSX.
5411
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react11.Fragment, { children: [
5936
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react12.Fragment, { children: [
5412
5937
  index > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MetaDot, {}),
5413
5938
  item
5414
5939
  ] }, index)
@@ -6006,7 +6531,7 @@ var SUPERSTATE_TOS_URL = "https://superstate.com/terms";
6006
6531
 
6007
6532
  // src/client/components/checkout/superstate/swap/review/SlippagePicker.tsx
6008
6533
  var import_lucide_react8 = require("lucide-react");
6009
- var import_react12 = require("react");
6534
+ var import_react13 = require("react");
6010
6535
  var import_jsx_runtime37 = require("react/jsx-runtime");
6011
6536
  function SlippagePicker({
6012
6537
  slippage,
@@ -6015,7 +6540,7 @@ function SlippagePicker({
6015
6540
  onSelect,
6016
6541
  className
6017
6542
  }) {
6018
- const optionsId = (0, import_react12.useId)();
6543
+ const optionsId = (0, import_react13.useId)();
6019
6544
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CoinListStyleScope, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
6020
6545
  "div",
6021
6546
  {
@@ -6874,10 +7399,10 @@ function ErrorView3({
6874
7399
  }
6875
7400
 
6876
7401
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
6877
- var import_react21 = require("react");
7402
+ var import_react22 = require("react");
6878
7403
 
6879
7404
  // src/client/hooks/checkout/ondo/buy/amount/useOndoAmountViewModel.ts
6880
- var import_react14 = require("react");
7405
+ var import_react15 = require("react");
6881
7406
 
6882
7407
  // src/client/ui/format/asset-icon.ts
6883
7408
  var USDC_ICON_URL = AssetIconUrl(
@@ -6950,7 +7475,7 @@ var CheckoutAssetUi = {
6950
7475
  };
6951
7476
 
6952
7477
  // src/client/hooks/shared/erc20/useErc20TokenBalances.ts
6953
- var import_react13 = require("react");
7478
+ var import_react14 = require("react");
6954
7479
  var ERC20_BALANCE_POLL_INTERVAL_MS = 15e3;
6955
7480
  function useErc20TokenBalances(options) {
6956
7481
  const {
@@ -6961,12 +7486,12 @@ function useErc20TokenBalances(options) {
6961
7486
  enabled
6962
7487
  } = options;
6963
7488
  const { coinlist, isReady } = useCoinList();
6964
- const [balances, setBalances] = (0, import_react13.useState)(/* @__PURE__ */ new Map());
6965
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
6966
- const fetchIdRef = (0, import_react13.useRef)(0);
6967
- const isFetchingRef = (0, import_react13.useRef)(false);
7489
+ const [balances, setBalances] = (0, import_react14.useState)(/* @__PURE__ */ new Map());
7490
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
7491
+ const fetchIdRef = (0, import_react14.useRef)(0);
7492
+ const isFetchingRef = (0, import_react14.useRef)(false);
6968
7493
  const assetsKey = assets.join(",");
6969
- (0, import_react13.useEffect)(() => {
7494
+ (0, import_react14.useEffect)(() => {
6970
7495
  if (!isReady) return;
6971
7496
  if (!enabled) {
6972
7497
  setIsLoading(false);
@@ -7031,13 +7556,13 @@ function useOndoAmountViewModel({
7031
7556
  }) {
7032
7557
  const { coinlist } = useCoinList();
7033
7558
  const locale = useLocale();
7034
- const [amountInput, setAmountInput] = (0, import_react14.useState)("");
7035
- const [selectedAsset, setSelectedAsset] = (0, import_react14.useState)(
7559
+ const [amountInput, setAmountInput] = (0, import_react15.useState)("");
7560
+ const [selectedAsset, setSelectedAsset] = (0, import_react15.useState)(
7036
7561
  ONDO_SUPPORTED_INPUT_ASSETS[0]
7037
7562
  );
7038
- const [error, setError] = (0, import_react14.useState)(null);
7039
- const [phase, setPhase] = (0, import_react14.useState)(null);
7040
- const preparationIdRef = (0, import_react14.useRef)(0);
7563
+ const [error, setError] = (0, import_react15.useState)(null);
7564
+ const [phase, setPhase] = (0, import_react15.useState)(null);
7565
+ const preparationIdRef = (0, import_react15.useRef)(0);
7041
7566
  const isActive = stepInput.type === "active";
7042
7567
  const networkName = getNetworkName(chain);
7043
7568
  const marketClosed = isActive && stepInput.tradingStatus?.type === "not-tradable";
@@ -7047,7 +7572,7 @@ function useOndoAmountViewModel({
7047
7572
  assets: ONDO_SUPPORTED_INPUT_ASSETS,
7048
7573
  enabled: isActive
7049
7574
  });
7050
- (0, import_react14.useEffect)(() => {
7575
+ (0, import_react15.useEffect)(() => {
7051
7576
  if (stepInput.type === "incomplete") {
7052
7577
  ++preparationIdRef.current;
7053
7578
  setAmountInput("");
@@ -7325,10 +7850,10 @@ function toInputAssetUi({
7325
7850
  }
7326
7851
 
7327
7852
  // src/client/hooks/checkout/ondo/buy/review/useOndoReviewViewModel.ts
7328
- var import_react17 = require("react");
7853
+ var import_react18 = require("react");
7329
7854
 
7330
7855
  // src/client/hooks/checkout/ondo/shared/data/useOndoSwapTransaction.ts
7331
- var import_react15 = require("react");
7856
+ var import_react16 = require("react");
7332
7857
 
7333
7858
  // src/client/hooks/checkout/ondo/shared/data/ondo-load-error.ts
7334
7859
  function ondoLoadErrorReason(error) {
@@ -7339,7 +7864,8 @@ function ondoLoadErrorReason(error) {
7339
7864
  function useOndoSwapTransaction(options) {
7340
7865
  const { request, data, enabled } = options;
7341
7866
  const { coinlist, isReady } = useCoinList();
7342
- const [state, setState] = (0, import_react15.useState)(
7867
+ const log = useLogger("useOndoSwapTransaction");
7868
+ const [state, setState] = (0, import_react16.useState)(
7343
7869
  () => data === void 0 ? { type: "LOADING" } : {
7344
7870
  type: "CONTENT",
7345
7871
  transaction: data,
@@ -7347,12 +7873,12 @@ function useOndoSwapTransaction(options) {
7347
7873
  refreshError: null
7348
7874
  }
7349
7875
  );
7350
- const fetchIdRef = (0, import_react15.useRef)(0);
7351
- const isFetchingRef = (0, import_react15.useRef)(false);
7876
+ const fetchIdRef = (0, import_react16.useRef)(0);
7877
+ const isFetchingRef = (0, import_react16.useRef)(false);
7352
7878
  const requestKey = request === null ? null : stableKey(request);
7353
- const requestRef = (0, import_react15.useRef)(request);
7879
+ const requestRef = (0, import_react16.useRef)(request);
7354
7880
  requestRef.current = request;
7355
- const build = (0, import_react15.useCallback)(async () => {
7881
+ const build = (0, import_react16.useCallback)(async () => {
7356
7882
  const params = requestRef.current;
7357
7883
  if (!isReady || !enabled || params === null) return;
7358
7884
  if (isFetchingRef.current) return;
@@ -7364,6 +7890,10 @@ function useOndoSwapTransaction(options) {
7364
7890
  try {
7365
7891
  const transaction = await coinlist.ondo.buildSwapTransaction(params);
7366
7892
  if (currentFetchId !== fetchIdRef.current) return;
7893
+ log.debug(() => ({
7894
+ msg: "settled",
7895
+ fields: { state: "CONTENT" }
7896
+ }));
7367
7897
  setState({
7368
7898
  type: "CONTENT",
7369
7899
  transaction,
@@ -7373,14 +7903,18 @@ function useOndoSwapTransaction(options) {
7373
7903
  } catch (error) {
7374
7904
  if (currentFetchId !== fetchIdRef.current) return;
7375
7905
  const reason = ondoLoadErrorReason(error);
7906
+ log.failure(
7907
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
7908
+ error
7909
+ );
7376
7910
  setState(
7377
7911
  (previous) => previous.type === "CONTENT" ? { ...previous, isRefreshing: false, refreshError: reason } : { type: "ERROR", reason }
7378
7912
  );
7379
7913
  } finally {
7380
7914
  isFetchingRef.current = false;
7381
7915
  }
7382
- }, [coinlist, isReady, enabled]);
7383
- (0, import_react15.useEffect)(() => {
7916
+ }, [coinlist, isReady, enabled, log]);
7917
+ (0, import_react16.useEffect)(() => {
7384
7918
  if (data === void 0) return;
7385
7919
  ++fetchIdRef.current;
7386
7920
  setState({
@@ -7391,14 +7925,14 @@ function useOndoSwapTransaction(options) {
7391
7925
  });
7392
7926
  }, [data]);
7393
7927
  const hasSeed = data !== void 0;
7394
- (0, import_react15.useEffect)(() => {
7928
+ (0, import_react16.useEffect)(() => {
7395
7929
  if (hasSeed || requestKey === null) return;
7396
7930
  build();
7397
7931
  return () => {
7398
7932
  ++fetchIdRef.current;
7399
7933
  };
7400
7934
  }, [build, requestKey, hasSeed]);
7401
- const refetch = (0, import_react15.useCallback)(() => {
7935
+ const refetch = (0, import_react16.useCallback)(() => {
7402
7936
  build();
7403
7937
  }, [build]);
7404
7938
  return { state, refetch };
@@ -7414,7 +7948,7 @@ function stableKey(request) {
7414
7948
  }
7415
7949
 
7416
7950
  // src/client/ui/hooks/useCountdown.ts
7417
- var import_react16 = require("react");
7951
+ var import_react17 = require("react");
7418
7952
  var DEFAULT_TICK_MS = 1e3;
7419
7953
  function useCountdown({
7420
7954
  until,
@@ -7422,8 +7956,8 @@ function useCountdown({
7422
7956
  enabled = true
7423
7957
  }) {
7424
7958
  const untilMs = until?.getTime() ?? null;
7425
- const [, tick] = (0, import_react16.useReducer)(nextTick, 0);
7426
- (0, import_react16.useEffect)(() => {
7959
+ const [, tick] = (0, import_react17.useReducer)(nextTick, 0);
7960
+ (0, import_react17.useEffect)(() => {
7427
7961
  if (untilMs === null || !enabled || remainingSeconds(untilMs) === 0) return;
7428
7962
  const interval = setInterval(() => {
7429
7963
  tick();
@@ -7451,8 +7985,8 @@ function useOndoReviewViewModel({
7451
7985
  }) {
7452
7986
  const { coinlist } = useCoinList();
7453
7987
  const locale = useLocale();
7454
- const [phase, setPhase] = (0, import_react17.useState)(null);
7455
- const [error, setError] = (0, import_react17.useState)(null);
7988
+ const [phase, setPhase] = (0, import_react18.useState)(null);
7989
+ const [error, setError] = (0, import_react18.useState)(null);
7456
7990
  const isActive = stepInput.type === "active";
7457
7991
  const { state: transactionState, refetch } = useOndoSwapTransaction({
7458
7992
  request: isActive ? {
@@ -7464,7 +7998,7 @@ function useOndoReviewViewModel({
7464
7998
  data: isActive ? stepInput.transaction : void 0,
7465
7999
  enabled: isActive
7466
8000
  });
7467
- (0, import_react17.useEffect)(() => {
8001
+ (0, import_react18.useEffect)(() => {
7468
8002
  if (stepInput.type === "incomplete") setError(null);
7469
8003
  }, [stepInput.type]);
7470
8004
  const transaction = transactionState.type === "CONTENT" ? transactionState.transaction : null;
@@ -7708,7 +8242,7 @@ function toMarketUi(state) {
7708
8242
  }
7709
8243
 
7710
8244
  // src/client/hooks/checkout/ondo/buy/wallet/useOndoWalletSelectViewModel.ts
7711
- var import_react18 = require("react");
8245
+ var import_react19 = require("react");
7712
8246
  var CONNECT_FAILED = "Could not connect that wallet. Please try again.";
7713
8247
  function useOndoWalletSelectViewModel({
7714
8248
  stepInput,
@@ -7717,8 +8251,9 @@ function useOndoWalletSelectViewModel({
7717
8251
  onComplete,
7718
8252
  onEdit
7719
8253
  }) {
7720
- const [selected, setSelected] = (0, import_react18.useState)(null);
7721
- const [error, setError] = (0, import_react18.useState)(null);
8254
+ const log = useLogger("useOndoWalletSelectViewModel");
8255
+ const [selected, setSelected] = (0, import_react19.useState)(null);
8256
+ const [error, setError] = (0, import_react19.useState)(null);
7722
8257
  const networkName = getNetworkName(chain);
7723
8258
  const selectedWallet = resolveWallet(wallets, selected);
7724
8259
  const uiState = () => {
@@ -7761,7 +8296,11 @@ function useOndoWalletSelectViewModel({
7761
8296
  setError(null);
7762
8297
  try {
7763
8298
  await wallets.connectExternal();
7764
- } catch {
8299
+ } catch (error2) {
8300
+ log.failure(
8301
+ () => ({ msg: "the host connectExternal handler threw" }),
8302
+ error2
8303
+ );
7765
8304
  setError(CONNECT_FAILED);
7766
8305
  return;
7767
8306
  }
@@ -7844,7 +8383,7 @@ function toConfirmedWalletUi(wallets, wallet) {
7844
8383
  }
7845
8384
 
7846
8385
  // src/client/hooks/checkout/ondo/shared/data/useOndoPrice.ts
7847
- var import_react19 = require("react");
8386
+ var import_react20 = require("react");
7848
8387
  var LOADING = { type: "LOADING" };
7849
8388
  function useOndoPrice(options) {
7850
8389
  const {
@@ -7856,13 +8395,15 @@ function useOndoPrice(options) {
7856
8395
  enabled
7857
8396
  } = options;
7858
8397
  const { coinlist, isReady } = useCoinList();
7859
- const [state, setState] = (0, import_react19.useState)(
8398
+ const log = useLogger("useOndoPrice");
8399
+ const [state, setState] = (0, import_react20.useState)(
7860
8400
  () => data === void 0 ? LOADING : { type: "CONTENT", quote: data, isRefreshing: false }
7861
8401
  );
7862
- const fetchIdRef = (0, import_react19.useRef)(0);
7863
- const isFetchingRef = (0, import_react19.useRef)(false);
8402
+ const fetchIdRef = (0, import_react20.useRef)(0);
8403
+ const isFetchingRef = (0, import_react20.useRef)(false);
8404
+ const hasQuoteRef = (0, import_react20.useRef)(data !== void 0);
7864
8405
  const sizeKey = quoteSizeKey(size);
7865
- (0, import_react19.useEffect)(() => {
8406
+ (0, import_react20.useEffect)(() => {
7866
8407
  if (!isReady || !enabled) return;
7867
8408
  const size2 = quoteSizeFromKey(sizeKey);
7868
8409
  const currentFetchId = ++fetchIdRef.current;
@@ -7876,11 +8417,31 @@ function useOndoPrice(options) {
7876
8417
  try {
7877
8418
  const quote = await coinlist.ondo.getQuote({ symbol, side, ...size2 });
7878
8419
  if (currentFetchId !== fetchIdRef.current) return;
8420
+ log.debug(() => ({
8421
+ msg: "settled",
8422
+ fields: { state: "CONTENT" }
8423
+ }));
8424
+ hasQuoteRef.current = true;
7879
8425
  setState({ type: "CONTENT", quote, isRefreshing: false });
7880
8426
  } catch (error) {
7881
8427
  if (currentFetchId !== fetchIdRef.current) return;
8428
+ const reason = ondoLoadErrorReason(error);
8429
+ if (hasQuoteRef.current) {
8430
+ log.warning(
8431
+ () => ({
8432
+ msg: "poll failed; keeping the last quote",
8433
+ fields: { reason }
8434
+ }),
8435
+ error
8436
+ );
8437
+ } else {
8438
+ log.failure(
8439
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
8440
+ error
8441
+ );
8442
+ }
7882
8443
  setState(
7883
- (previous) => previous.type === "CONTENT" ? { ...previous, isRefreshing: false } : { type: "ERROR", reason: ondoLoadErrorReason(error) }
8444
+ (previous) => previous.type === "CONTENT" ? { ...previous, isRefreshing: false } : { type: "ERROR", reason }
7884
8445
  );
7885
8446
  } finally {
7886
8447
  if (currentFetchId === fetchIdRef.current) {
@@ -7894,7 +8455,7 @@ function useOndoPrice(options) {
7894
8455
  clearInterval(interval);
7895
8456
  ++fetchIdRef.current;
7896
8457
  };
7897
- }, [coinlist, isReady, enabled, symbol, side, sizeKey, pollIntervalMs]);
8458
+ }, [coinlist, isReady, enabled, symbol, side, sizeKey, pollIntervalMs, log]);
7898
8459
  return { state };
7899
8460
  }
7900
8461
  function quoteSizeKey(size) {
@@ -7915,7 +8476,7 @@ function quoteSizeFromKey(key) {
7915
8476
  }
7916
8477
 
7917
8478
  // src/client/hooks/checkout/ondo/shared/data/useOndoTradingStatus.ts
7918
- var import_react20 = require("react");
8479
+ var import_react21 = require("react");
7919
8480
  var LOADING2 = { type: "LOADING" };
7920
8481
  function useOndoTradingStatus(options) {
7921
8482
  const {
@@ -7926,12 +8487,14 @@ function useOndoTradingStatus(options) {
7926
8487
  enabled
7927
8488
  } = options;
7928
8489
  const { coinlist, isReady } = useCoinList();
7929
- const [state, setState] = (0, import_react20.useState)(
8490
+ const log = useLogger("useOndoTradingStatus");
8491
+ const [state, setState] = (0, import_react21.useState)(
7930
8492
  () => data === void 0 ? LOADING2 : { type: "CONTENT", status: data }
7931
8493
  );
7932
- const fetchIdRef = (0, import_react20.useRef)(0);
7933
- const isFetchingRef = (0, import_react20.useRef)(false);
7934
- (0, import_react20.useEffect)(() => {
8494
+ const fetchIdRef = (0, import_react21.useRef)(0);
8495
+ const isFetchingRef = (0, import_react21.useRef)(false);
8496
+ const hasStatusRef = (0, import_react21.useRef)(data !== void 0);
8497
+ (0, import_react21.useEffect)(() => {
7935
8498
  if (!isReady || !enabled) return;
7936
8499
  const currentFetchId = ++fetchIdRef.current;
7937
8500
  isFetchingRef.current = false;
@@ -7941,11 +8504,31 @@ function useOndoTradingStatus(options) {
7941
8504
  try {
7942
8505
  const status = await coinlist.ondo.getTradingStatus({ symbol, side });
7943
8506
  if (currentFetchId !== fetchIdRef.current) return;
8507
+ log.debug(() => ({
8508
+ msg: "settled",
8509
+ fields: { state: "CONTENT", status: status.type }
8510
+ }));
8511
+ hasStatusRef.current = true;
7944
8512
  setState({ type: "CONTENT", status });
7945
8513
  } catch (error) {
7946
8514
  if (currentFetchId !== fetchIdRef.current) return;
8515
+ const reason = ondoLoadErrorReason(error);
8516
+ if (hasStatusRef.current) {
8517
+ log.warning(
8518
+ () => ({
8519
+ msg: "poll failed; keeping the last status",
8520
+ fields: { reason }
8521
+ }),
8522
+ error
8523
+ );
8524
+ } else {
8525
+ log.failure(
8526
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
8527
+ error
8528
+ );
8529
+ }
7947
8530
  setState(
7948
- (previous) => previous.type === "CONTENT" ? previous : { type: "ERROR", reason: ondoLoadErrorReason(error) }
8531
+ (previous) => previous.type === "CONTENT" ? previous : { type: "ERROR", reason }
7949
8532
  );
7950
8533
  } finally {
7951
8534
  if (currentFetchId === fetchIdRef.current) {
@@ -7959,7 +8542,7 @@ function useOndoTradingStatus(options) {
7959
8542
  clearInterval(interval);
7960
8543
  ++fetchIdRef.current;
7961
8544
  };
7962
- }, [coinlist, isReady, enabled, symbol, side, pollIntervalMs]);
8545
+ }, [coinlist, isReady, enabled, symbol, side, pollIntervalMs, log]);
7963
8546
  return { state };
7964
8547
  }
7965
8548
 
@@ -7973,8 +8556,8 @@ function useOndoBuyCheckoutViewModel({
7973
8556
  onOrderConfirmed
7974
8557
  }) {
7975
8558
  const locale = useLocale();
7976
- const [step, setStep] = (0, import_react21.useState)({ type: "wallet" });
7977
- const [orderConfirmed, setOrderConfirmed] = (0, import_react21.useState)({ type: "hidden" });
8559
+ const [step, setStep] = (0, import_react22.useState)({ type: "wallet" });
8560
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react22.useState)({ type: "hidden" });
7978
8561
  const { state: priceState } = useOndoPrice({
7979
8562
  symbol: ondoSymbol,
7980
8563
  side: "buy",
@@ -8161,10 +8744,10 @@ function toOrderConfirmedUi({
8161
8744
  }
8162
8745
 
8163
8746
  // src/client/hooks/checkout/superstate/swap/useSuperstateSwapCheckoutViewModel.ts
8164
- var import_react27 = require("react");
8747
+ var import_react28 = require("react");
8165
8748
 
8166
8749
  // src/client/hooks/checkout/superstate/swap/amount/useSuperstateAmountViewModel.ts
8167
- var import_react22 = require("react");
8750
+ var import_react23 = require("react");
8168
8751
  var NO_WALLET2 = EvmWalletAddress(
8169
8752
  "0x0000000000000000000000000000000000000000"
8170
8753
  );
@@ -8178,11 +8761,11 @@ function useSuperstateAmountViewModel({
8178
8761
  enabled = true
8179
8762
  }) {
8180
8763
  const locale = useLocale();
8181
- const [amountInput, setAmountInput] = (0, import_react22.useState)("");
8182
- const [selectedAsset, setSelectedAsset] = (0, import_react22.useState)(
8764
+ const [amountInput, setAmountInput] = (0, import_react23.useState)("");
8765
+ const [selectedAsset, setSelectedAsset] = (0, import_react23.useState)(
8183
8766
  SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]
8184
8767
  );
8185
- const [error, setError] = (0, import_react22.useState)(null);
8768
+ const [error, setError] = (0, import_react23.useState)(null);
8186
8769
  const isActive = stepInput.type === "active";
8187
8770
  const networkName = getNetworkName(chain);
8188
8771
  const { balances, isLoading: balancesLoading } = useErc20TokenBalances({
@@ -8195,7 +8778,7 @@ function useSuperstateAmountViewModel({
8195
8778
  // on this step satisfies the first and not the second.
8196
8779
  enabled: enabled && isActive
8197
8780
  });
8198
- (0, import_react22.useEffect)(() => {
8781
+ (0, import_react23.useEffect)(() => {
8199
8782
  if (stepInput.type === "incomplete") {
8200
8783
  setAmountInput("");
8201
8784
  setSelectedAsset(SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]);
@@ -8366,19 +8949,20 @@ function toInputAssetUi2({
8366
8949
  }
8367
8950
 
8368
8951
  // src/client/hooks/checkout/superstate/swap/data/useSwapOutputToken.ts
8369
- var import_react23 = require("react");
8952
+ var import_react24 = require("react");
8370
8953
  var LOADING_STATE = { type: "LOADING" };
8371
8954
  function useSwapOutputToken(options) {
8372
8955
  const { contractAddress, chain, enabled } = options;
8373
8956
  const { coinlist, isReady } = useCoinList();
8374
- const [outputTokenState, setOutputTokenState] = (0, import_react23.useState)(LOADING_STATE);
8375
- const [retryCount, setRetryCount] = (0, import_react23.useState)(0);
8376
- const fetchIdRef = (0, import_react23.useRef)(0);
8377
- const refetch = (0, import_react23.useCallback)(() => {
8957
+ const log = useLogger("useSwapOutputToken");
8958
+ const [outputTokenState, setOutputTokenState] = (0, import_react24.useState)(LOADING_STATE);
8959
+ const [retryCount, setRetryCount] = (0, import_react24.useState)(0);
8960
+ const fetchIdRef = (0, import_react24.useRef)(0);
8961
+ const refetch = (0, import_react24.useCallback)(() => {
8378
8962
  setOutputTokenState(LOADING_STATE);
8379
8963
  setRetryCount((count) => count + 1);
8380
8964
  }, []);
8381
- (0, import_react23.useEffect)(() => {
8965
+ (0, import_react24.useEffect)(() => {
8382
8966
  if (!enabled || !isReady) return;
8383
8967
  const currentFetchId = ++fetchIdRef.current;
8384
8968
  const load = async () => {
@@ -8388,9 +8972,17 @@ function useSwapOutputToken(options) {
8388
8972
  chain
8389
8973
  });
8390
8974
  if (currentFetchId !== fetchIdRef.current) return;
8975
+ log.debug(() => ({
8976
+ msg: "settled",
8977
+ fields: { state: "CONTENT", symbol: outputToken.symbol }
8978
+ }));
8391
8979
  setOutputTokenState({ type: "CONTENT", outputToken });
8392
- } catch {
8980
+ } catch (error) {
8393
8981
  if (currentFetchId !== fetchIdRef.current) return;
8982
+ log.failure(
8983
+ () => ({ msg: "settled", fields: { state: "ERROR" } }),
8984
+ error
8985
+ );
8394
8986
  setOutputTokenState({ type: "ERROR" });
8395
8987
  }
8396
8988
  };
@@ -8398,12 +8990,12 @@ function useSwapOutputToken(options) {
8398
8990
  return () => {
8399
8991
  ++fetchIdRef.current;
8400
8992
  };
8401
- }, [coinlist, isReady, contractAddress, chain, enabled, retryCount]);
8993
+ }, [coinlist, isReady, contractAddress, chain, enabled, retryCount, log]);
8402
8994
  return { outputTokenState, refetch };
8403
8995
  }
8404
8996
 
8405
8997
  // src/client/hooks/checkout/superstate/swap/data/useSwapQuote.ts
8406
- var import_react24 = require("react");
8998
+ var import_react25 = require("react");
8407
8999
  function useSwapQuote(options) {
8408
9000
  const {
8409
9001
  contractAddress,
@@ -8415,13 +9007,14 @@ function useSwapQuote(options) {
8415
9007
  enabled
8416
9008
  } = options;
8417
9009
  const { coinlist, isReady } = useCoinList();
8418
- const [quote, setQuote] = (0, import_react24.useState)(null);
8419
- const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
8420
- const [isRefreshing, setIsRefreshing] = (0, import_react24.useState)(false);
8421
- const isFetchingRef = (0, import_react24.useRef)(false);
8422
- const hasQuoteRef = (0, import_react24.useRef)(false);
8423
- const fetchIdRef = (0, import_react24.useRef)(0);
8424
- (0, import_react24.useEffect)(() => {
9010
+ const log = useLogger("useSwapQuote");
9011
+ const [quote, setQuote] = (0, import_react25.useState)(null);
9012
+ const [isLoading, setIsLoading] = (0, import_react25.useState)(true);
9013
+ const [isRefreshing, setIsRefreshing] = (0, import_react25.useState)(false);
9014
+ const isFetchingRef = (0, import_react25.useRef)(false);
9015
+ const hasQuoteRef = (0, import_react25.useRef)(false);
9016
+ const fetchIdRef = (0, import_react25.useRef)(0);
9017
+ (0, import_react25.useEffect)(() => {
8425
9018
  if (!isReady) return;
8426
9019
  if (!enabled) {
8427
9020
  setIsLoading(false);
@@ -8455,7 +9048,11 @@ function useSwapQuote(options) {
8455
9048
  hasQuoteRef.current = true;
8456
9049
  setIsLoading(false);
8457
9050
  }
8458
- } catch {
9051
+ } catch (error) {
9052
+ log.warning(
9053
+ () => ({ msg: "poll failed; retrying on the next tick" }),
9054
+ error
9055
+ );
8459
9056
  } finally {
8460
9057
  if (currentFetchId === fetchIdRef.current) {
8461
9058
  isFetchingRef.current = false;
@@ -8480,13 +9077,14 @@ function useSwapQuote(options) {
8480
9077
  inputTokenAddress,
8481
9078
  outputTokenDecimals,
8482
9079
  pollIntervalMs,
8483
- enabled
9080
+ enabled,
9081
+ log
8484
9082
  ]);
8485
9083
  return { quote, isLoading, isRefreshing };
8486
9084
  }
8487
9085
 
8488
9086
  // src/client/hooks/checkout/superstate/swap/review/useSuperstateReviewViewModel.ts
8489
- var import_react25 = require("react");
9087
+ var import_react26 = require("react");
8490
9088
  function useSuperstateReviewViewModel({
8491
9089
  stepInput,
8492
9090
  contractAddress,
@@ -8496,11 +9094,11 @@ function useSuperstateReviewViewModel({
8496
9094
  }) {
8497
9095
  const { coinlist, isReady } = useCoinList();
8498
9096
  const locale = useLocale();
8499
- const [slippageBps, setSlippageBps] = (0, import_react25.useState)(DEFAULT_SLIPPAGE_BPS);
8500
- const [slippageExpanded, setSlippageExpanded] = (0, import_react25.useState)(false);
8501
- const [phase, setPhase] = (0, import_react25.useState)(null);
8502
- const [error, setError] = (0, import_react25.useState)(null);
8503
- (0, import_react25.useEffect)(() => {
9097
+ const [slippageBps, setSlippageBps] = (0, import_react26.useState)(DEFAULT_SLIPPAGE_BPS);
9098
+ const [slippageExpanded, setSlippageExpanded] = (0, import_react26.useState)(false);
9099
+ const [phase, setPhase] = (0, import_react26.useState)(null);
9100
+ const [error, setError] = (0, import_react26.useState)(null);
9101
+ (0, import_react26.useEffect)(() => {
8504
9102
  if (stepInput.type === "incomplete") {
8505
9103
  setSlippageBps(DEFAULT_SLIPPAGE_BPS);
8506
9104
  setSlippageExpanded(false);
@@ -8817,7 +9415,7 @@ function priceUi(quote, outputToken, locale) {
8817
9415
  }
8818
9416
 
8819
9417
  // src/client/hooks/checkout/superstate/swap/wallet/useSuperstateWalletViewModel.ts
8820
- var import_react26 = require("react");
9418
+ var import_react27 = require("react");
8821
9419
  var CONNECT_FAILED2 = "Could not connect that wallet. Please try again.";
8822
9420
  function useSuperstateWalletViewModel({
8823
9421
  stepInput,
@@ -8829,12 +9427,13 @@ function useSuperstateWalletViewModel({
8829
9427
  onEdit
8830
9428
  }) {
8831
9429
  const { coinlist, isReady } = useCoinList();
8832
- const [selected, setSelected] = (0, import_react26.useState)(null);
8833
- const [phase, setPhase] = (0, import_react26.useState)(null);
8834
- const [error, setError] = (0, import_react26.useState)(null);
9430
+ const log = useLogger("useSuperstateWalletViewModel");
9431
+ const [selected, setSelected] = (0, import_react27.useState)(null);
9432
+ const [phase, setPhase] = (0, import_react27.useState)(null);
9433
+ const [error, setError] = (0, import_react27.useState)(null);
8835
9434
  const networkName = getNetworkName(chain);
8836
9435
  const selectedWallet = resolveWallet2(wallets, selected);
8837
- (0, import_react26.useEffect)(() => {
9436
+ (0, import_react27.useEffect)(() => {
8838
9437
  if (stepInput.type === "completed") {
8839
9438
  setPhase(null);
8840
9439
  setError(null);
@@ -8909,7 +9508,11 @@ function useSuperstateWalletViewModel({
8909
9508
  setError(null);
8910
9509
  try {
8911
9510
  await wallets.connectExternal();
8912
- } catch {
9511
+ } catch (error2) {
9512
+ log.failure(
9513
+ () => ({ msg: "the host connectExternal handler threw" }),
9514
+ error2
9515
+ );
8913
9516
  setError(CONNECT_FAILED2);
8914
9517
  return;
8915
9518
  }
@@ -9050,8 +9653,8 @@ function useSuperstateSwapCheckoutViewModel({
9050
9653
  const locale = useLocale();
9051
9654
  const contractAddress = superstateSwapContractAddress(chain);
9052
9655
  const assetIconUrl = offerIconUrl(offer);
9053
- const [step, setStep] = (0, import_react27.useState)({ type: "wallet" });
9054
- const [orderConfirmed, setOrderConfirmed] = (0, import_react27.useState)({ type: "hidden" });
9656
+ const [step, setStep] = (0, import_react28.useState)({ type: "wallet" });
9657
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react28.useState)({ type: "hidden" });
9055
9658
  const live = enabled && contractAddress !== null;
9056
9659
  const contract = contractAddress ?? NO_CONTRACT;
9057
9660
  const { outputTokenState, refetch: refetchOutputToken } = useSwapOutputToken({
@@ -9606,18 +10209,19 @@ function EmptyState() {
9606
10209
  }
9607
10210
 
9608
10211
  // src/client/hooks/offers/grid/useOffersGridViewModel.ts
9609
- var import_react29 = require("react");
10212
+ var import_react30 = require("react");
9610
10213
 
9611
10214
  // src/client/hooks/offers/data/useOffers.ts
9612
- var import_react28 = require("react");
10215
+ var import_react29 = require("react");
9613
10216
  var LOADING_STATE2 = { type: "LOADING" };
9614
10217
  function useOffers(options = {}) {
9615
10218
  const { coinlist, isReady } = useCoinList();
10219
+ const log = useLogger("useOffers");
9616
10220
  const { data: serverOffers } = options;
9617
- const [offersState, setOffersState] = (0, import_react28.useState)(
10221
+ const [offersState, setOffersState] = (0, import_react29.useState)(
9618
10222
  serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE2
9619
10223
  );
9620
- (0, import_react28.useEffect)(() => {
10224
+ (0, import_react29.useEffect)(() => {
9621
10225
  let isCancelled = false;
9622
10226
  if (!isReady) {
9623
10227
  if (serverOffers === void 0) {
@@ -9635,18 +10239,26 @@ function useOffers(options = {}) {
9635
10239
  setOffersState(LOADING_STATE2);
9636
10240
  coinlist.offers.list().then((offers) => {
9637
10241
  if (!isCancelled) {
10242
+ log.debug(() => ({
10243
+ msg: "settled",
10244
+ fields: { state: "CONTENT", count: offers.length }
10245
+ }));
9638
10246
  setOffersState({ type: "CONTENT", offers });
9639
10247
  }
9640
10248
  }).catch((error) => {
9641
10249
  if (!isCancelled) {
9642
10250
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
10251
+ log.failure(
10252
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
10253
+ error
10254
+ );
9643
10255
  setOffersState({ type: "ERROR", reason });
9644
10256
  }
9645
10257
  });
9646
10258
  return () => {
9647
10259
  isCancelled = true;
9648
10260
  };
9649
- }, [coinlist, isReady, serverOffers]);
10261
+ }, [coinlist, isReady, serverOffers, log]);
9650
10262
  return { offersState };
9651
10263
  }
9652
10264
 
@@ -9678,11 +10290,11 @@ function useOffersGridViewModel(options = {}) {
9678
10290
  const { data, onOfferClick } = options;
9679
10291
  const { offersState } = useOffers({ data });
9680
10292
  const locale = useLocale();
9681
- const state = (0, import_react29.useMemo)(
10293
+ const state = (0, import_react30.useMemo)(
9682
10294
  () => toUiState(offersState, locale, onOfferClick !== void 0),
9683
10295
  [offersState, locale, onOfferClick]
9684
10296
  );
9685
- const onEvent = (0, import_react29.useCallback)(
10297
+ const onEvent = (0, import_react30.useCallback)(
9686
10298
  (event) => {
9687
10299
  switch (event.type) {
9688
10300
  case "ON_OFFER_CLICK": {
@@ -9745,13 +10357,13 @@ function OffersGridContainer({
9745
10357
  }
9746
10358
 
9747
10359
  // src/client/components/requirements/checklist/ConnectedWalletList.tsx
9748
- var import_react30 = require("react");
10360
+ var import_react31 = require("react");
9749
10361
  var import_jsx_runtime48 = require("react/jsx-runtime");
9750
10362
  function ConnectedWalletRow({
9751
10363
  wallet,
9752
10364
  onRemove
9753
10365
  }) {
9754
- const [state, setState] = (0, import_react30.useState)("idle");
10366
+ const [state, setState] = (0, import_react31.useState)("idle");
9755
10367
  const remove = async () => {
9756
10368
  if (!onRemove) return;
9757
10369
  setState("removing");
@@ -10321,23 +10933,24 @@ function toError(error) {
10321
10933
  }
10322
10934
 
10323
10935
  // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
10324
- var import_react32 = require("react");
10936
+ var import_react33 = require("react");
10325
10937
 
10326
10938
  // src/client/hooks/requirements/data/useKycToken.ts
10327
- var import_react31 = require("react");
10939
+ var import_react32 = require("react");
10328
10940
  var IDLE_STATE = { type: "IDLE" };
10329
10941
  var LOADING_STATE3 = { type: "LOADING" };
10330
10942
  function useKycToken(levelName, reset) {
10331
10943
  const { coinlist } = useCoinList();
10332
- const [kycTokenState, setKycTokenState] = (0, import_react31.useState)(IDLE_STATE);
10333
- const resetPendingRef = (0, import_react31.useRef)(reset === true);
10334
- const tokenIssuedRef = (0, import_react31.useRef)(false);
10335
- (0, import_react31.useEffect)(() => {
10944
+ const log = useLogger("useKycToken");
10945
+ const [kycTokenState, setKycTokenState] = (0, import_react32.useState)(IDLE_STATE);
10946
+ const resetPendingRef = (0, import_react32.useRef)(reset === true);
10947
+ const tokenIssuedRef = (0, import_react32.useRef)(false);
10948
+ (0, import_react32.useEffect)(() => {
10336
10949
  if (!tokenIssuedRef.current) {
10337
10950
  resetPendingRef.current = reset === true;
10338
10951
  }
10339
10952
  }, [reset]);
10340
- const fetchToken = (0, import_react31.useCallback)(async () => {
10953
+ const fetchToken = (0, import_react32.useCallback)(async () => {
10341
10954
  setKycTokenState(LOADING_STATE3);
10342
10955
  try {
10343
10956
  const kycToken = await coinlist.requirements.createKycToken({
@@ -10346,14 +10959,22 @@ function useKycToken(levelName, reset) {
10346
10959
  });
10347
10960
  resetPendingRef.current = false;
10348
10961
  tokenIssuedRef.current = true;
10962
+ log.debug(() => ({
10963
+ msg: "settled",
10964
+ fields: { state: "CONTENT" }
10965
+ }));
10349
10966
  setKycTokenState({ type: "CONTENT", token: kycToken.token });
10350
10967
  return kycToken.token;
10351
10968
  } catch (error) {
10352
10969
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
10970
+ log.failure(
10971
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
10972
+ error
10973
+ );
10353
10974
  setKycTokenState({ type: "ERROR", reason });
10354
10975
  throw error;
10355
10976
  }
10356
- }, [coinlist, levelName]);
10977
+ }, [coinlist, levelName, log]);
10357
10978
  return { kycTokenState, fetchToken };
10358
10979
  }
10359
10980
 
@@ -10363,8 +10984,8 @@ var GENERIC_ERROR_MESSAGE2 = "Unable to start identity verification right now. P
10363
10984
  function useIdentityVerificationViewModel(options = {}) {
10364
10985
  const { levelName, reset, locale, onSubmitted, onError } = options;
10365
10986
  const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
10366
- const fetchedRef = (0, import_react32.useRef)(false);
10367
- (0, import_react32.useEffect)(() => {
10987
+ const fetchedRef = (0, import_react33.useRef)(false);
10988
+ (0, import_react33.useEffect)(() => {
10368
10989
  if (fetchedRef.current) {
10369
10990
  return;
10370
10991
  }
@@ -10372,7 +10993,7 @@ function useIdentityVerificationViewModel(options = {}) {
10372
10993
  fetchToken().catch(() => {
10373
10994
  });
10374
10995
  }, [fetchToken]);
10375
- const state = (0, import_react32.useMemo)(() => {
10996
+ const state = (0, import_react33.useMemo)(() => {
10376
10997
  switch (kycTokenState.type) {
10377
10998
  case "IDLE":
10378
10999
  case "LOADING":
@@ -10398,7 +11019,7 @@ function useIdentityVerificationViewModel(options = {}) {
10398
11019
  }
10399
11020
  }
10400
11021
  }, [kycTokenState, locale, fetchToken]);
10401
- const onEvent = (0, import_react32.useCallback)(
11022
+ const onEvent = (0, import_react33.useCallback)(
10402
11023
  (event) => {
10403
11024
  switch (event.type) {
10404
11025
  case "ON_RETRY":
@@ -10660,10 +11281,10 @@ function SignOnlyScreen({
10660
11281
  }
10661
11282
 
10662
11283
  // src/client/hooks/requirements/tax-document/useTaxDocumentModalViewModel.ts
10663
- var import_react34 = require("react");
11284
+ var import_react35 = require("react");
10664
11285
 
10665
11286
  // src/client/hooks/requirements/data/useTaxDocument.ts
10666
- var import_react33 = require("react");
11287
+ var import_react34 = require("react");
10667
11288
  var IDLE_SIGN = { type: "idle", error: null };
10668
11289
  var LOADING_STATE4 = { type: "LOADING" };
10669
11290
  var SIGN_FAILED_MESSAGE = "Unable to sign document. Please try again.";
@@ -10737,8 +11358,9 @@ function useTaxDocument({
10737
11358
  isOpen
10738
11359
  }) {
10739
11360
  const { coinlist, isReady } = useCoinList();
10740
- const [state, setState] = (0, import_react33.useState)(LOADING_STATE4);
10741
- (0, import_react33.useEffect)(() => {
11361
+ const log = useLogger("useTaxDocument");
11362
+ const [state, setState] = (0, import_react34.useState)(LOADING_STATE4);
11363
+ (0, import_react34.useEffect)(() => {
10742
11364
  let isCancelled = false;
10743
11365
  if (!isOpen) {
10744
11366
  return () => {
@@ -10768,16 +11390,18 @@ function useTaxDocument({
10768
11390
  });
10769
11391
  }).catch((error) => {
10770
11392
  if (isCancelled) return;
10771
- setState({
10772
- type: "ERROR",
10773
- reason: error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error"
10774
- });
11393
+ const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
11394
+ log.failure(
11395
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
11396
+ error
11397
+ );
11398
+ setState({ type: "ERROR", reason });
10775
11399
  });
10776
11400
  return () => {
10777
11401
  isCancelled = true;
10778
11402
  };
10779
- }, [coinlist, isReady, isOpen]);
10780
- const onEditField = (0, import_react33.useCallback)(
11403
+ }, [coinlist, isReady, isOpen, log]);
11404
+ const onEditField = (0, import_react34.useCallback)(
10781
11405
  (field, value) => {
10782
11406
  setState(
10783
11407
  (prev) => prev.type === "EDITING" ? { ...prev, fields: { ...prev.fields, [field]: value } } : prev
@@ -10785,7 +11409,7 @@ function useTaxDocument({
10785
11409
  },
10786
11410
  []
10787
11411
  );
10788
- const onStartEdit = (0, import_react33.useCallback)(() => {
11412
+ const onStartEdit = (0, import_react34.useCallback)(() => {
10789
11413
  setState(
10790
11414
  (prev) => prev.type === "REVIEW" ? {
10791
11415
  type: "EDITING",
@@ -10796,7 +11420,7 @@ function useTaxDocument({
10796
11420
  } : prev
10797
11421
  );
10798
11422
  }, []);
10799
- const onSaveEdit = (0, import_react33.useCallback)(() => {
11423
+ const onSaveEdit = (0, import_react34.useCallback)(() => {
10800
11424
  setState(
10801
11425
  (prev) => prev.type === "EDITING" ? {
10802
11426
  type: "REVIEW",
@@ -10807,7 +11431,7 @@ function useTaxDocument({
10807
11431
  } : prev
10808
11432
  );
10809
11433
  }, []);
10810
- const onCancelEdit = (0, import_react33.useCallback)(() => {
11434
+ const onCancelEdit = (0, import_react34.useCallback)(() => {
10811
11435
  setState(
10812
11436
  (prev) => prev.type === "EDITING" ? {
10813
11437
  type: "REVIEW",
@@ -10818,7 +11442,7 @@ function useTaxDocument({
10818
11442
  } : prev
10819
11443
  );
10820
11444
  }, []);
10821
- const onSign = (0, import_react33.useCallback)(() => {
11445
+ const onSign = (0, import_react34.useCallback)(() => {
10822
11446
  if (state.type !== "REVIEW" && state.type !== "SIGN_ONLY") return;
10823
11447
  if (state.type === "REVIEW" && state.fields.dob.trim() !== "" && !isValidUsDate(state.fields.dob)) {
10824
11448
  setState({
@@ -10833,12 +11457,13 @@ function useTaxDocument({
10833
11457
  fields: state.type === "REVIEW" ? toSubmissionFields(state.fields, state.addressParts) : {}
10834
11458
  }).then((submission) => {
10835
11459
  setState({ type: "SUBMITTED", submission });
10836
- }).catch(() => {
11460
+ }).catch((error) => {
11461
+ log.failure(() => ({ msg: "signing the tax document failed" }), error);
10837
11462
  setState(
10838
11463
  (prev) => prev.type === "REVIEW" || prev.type === "SIGN_ONLY" ? { ...prev, sign: { type: "idle", error: SIGN_FAILED_MESSAGE } } : prev
10839
11464
  );
10840
11465
  });
10841
- }, [state, coinlist]);
11466
+ }, [state, coinlist, log]);
10842
11467
  return { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign };
10843
11468
  }
10844
11469
 
@@ -10859,19 +11484,19 @@ function useTaxDocumentModalViewModel({
10859
11484
  onSubmitted
10860
11485
  }) {
10861
11486
  const { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign } = useTaxDocument({ isOpen });
10862
- (0, import_react34.useEffect)(() => {
11487
+ (0, import_react35.useEffect)(() => {
10863
11488
  if (state.type === "SUBMITTED") {
10864
11489
  onSubmitted?.(state.submission);
10865
11490
  onClose();
10866
11491
  }
10867
11492
  }, [state]);
10868
- const uiState = (0, import_react34.useMemo)(() => {
11493
+ const uiState = (0, import_react35.useMemo)(() => {
10869
11494
  if (!isOpen || state.type === "SUBMITTED") {
10870
11495
  return { type: "hidden" };
10871
11496
  }
10872
11497
  return { type: "content", title: toTitle(state), screen: toScreen(state) };
10873
11498
  }, [isOpen, state]);
10874
- const onEvent = (0, import_react34.useCallback)(
11499
+ const onEvent = (0, import_react35.useCallback)(
10875
11500
  (event) => {
10876
11501
  switch (event.type) {
10877
11502
  case "ON_CLOSE":
@@ -10977,14 +11602,14 @@ function TaxDocumentModalContainer({
10977
11602
  }
10978
11603
 
10979
11604
  // src/client/components/requirements/wallet/ConnectWalletModalView.tsx
10980
- var import_react35 = require("react");
11605
+ var import_react36 = require("react");
10981
11606
  var import_jsx_runtime57 = require("react/jsx-runtime");
10982
11607
  function ConnectWalletModalView({
10983
11608
  state,
10984
11609
  onEvent,
10985
11610
  className
10986
11611
  }) {
10987
- const titleId = (0, import_react35.useId)();
11612
+ const titleId = (0, import_react36.useId)();
10988
11613
  if (state.type === "hidden") {
10989
11614
  return null;
10990
11615
  }
@@ -11087,10 +11712,10 @@ function Screen2({
11087
11712
  }
11088
11713
 
11089
11714
  // src/client/hooks/requirements/wallet/useConnectWalletModalViewModel.ts
11090
- var import_react37 = require("react");
11715
+ var import_react38 = require("react");
11091
11716
 
11092
11717
  // src/client/hooks/requirements/data/useConnectWallet.ts
11093
- var import_react36 = require("react");
11718
+ var import_react37 = require("react");
11094
11719
 
11095
11720
  // src/client/core/wallets/connect-external-wallet.ts
11096
11721
  var DEFAULT_STATEMENT = "Sign this message to prove you own this wallet. This does not cost gas or move funds.";
@@ -11158,9 +11783,9 @@ async function connectExternalWalletFlow(params) {
11158
11783
  isCancelled,
11159
11784
  onProgress
11160
11785
  } = params;
11161
- const emit = (phase) => onProgress?.(phase);
11786
+ const emit2 = (phase) => onProgress?.(phase);
11162
11787
  const cancelled = () => isCancelled?.() ?? false;
11163
- emit("requesting-challenge");
11788
+ emit2("requesting-challenge");
11164
11789
  let challenge;
11165
11790
  try {
11166
11791
  challenge = await coinlist.wallets.createOwnershipChallenge(
@@ -11170,7 +11795,7 @@ async function connectExternalWalletFlow(params) {
11170
11795
  return { type: "error", error: classifyApiError(error) };
11171
11796
  }
11172
11797
  if (cancelled()) return { type: "cancelled" };
11173
- emit("signing-message");
11798
+ emit2("signing-message");
11174
11799
  let signature;
11175
11800
  try {
11176
11801
  signature = await wallet.signMessage(challenge.message);
@@ -11181,7 +11806,7 @@ async function connectExternalWalletFlow(params) {
11181
11806
  return { type: "error", error: flowError("unknown") };
11182
11807
  }
11183
11808
  if (cancelled()) return { type: "cancelled" };
11184
- emit("submitting-signature");
11809
+ emit2("submitting-signature");
11185
11810
  try {
11186
11811
  const binding = await coinlist.wallets.connectExternal({
11187
11812
  offerId,
@@ -11221,24 +11846,24 @@ function useConnectWallet({
11221
11846
  statement
11222
11847
  }) {
11223
11848
  const { coinlist } = useCoinList();
11224
- const [state, setState] = (0, import_react36.useState)(
11849
+ const [state, setState] = (0, import_react37.useState)(
11225
11850
  () => wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
11226
11851
  );
11227
- const attempt = (0, import_react36.useRef)(0);
11228
- (0, import_react36.useEffect)(() => {
11852
+ const attempt = (0, import_react37.useRef)(0);
11853
+ (0, import_react37.useEffect)(() => {
11229
11854
  attempt.current += 1;
11230
11855
  if (!isOpen) return;
11231
11856
  setState(
11232
11857
  wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
11233
11858
  );
11234
11859
  }, [isOpen, wallet?.address]);
11235
- (0, import_react36.useEffect)(
11860
+ (0, import_react37.useEffect)(
11236
11861
  () => () => {
11237
11862
  attempt.current += 1;
11238
11863
  },
11239
11864
  []
11240
11865
  );
11241
- const onSign = (0, import_react36.useCallback)(() => {
11866
+ const onSign = (0, import_react37.useCallback)(() => {
11242
11867
  if (!wallet || state.type !== "READY") return;
11243
11868
  attempt.current += 1;
11244
11869
  const gen = attempt.current;
@@ -11300,13 +11925,13 @@ function useConnectWalletModalViewModel({
11300
11925
  challengeType,
11301
11926
  statement
11302
11927
  });
11303
- (0, import_react37.useEffect)(() => {
11928
+ (0, import_react38.useEffect)(() => {
11304
11929
  if (state.type === "CONNECTED") {
11305
11930
  onConnected?.(state.binding);
11306
11931
  onClose();
11307
11932
  }
11308
11933
  }, [state]);
11309
- const uiState = (0, import_react37.useMemo)(() => {
11934
+ const uiState = (0, import_react38.useMemo)(() => {
11310
11935
  if (!isOpen || state.type === "CONNECTED") {
11311
11936
  return { type: "hidden" };
11312
11937
  }
@@ -11331,7 +11956,7 @@ function useConnectWalletModalViewModel({
11331
11956
  canRequestConnect
11332
11957
  };
11333
11958
  }, [isOpen, state, onRequestConnect]);
11334
- const onEvent = (0, import_react37.useCallback)(
11959
+ const onEvent = (0, import_react38.useCallback)(
11335
11960
  (event) => {
11336
11961
  switch (event.type) {
11337
11962
  case "ON_CLOSE":
@@ -11372,7 +11997,7 @@ function ConnectWalletModalContainer({
11372
11997
  }
11373
11998
 
11374
11999
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
11375
- var import_react40 = require("react");
12000
+ var import_react41 = require("react");
11376
12001
 
11377
12002
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.types.ts
11378
12003
  var RequirementItemUi = {
@@ -11426,7 +12051,7 @@ var ChecklistStatus = {
11426
12051
  };
11427
12052
 
11428
12053
  // src/client/hooks/requirements/data/useOptionAddresses.ts
11429
- var import_react38 = require("react");
12054
+ var import_react39 = require("react");
11430
12055
  var LOADING_STATE5 = { type: "LOADING" };
11431
12056
  var EMPTY_STATE = {
11432
12057
  type: "CONTENT",
@@ -11434,20 +12059,21 @@ var EMPTY_STATE = {
11434
12059
  };
11435
12060
  function useOptionAddresses(offerId, offerOptionId, options = {}) {
11436
12061
  const { coinlist, isReady } = useCoinList();
12062
+ const log = useLogger("useOptionAddresses");
11437
12063
  const { data, enabled = true } = options;
11438
- const [addressesState, setAddressesState] = (0, import_react38.useState)(
12064
+ const [addressesState, setAddressesState] = (0, import_react39.useState)(
11439
12065
  data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE5
11440
12066
  );
11441
- const [fetchKey, setFetchKey] = (0, import_react38.useState)(0);
11442
- const refetch = (0, import_react38.useCallback)(() => setFetchKey((k) => k + 1), []);
11443
- const disconnect = (0, import_react38.useCallback)(
12067
+ const [fetchKey, setFetchKey] = (0, import_react39.useState)(0);
12068
+ const refetch = (0, import_react39.useCallback)(() => setFetchKey((k) => k + 1), []);
12069
+ const disconnect = (0, import_react39.useCallback)(
11444
12070
  async (addressId) => {
11445
12071
  await coinlist.wallets.remove({ offerId, addressId });
11446
12072
  refetch();
11447
12073
  },
11448
12074
  [coinlist, offerId, refetch]
11449
12075
  );
11450
- (0, import_react38.useEffect)(() => {
12076
+ (0, import_react39.useEffect)(() => {
11451
12077
  let isCancelled = false;
11452
12078
  if (!enabled) {
11453
12079
  setAddressesState(
@@ -11479,33 +12105,42 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
11479
12105
  setAddressesState(LOADING_STATE5);
11480
12106
  coinlist.wallets.list({ offerId, offerOptionId }).then((addresses) => {
11481
12107
  if (!isCancelled) {
12108
+ log.debug(() => ({
12109
+ msg: "settled",
12110
+ fields: { state: "CONTENT", count: addresses.length }
12111
+ }));
11482
12112
  setAddressesState({ type: "CONTENT", addresses });
11483
12113
  }
11484
12114
  }).catch((error) => {
11485
12115
  if (!isCancelled) {
11486
12116
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
12117
+ log.failure(
12118
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
12119
+ error
12120
+ );
11487
12121
  setAddressesState({ type: "ERROR", reason });
11488
12122
  }
11489
12123
  });
11490
12124
  return () => {
11491
12125
  isCancelled = true;
11492
12126
  };
11493
- }, [coinlist, isReady, enabled, offerId, offerOptionId, fetchKey]);
12127
+ }, [coinlist, isReady, enabled, offerId, offerOptionId, fetchKey, log]);
11494
12128
  return { addressesState, refetch, disconnect };
11495
12129
  }
11496
12130
 
11497
12131
  // src/client/hooks/requirements/data/useRequirements.ts
11498
- var import_react39 = require("react");
12132
+ var import_react40 = require("react");
11499
12133
  var LOADING_STATE6 = { type: "LOADING" };
11500
12134
  function useRequirements(offerId, options = {}) {
11501
12135
  const { coinlist, isReady } = useCoinList();
12136
+ const log = useLogger("useRequirements");
11502
12137
  const { data } = options;
11503
- const [requirementsState, setRequirementsState] = (0, import_react39.useState)(
12138
+ const [requirementsState, setRequirementsState] = (0, import_react40.useState)(
11504
12139
  data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE6
11505
12140
  );
11506
- const [fetchKey, setFetchKey] = (0, import_react39.useState)(0);
11507
- const refetch = (0, import_react39.useCallback)(() => setFetchKey((k) => k + 1), []);
11508
- (0, import_react39.useEffect)(() => {
12141
+ const [fetchKey, setFetchKey] = (0, import_react40.useState)(0);
12142
+ const refetch = (0, import_react40.useCallback)(() => setFetchKey((k) => k + 1), []);
12143
+ (0, import_react40.useEffect)(() => {
11509
12144
  let isCancelled = false;
11510
12145
  if (!isReady) {
11511
12146
  if (data === void 0) {
@@ -11532,6 +12167,14 @@ function useRequirements(offerId, options = {}) {
11532
12167
  coinlist.requirements.statuses(offerId)
11533
12168
  ]).then(([requirementsByOptionId, statuses]) => {
11534
12169
  if (!isCancelled) {
12170
+ log.debug(() => ({
12171
+ msg: "settled",
12172
+ fields: {
12173
+ state: "CONTENT",
12174
+ options: Object.keys(requirementsByOptionId).length,
12175
+ statuses: statuses.length
12176
+ }
12177
+ }));
11535
12178
  setRequirementsState({
11536
12179
  type: "CONTENT",
11537
12180
  requirements: requirementsByOptionId,
@@ -11541,22 +12184,23 @@ function useRequirements(offerId, options = {}) {
11541
12184
  }).catch((error) => {
11542
12185
  if (!isCancelled) {
11543
12186
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
12187
+ log.failure(
12188
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
12189
+ error
12190
+ );
11544
12191
  setRequirementsState({ type: "ERROR", reason });
11545
12192
  }
11546
12193
  });
11547
12194
  return () => {
11548
12195
  isCancelled = true;
11549
12196
  };
11550
- }, [coinlist, isReady, offerId, fetchKey]);
12197
+ }, [coinlist, isReady, offerId, fetchKey, log]);
11551
12198
  return { requirementsState, refetch };
11552
12199
  }
11553
12200
 
11554
12201
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
11555
12202
  var DEFAULT_LABELS = {
11556
12203
  kyc_approved: "KYC Verification",
11557
- identity_verified: "Identity Verification",
11558
- proof_of_address: "Proof of Address",
11559
- source_of_funds: "Source of Funds",
11560
12204
  external_wallet: "External Wallet",
11561
12205
  whitelisted_wallet: "Whitelisted Wallet",
11562
12206
  jurisdiction: "Jurisdiction Check",
@@ -11565,9 +12209,6 @@ var DEFAULT_LABELS = {
11565
12209
  };
11566
12210
  var DEFAULT_DESCRIPTIONS = {
11567
12211
  kyc_approved: "Complete Know Your Customer verification.",
11568
- identity_verified: "Verify your identity.",
11569
- proof_of_address: "Provide proof of your residential address.",
11570
- source_of_funds: "Provide documentation for your source of funds.",
11571
12212
  external_wallet: "Connect an external wallet.",
11572
12213
  whitelisted_wallet: "Connect a whitelisted wallet.",
11573
12214
  jurisdiction: "Confirm your jurisdiction eligibility.",
@@ -11596,21 +12237,22 @@ function useRequirementsChecklistViewModel(options) {
11596
12237
  data,
11597
12238
  identityVerificationOptions
11598
12239
  } = options;
12240
+ const log = useLogger("useRequirementsChecklistViewModel");
11599
12241
  const { coinlist } = useCoinList();
11600
12242
  const { requirementsState, refetch } = useRequirements(offerId, { data });
11601
- const [expandedId, setExpandedId] = (0, import_react40.useState)(null);
11602
- const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react40.useState)(false);
11603
- const [connectWalletOpen, setConnectWalletOpen] = (0, import_react40.useState)(false);
11604
- const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react40.useState)(null);
11605
- const isMountedRef = (0, import_react40.useRef)(true);
11606
- (0, import_react40.useEffect)(() => {
12243
+ const [expandedId, setExpandedId] = (0, import_react41.useState)(null);
12244
+ const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react41.useState)(false);
12245
+ const [connectWalletOpen, setConnectWalletOpen] = (0, import_react41.useState)(false);
12246
+ const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react41.useState)(null);
12247
+ const isMountedRef = (0, import_react41.useRef)(true);
12248
+ (0, import_react41.useEffect)(() => {
11607
12249
  isMountedRef.current = true;
11608
12250
  return () => {
11609
12251
  isMountedRef.current = false;
11610
12252
  };
11611
12253
  }, []);
11612
- const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react40.useState)(false);
11613
- (0, import_react40.useEffect)(() => {
12254
+ const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react41.useState)(false);
12255
+ (0, import_react41.useEffect)(() => {
11614
12256
  if (requirementsState.type === "CONTENT") {
11615
12257
  setHasWalletRequirement(
11616
12258
  (requirementsState.requirements[optionId] ?? []).some(
@@ -11626,14 +12268,14 @@ function useRequirementsChecklistViewModel(options) {
11626
12268
  } = useOptionAddresses(offerId, optionId, {
11627
12269
  enabled: hasWalletRequirement
11628
12270
  });
11629
- const removeWallet = (0, import_react40.useCallback)(
12271
+ const removeWallet = (0, import_react41.useCallback)(
11630
12272
  async (addressId) => {
11631
12273
  await disconnect(OfferOptionAddressId(addressId));
11632
12274
  refetch();
11633
12275
  },
11634
12276
  [disconnect, refetch]
11635
12277
  );
11636
- const awaitVerificationResult = (0, import_react40.useCallback)(
12278
+ const awaitVerificationResult = (0, import_react41.useCallback)(
11637
12279
  (requirementId, statusBeforeSubmit) => {
11638
12280
  void (async () => {
11639
12281
  const deadline = Date.now() + VERIFICATION_POLL_TIMEOUT_MS;
@@ -11647,6 +12289,9 @@ function useRequirementsChecklistViewModel(options) {
11647
12289
  )?.status;
11648
12290
  if (current !== void 0 && current !== statusBeforeSubmit) break;
11649
12291
  } catch (_) {
12292
+ log.debug(() => ({
12293
+ msg: "status poll tick failed; retrying until deadline"
12294
+ }));
11650
12295
  }
11651
12296
  }
11652
12297
  if (isMountedRef.current) {
@@ -11655,13 +12300,13 @@ function useRequirementsChecklistViewModel(options) {
11655
12300
  }
11656
12301
  })();
11657
12302
  },
11658
- [coinlist, offerId, refetch]
12303
+ [coinlist, offerId, refetch, log]
11659
12304
  );
11660
- const requirements = (0, import_react40.useMemo)(
12305
+ const requirements = (0, import_react41.useMemo)(
11661
12306
  () => requirementsState.type === "CONTENT" ? requirementsState.requirements[optionId] ?? [] : [],
11662
12307
  [requirementsState, optionId]
11663
12308
  );
11664
- const statusById = (0, import_react40.useMemo)(() => {
12309
+ const statusById = (0, import_react41.useMemo)(() => {
11665
12310
  if (requirementsState.type !== "CONTENT") {
11666
12311
  return /* @__PURE__ */ new Map();
11667
12312
  }
@@ -11670,7 +12315,7 @@ function useRequirementsChecklistViewModel(options) {
11670
12315
  requirementsState.statuses.filter((s) => ids.has(s.id)).map((s) => [s.id, s])
11671
12316
  );
11672
12317
  }, [requirementsState, requirements]);
11673
- const state = (0, import_react40.useMemo)(() => {
12318
+ const state = (0, import_react41.useMemo)(() => {
11674
12319
  switch (requirementsState.type) {
11675
12320
  case "LOADING":
11676
12321
  return { type: "loading" };
@@ -11739,7 +12384,7 @@ function useRequirementsChecklistViewModel(options) {
11739
12384
  identityVerificationOptions,
11740
12385
  removeWallet
11741
12386
  ]);
11742
- const handleRequirementAction = (0, import_react40.useCallback)(
12387
+ const handleRequirementAction = (0, import_react41.useCallback)(
11743
12388
  (requirement) => {
11744
12389
  const inlineVerification = statusById.get(requirement.id)?.kycLevel !== void 0 && onRequirementActionOverride === void 0;
11745
12390
  if (inlineVerification) {
@@ -11771,7 +12416,7 @@ function useRequirementsChecklistViewModel(options) {
11771
12416
  coinlist
11772
12417
  ]
11773
12418
  );
11774
- const onEvent = (0, import_react40.useCallback)(
12419
+ const onEvent = (0, import_react41.useCallback)(
11775
12420
  (event) => {
11776
12421
  switch (event.type) {
11777
12422
  case "ON_TOGGLE_ITEM":
@@ -11934,26 +12579,179 @@ function RequirementsChecklistContainer({
11934
12579
  ] });
11935
12580
  }
11936
12581
 
12582
+ // src/client/core/observability/pino-client-logger.ts
12583
+ var import_pino = require("pino");
12584
+
12585
+ // src/shared/core/observability/pino-logger.ts
12586
+ function toPinoRecord(event) {
12587
+ try {
12588
+ const record = {};
12589
+ for (const key of ownKeys(event.fields)) {
12590
+ record[key] = readProperty(event.fields, key, 0, /* @__PURE__ */ new WeakSet());
12591
+ }
12592
+ const cause = "cause" in event ? event.cause : void 0;
12593
+ if (cause !== void 0) {
12594
+ record.cause = sanitize(cause, 0, /* @__PURE__ */ new WeakSet());
12595
+ }
12596
+ return { ...record, scope: event.scope, ...event.bindings };
12597
+ } catch (_) {
12598
+ return { "log.render": "<unrenderable event>" };
12599
+ }
12600
+ }
12601
+ var PINO_LEVEL = {
12602
+ none: "silent",
12603
+ error: "error",
12604
+ warn: "warn",
12605
+ info: "info",
12606
+ debug: "debug"
12607
+ };
12608
+ var MAX_DEPTH = 8;
12609
+ function sanitize(value, depth, seen) {
12610
+ switch (typeof value) {
12611
+ case "string":
12612
+ case "boolean":
12613
+ return value;
12614
+ case "number":
12615
+ return Number.isFinite(value) ? value : String(value);
12616
+ case "bigint":
12617
+ return value.toString();
12618
+ case "undefined":
12619
+ return "<undefined>";
12620
+ case "function":
12621
+ return "<function>";
12622
+ case "symbol":
12623
+ return value.toString();
12624
+ case "object":
12625
+ return value === null ? null : sanitizeObject(value, depth, seen);
12626
+ default:
12627
+ return "<unrenderable>";
12628
+ }
12629
+ }
12630
+ function sanitizeObject(value, depth, seen) {
12631
+ if (seen.has(value)) return "<circular>";
12632
+ if (depth >= MAX_DEPTH) return "<max depth>";
12633
+ if (value instanceof Error) return describeError(value);
12634
+ if (value instanceof Date) return describeDate(value);
12635
+ seen.add(value);
12636
+ try {
12637
+ if (Array.isArray(value)) {
12638
+ return value.map(
12639
+ (_item, index) => readProperty(value, String(index), depth, seen)
12640
+ );
12641
+ }
12642
+ const out = {};
12643
+ for (const key of ownKeys(value)) {
12644
+ out[key] = readProperty(value, key, depth, seen);
12645
+ }
12646
+ return out;
12647
+ } finally {
12648
+ seen.delete(value);
12649
+ }
12650
+ }
12651
+ function readProperty(owner, key, depth, seen) {
12652
+ try {
12653
+ return sanitize(owner[key], depth + 1, seen);
12654
+ } catch (_) {
12655
+ return "<unreadable>";
12656
+ }
12657
+ }
12658
+ function ownKeys(value) {
12659
+ try {
12660
+ return Object.keys(value);
12661
+ } catch (_) {
12662
+ return [];
12663
+ }
12664
+ }
12665
+ function describeError(error) {
12666
+ return {
12667
+ name: safeRead(() => error.name),
12668
+ message: safeRead(() => error.message),
12669
+ stack: safeRead(() => error.stack)
12670
+ };
12671
+ }
12672
+ function describeDate(date) {
12673
+ return safeRead(() => date.toISOString());
12674
+ }
12675
+ function safeRead(read) {
12676
+ try {
12677
+ const value = read();
12678
+ return typeof value === "string" ? value : "<unreadable>";
12679
+ } catch (_) {
12680
+ return "<unreadable>";
12681
+ }
12682
+ }
12683
+ var SDK_LOGGER_NAME = "@coinlist-co/react";
12684
+ function loggerOverPino(sink, level) {
12685
+ return {
12686
+ level: () => level,
12687
+ debug: (event) => emit(sink, "debug", event),
12688
+ info: (event) => emit(sink, "info", event),
12689
+ warn: (event) => emit(sink, "warn", event),
12690
+ error: (event) => emit(sink, "error", event)
12691
+ };
12692
+ }
12693
+ function emit(sink, method, event) {
12694
+ try {
12695
+ const value = event();
12696
+ sink[method](toPinoRecord(value), value.msg);
12697
+ } catch (error) {
12698
+ reportRenderFailure(sink, error);
12699
+ }
12700
+ }
12701
+ function reportRenderFailure(sink, error) {
12702
+ try {
12703
+ sink.error(
12704
+ { "error.type": error instanceof Error ? error.name : typeof error },
12705
+ "log event failed to render"
12706
+ );
12707
+ } catch (_) {
12708
+ }
12709
+ }
12710
+
12711
+ // src/client/core/observability/pino-client-logger.ts
12712
+ function pinoClientLogger(options) {
12713
+ return loggerOverPino(
12714
+ // `name` as a child binding rather than pino's `name` option: the option
12715
+ // is honoured by pino's node build and silently dropped by its browser
12716
+ // build, so a binding is the only spelling that identifies the SDK in
12717
+ // both environments.
12718
+ (0, import_pino.pino)({
12719
+ level: PINO_LEVEL[options.level],
12720
+ browser: { asObject: true }
12721
+ }).child({ name: SDK_LOGGER_NAME }),
12722
+ options.level
12723
+ );
12724
+ }
12725
+
11937
12726
  // src/client/hooks/auth/useCompleteOAuth.ts
11938
- var import_react41 = require("react");
12727
+ var import_react42 = require("react");
11939
12728
  function useCompleteOAuth(options) {
11940
12729
  const { coinlist } = useCoinList();
11941
- const postOAuthCompleteRef = (0, import_react41.useRef)(options.postOAuthComplete);
11942
- const onFailureRef = (0, import_react41.useRef)(options.onFailure);
11943
- const onSuccessRef = (0, import_react41.useRef)(options.onSuccess);
12730
+ const log = useLogger("useCompleteOAuth");
12731
+ const postOAuthCompleteRef = (0, import_react42.useRef)(options.postOAuthComplete);
12732
+ const onFailureRef = (0, import_react42.useRef)(options.onFailure);
12733
+ const onSuccessRef = (0, import_react42.useRef)(options.onSuccess);
11944
12734
  postOAuthCompleteRef.current = options.postOAuthComplete;
11945
12735
  onFailureRef.current = options.onFailure;
11946
12736
  onSuccessRef.current = options.onSuccess;
11947
- const hasStartedExchangeRef = (0, import_react41.useRef)(false);
11948
- (0, import_react41.useEffect)(() => {
12737
+ const hasStartedExchangeRef = (0, import_react42.useRef)(false);
12738
+ (0, import_react42.useEffect)(() => {
11949
12739
  if (typeof window === "undefined") return;
11950
12740
  const params = new URLSearchParams(window.location.search);
11951
12741
  if (!params.has("code") && !params.has("error")) return;
11952
12742
  if (hasStartedExchangeRef.current) return;
11953
12743
  const oauthResult = coinlist.auth.completeOAuth();
11954
12744
  if (oauthResult.type === "error") {
12745
+ log.error(() => ({
12746
+ msg: "oauth callback rejected",
12747
+ fields: { reason: oauthResult.reason }
12748
+ }));
11955
12749
  void Promise.resolve(onFailureRef.current(oauthResult.reason)).catch(
11956
- () => {
12750
+ (error) => {
12751
+ log.failure(
12752
+ () => ({ msg: "the host onFailure handler threw" }),
12753
+ error
12754
+ );
11957
12755
  }
11958
12756
  );
11959
12757
  return;
@@ -11968,15 +12766,27 @@ function useCompleteOAuth(options) {
11968
12766
  });
11969
12767
  if (cancelled) return;
11970
12768
  if (!ok) {
12769
+ log.error(() => ({
12770
+ msg: "the host postOAuthComplete handler reported failure",
12771
+ fields: { reason: "complete_request_failed" }
12772
+ }));
11971
12773
  hasStartedExchangeRef.current = false;
11972
12774
  await onFailureRef.current("complete_request_failed");
11973
12775
  return;
11974
12776
  }
11975
12777
  await coinlist.init();
11976
12778
  if (cancelled) return;
12779
+ log.info(() => ({ msg: "session established" }));
11977
12780
  await onSuccessRef.current();
11978
- } catch {
12781
+ } catch (error) {
11979
12782
  if (cancelled) return;
12783
+ log.failure(
12784
+ () => ({
12785
+ msg: "settled",
12786
+ fields: { state: "ERROR", reason: "complete_request_failed" }
12787
+ }),
12788
+ error
12789
+ );
11980
12790
  hasStartedExchangeRef.current = false;
11981
12791
  await onFailureRef.current("complete_request_failed");
11982
12792
  }
@@ -11985,19 +12795,20 @@ function useCompleteOAuth(options) {
11985
12795
  cancelled = true;
11986
12796
  hasStartedExchangeRef.current = false;
11987
12797
  };
11988
- }, [coinlist]);
12798
+ }, [coinlist, log]);
11989
12799
  }
11990
12800
 
11991
12801
  // src/client/hooks/checkout/coin-list/token-sale/data/useParticipations.ts
11992
- var import_react42 = require("react");
12802
+ var import_react43 = require("react");
11993
12803
  var LOADING_STATE7 = { type: "LOADING" };
11994
12804
  function useParticipations(offerId, options = {}) {
11995
12805
  const { coinlist, isReady } = useCoinList();
12806
+ const log = useLogger("useParticipations");
11996
12807
  const { data } = options;
11997
- const [participationsState, setParticipationsState] = (0, import_react42.useState)(
12808
+ const [participationsState, setParticipationsState] = (0, import_react43.useState)(
11998
12809
  data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE7
11999
12810
  );
12000
- (0, import_react42.useEffect)(() => {
12811
+ (0, import_react43.useEffect)(() => {
12001
12812
  let isCancelled = false;
12002
12813
  if (!isReady) {
12003
12814
  if (data === void 0) {
@@ -12015,31 +12826,40 @@ function useParticipations(offerId, options = {}) {
12015
12826
  setParticipationsState(LOADING_STATE7);
12016
12827
  coinlist.tokenSale.list(offerId).then((participations) => {
12017
12828
  if (!isCancelled) {
12829
+ log.debug(() => ({
12830
+ msg: "settled",
12831
+ fields: { state: "CONTENT", count: participations.length }
12832
+ }));
12018
12833
  setParticipationsState({ type: "CONTENT", participations });
12019
12834
  }
12020
12835
  }).catch((error) => {
12021
12836
  if (!isCancelled) {
12022
12837
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
12838
+ log.failure(
12839
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
12840
+ error
12841
+ );
12023
12842
  setParticipationsState({ type: "ERROR", reason });
12024
12843
  }
12025
12844
  });
12026
12845
  return () => {
12027
12846
  isCancelled = true;
12028
12847
  };
12029
- }, [coinlist, isReady, offerId, data]);
12848
+ }, [coinlist, isReady, offerId, data, log]);
12030
12849
  return { participationsState };
12031
12850
  }
12032
12851
 
12033
12852
  // src/client/hooks/offers/data/useOfferDetails.ts
12034
- var import_react43 = require("react");
12853
+ var import_react44 = require("react");
12035
12854
  var LOADING_STATE8 = { type: "LOADING" };
12036
12855
  function useOfferDetails(offerId, options = {}) {
12037
12856
  const { coinlist, isReady } = useCoinList();
12857
+ const log = useLogger("useOfferDetails");
12038
12858
  const { data } = options;
12039
- const [offerDetailsState, setOfferDetailsState] = (0, import_react43.useState)(
12859
+ const [offerDetailsState, setOfferDetailsState] = (0, import_react44.useState)(
12040
12860
  data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE8
12041
12861
  );
12042
- (0, import_react43.useEffect)(() => {
12862
+ (0, import_react44.useEffect)(() => {
12043
12863
  let isCancelled = false;
12044
12864
  if (!isReady) {
12045
12865
  if (data === void 0) {
@@ -12057,36 +12877,45 @@ function useOfferDetails(offerId, options = {}) {
12057
12877
  setOfferDetailsState(LOADING_STATE8);
12058
12878
  coinlist.offers.get(offerId).then((offerDetail) => {
12059
12879
  if (!isCancelled) {
12880
+ log.debug(() => ({
12881
+ msg: "settled",
12882
+ fields: { state: "CONTENT", offerId: offerDetail.id }
12883
+ }));
12060
12884
  setOfferDetailsState({ type: "CONTENT", offerDetail });
12061
12885
  }
12062
12886
  }).catch((error) => {
12063
12887
  if (!isCancelled) {
12064
12888
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
12889
+ log.failure(
12890
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
12891
+ error
12892
+ );
12065
12893
  setOfferDetailsState({ type: "ERROR", reason });
12066
12894
  }
12067
12895
  });
12068
12896
  return () => {
12069
12897
  isCancelled = true;
12070
12898
  };
12071
- }, [coinlist, isReady, offerId, data]);
12899
+ }, [coinlist, isReady, offerId, data, log]);
12072
12900
  return { offerDetailsState };
12073
12901
  }
12074
12902
 
12075
12903
  // src/client/hooks/tokens/data/useTokenMetadata.ts
12076
- var import_react44 = require("react");
12904
+ var import_react45 = require("react");
12077
12905
  var DISABLED_STATE = { type: "DISABLED" };
12078
12906
  var LOADING_STATE9 = { type: "LOADING" };
12079
12907
  function useTokenMetadata(options) {
12080
12908
  const { chain, address, data, enabled = true } = options;
12081
12909
  const { coinlist, isReady } = useCoinList();
12082
- const [state, setState] = (0, import_react44.useState)(
12910
+ const log = useLogger("useTokenMetadata");
12911
+ const [state, setState] = (0, import_react45.useState)(
12083
12912
  () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE9
12084
12913
  );
12085
- const [refetchCount, setRefetchCount] = (0, import_react44.useState)(0);
12086
- const refetch = (0, import_react44.useCallback)(() => {
12914
+ const [refetchCount, setRefetchCount] = (0, import_react45.useState)(0);
12915
+ const refetch = (0, import_react45.useCallback)(() => {
12087
12916
  setRefetchCount((count) => count + 1);
12088
12917
  }, []);
12089
- (0, import_react44.useEffect)(() => {
12918
+ (0, import_react45.useEffect)(() => {
12090
12919
  let isCancelled = false;
12091
12920
  const seedActive = data !== void 0 && refetchCount === 0;
12092
12921
  if (!isReady || !enabled || seedActive) {
@@ -12097,17 +12926,32 @@ function useTokenMetadata(options) {
12097
12926
  setState(LOADING_STATE9);
12098
12927
  coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
12099
12928
  if (!isCancelled) {
12929
+ log.debug(() => ({
12930
+ msg: "settled",
12931
+ fields: {
12932
+ state: "CONTENT",
12933
+ listed: tokenMetadata !== null,
12934
+ symbol: tokenMetadata?.symbol ?? null
12935
+ }
12936
+ }));
12100
12937
  setState({ type: "CONTENT", tokenMetadata });
12101
12938
  }
12102
- }).catch(() => {
12939
+ }).catch((error) => {
12103
12940
  if (!isCancelled) {
12941
+ log.failure(
12942
+ () => ({
12943
+ msg: "settled",
12944
+ fields: { state: "ERROR", reason: "generic-error" }
12945
+ }),
12946
+ error
12947
+ );
12104
12948
  setState({ type: "ERROR", reason: "generic-error" });
12105
12949
  }
12106
12950
  });
12107
12951
  return () => {
12108
12952
  isCancelled = true;
12109
12953
  };
12110
- }, [coinlist, isReady, enabled, chain, address, data, refetchCount]);
12954
+ }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
12111
12955
  return {
12112
12956
  // LOADING would be a lie while disabled: nothing is in flight and nothing
12113
12957
  // will replace it. Settled states (a seed, a previous answer) survive.
@@ -12155,6 +12999,7 @@ function useTokenMetadata(options) {
12155
12999
  OndoReviewView,
12156
13000
  OndoSidebarView,
12157
13001
  OndoWalletSelectView,
13002
+ RedactedWalletError,
12158
13003
  RequirementItem,
12159
13004
  RequirementItemUi,
12160
13005
  RequirementStatus,
@@ -12187,6 +13032,7 @@ function useTokenMetadata(options) {
12187
13032
  formatMonthYear,
12188
13033
  offerIconUrl,
12189
13034
  ondoLoadErrorReason,
13035
+ pinoClientLogger,
12190
13036
  prepareOndoSwap,
12191
13037
  quoteIsStale,
12192
13038
  quoteOverAsks,