@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
@@ -1,7 +1,10 @@
1
1
  import {
2
2
  AuthenticatedApiClient,
3
- NABU_BASE_URL
4
- } from "../chunk-KDGNDAHA.js";
3
+ NABU_BASE_URL,
4
+ PINO_LEVEL,
5
+ SDK_LOGGER_NAME,
6
+ loggerOverPino
7
+ } from "../chunk-AQIHCFW4.js";
5
8
  import {
6
9
  AuthorizationCode,
7
10
  CodeVerifier,
@@ -13,6 +16,7 @@ import {
13
16
  ONDO_QUOTE_EXPIRY_THRESHOLD_MS,
14
17
  ONDO_SUPPORTED_INPUT_ASSETS,
15
18
  OffersNamespaceImpl,
19
+ RedactedWalletError,
16
20
  SLIPPAGE_OPTIONS_BPS,
17
21
  SUPERSTATE_ISSUER_NAME,
18
22
  SUPERSTATE_SUPPORTED_INPUT_ASSETS,
@@ -30,7 +34,7 @@ import {
30
34
  isStopped,
31
35
  ondoSwapContractAddress,
32
36
  superstateSwapContractAddress
33
- } from "../chunk-B2HCVPCQ.js";
37
+ } from "../chunk-5KYO7OOX.js";
34
38
  import {
35
39
  API_VERSION,
36
40
  AssetDecimals,
@@ -60,31 +64,30 @@ import {
60
64
  TokensNamespaceImpl,
61
65
  VERIFY_IDENTITY_ACCREDITATION_PATH,
62
66
  VERIFY_IDENTITY_PATH,
63
- VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH,
64
- VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH,
65
- VERIFY_IDENTITY_VERIFIED_PATH,
66
67
  WALLET_PATH,
67
68
  WalletAddress,
68
69
  WalletsNamespaceImpl,
69
70
  apiErrorCode,
70
71
  assetAmount,
72
+ describeErrorUnredacted,
71
73
  formatAmount,
72
74
  formatBpsAsPercent,
73
75
  formatRawAmount,
74
76
  formattedUsdPrice,
75
77
  getNetworkName,
76
78
  getUUIDv4,
79
+ internalLogger,
77
80
  parseBlockchainAmount,
78
81
  shortenAddress,
79
82
  txExplorerUrl,
80
83
  usdAmount
81
- } from "../chunk-UIIXXLA7.js";
84
+ } from "../chunk-ZVB6KWZ2.js";
82
85
 
83
86
  // src/client/CoinListProvider.tsx
84
87
  import {
85
- createContext as createContext2,
88
+ createContext as createContext3,
86
89
  useEffect,
87
- useMemo,
90
+ useMemo as useMemo2,
88
91
  useState
89
92
  } from "react";
90
93
 
@@ -125,10 +128,13 @@ function generateUserAgent() {
125
128
 
126
129
  // src/client/core/api/api-client.ts
127
130
  var ApiClient = class {
128
- constructor(config, fetchAccessToken) {
129
- this.client = new AuthenticatedApiClient(config, fetchAccessToken, [
130
- userAgentMiddleware
131
- ]);
131
+ constructor(config, fetchAccessToken, logger = null) {
132
+ this.client = new AuthenticatedApiClient(
133
+ config,
134
+ fetchAccessToken,
135
+ [userAgentMiddleware],
136
+ logger
137
+ );
132
138
  }
133
139
  async send(request) {
134
140
  return this.client.send(request);
@@ -142,11 +148,15 @@ var ClientAuthNamespaceImpl = class {
142
148
  constructor(config, session) {
143
149
  this.config = config;
144
150
  this.session = session;
151
+ this.log = internalLogger(config.logger ?? null, "AUTH");
145
152
  }
146
153
  getState() {
147
154
  return this.session.getState();
148
155
  }
149
156
  async startOAuth() {
157
+ return this.log.wrap("startOAuth", void 0, () => this.redirectToOAuth());
158
+ }
159
+ async redirectToOAuth() {
150
160
  const pkceParams = await generatePKCEParams(this.config);
151
161
  sessionStorage.setItem(OAUTH_STATE_KEY, pkceParams.state);
152
162
  sessionStorage.setItem(OAUTH_CODE_VERIFIER_KEY, pkceParams.codeVerifier);
@@ -159,9 +169,37 @@ var ClientAuthNamespaceImpl = class {
159
169
  state: pkceParams.state
160
170
  });
161
171
  const baseUrl = this.config.coinlistBaseUrl ?? COINLIST_BASE_URL;
172
+ this.log.child({ op: "startOAuth" }).info(() => ({ msg: "redirecting to CoinList", fields: { baseUrl } }));
162
173
  window.location.href = `${baseUrl}${OAUTH_PAGE_PATH}?${params.toString()}`;
163
174
  }
175
+ /**
176
+ * Every failure here is silent from the browser's side - a state mismatch
177
+ * and a missing verifier both just leave the user logged out - so the
178
+ * reason is logged rather than left for the host to infer from a callback.
179
+ */
164
180
  completeOAuth() {
181
+ const result = this.readOauthCallback();
182
+ switch (result.type) {
183
+ case "error":
184
+ this.log.child({ op: "completeOAuth" }).error(() => ({
185
+ msg: "oauth callback rejected",
186
+ fields: { reason: result.reason }
187
+ }));
188
+ return result;
189
+ case "ok":
190
+ this.log.child({ op: "completeOAuth" }).info(() => ({ msg: "authorization code received" }));
191
+ return result;
192
+ default: {
193
+ const _exhaustive = result;
194
+ return result;
195
+ }
196
+ }
197
+ }
198
+ logout() {
199
+ this.log.child({ op: "logout" }).info(() => ({ msg: "access token cleared" }));
200
+ this.session.clearAccessToken();
201
+ }
202
+ readOauthCallback() {
165
203
  const params = new URLSearchParams(window.location.search);
166
204
  const coinlistError = params.get("error");
167
205
  if (coinlistError) {
@@ -189,33 +227,42 @@ var ClientAuthNamespaceImpl = class {
189
227
  codeVerifier: CodeVerifier(codeVerifierValue)
190
228
  };
191
229
  }
192
- logout() {
193
- this.session.clearAccessToken();
194
- }
195
230
  };
196
231
 
197
232
  // src/client/core/blockchain/wallet-error.ts
198
233
  import {
234
+ BaseError,
199
235
  ContractFunctionRevertedError,
200
236
  InsufficientFundsError,
201
237
  UserRejectedRequestError,
202
238
  WaitForTransactionReceiptTimeoutError
203
239
  } from "viem";
204
240
  function classifyWalletError(error, ctx) {
205
- if (error instanceof UserRejectedRequestError) {
241
+ if (causeOf(error, UserRejectedRequestError)) {
206
242
  return { type: "user_rejected" };
207
243
  }
208
- if (error instanceof InsufficientFundsError) {
244
+ if (causeOf(error, InsufficientFundsError)) {
209
245
  return { type: "insufficient_funds" };
210
246
  }
211
- if (error instanceof ContractFunctionRevertedError) {
212
- return { type: "contract_reverted", reason: error.reason ?? error.message };
247
+ const reverted = causeOf(error, ContractFunctionRevertedError);
248
+ if (reverted) {
249
+ return { type: "contract_reverted", reason: revertReason(reverted) };
213
250
  }
214
- if (error instanceof WaitForTransactionReceiptTimeoutError && ctx?.hash) {
251
+ if (causeOf(error, WaitForTransactionReceiptTimeoutError) && ctx?.hash) {
215
252
  return { type: "timeout", hash: ctx.hash };
216
253
  }
217
254
  return { type: "unknown", cause: error };
218
255
  }
256
+ function causeOf(error, errorClass) {
257
+ if (error instanceof errorClass) return error;
258
+ if (!(error instanceof BaseError)) return null;
259
+ const found = error.walk((cause) => cause instanceof errorClass);
260
+ return found instanceof errorClass ? found : null;
261
+ }
262
+ function revertReason(error) {
263
+ if (!error.raw || error.raw === "0x") return null;
264
+ return error.reason ?? error.data?.errorName ?? error.signature ?? null;
265
+ }
219
266
 
220
267
  // src/client/core/blockchain/erc20/approval.ts
221
268
  async function ensureErc20Allowance({
@@ -394,6 +441,72 @@ async function executeTokenSale(params) {
394
441
  return { type: "success", participation, approvalTxHash };
395
442
  }
396
443
 
444
+ // src/client/core/observability/flow-logging.ts
445
+ async function withFlowLogging(log, flow, onProgress, run) {
446
+ const flowLog = log.child({ flow });
447
+ flowLog.info(() => ({ msg: "flow started" }));
448
+ try {
449
+ const result = await run((phase) => {
450
+ flowLog.info(() => ({ msg: "flow advanced", fields: { phase } }));
451
+ onProgress?.(phase);
452
+ });
453
+ logOutcome(flowLog, result);
454
+ return result;
455
+ } catch (error) {
456
+ flowLog.failure(
457
+ () => ({ msg: "flow threw instead of returning a step" }),
458
+ error
459
+ );
460
+ throw error;
461
+ }
462
+ }
463
+ function logOutcome(log, outcome) {
464
+ switch (outcome.type) {
465
+ case "success":
466
+ log.info(() => ({ msg: "flow succeeded" }));
467
+ return;
468
+ case "error":
469
+ log.debug(() => ({
470
+ msg: "flow failed",
471
+ fields: {
472
+ step: outcome.error.step,
473
+ error: describeErrorUnredacted(outcome.error.cause)
474
+ }
475
+ }));
476
+ log.error(() => ({
477
+ msg: "flow failed",
478
+ fields: { step: outcome.error.step },
479
+ ...walletCause(outcome.error.cause)
480
+ }));
481
+ return;
482
+ default: {
483
+ const _exhaustive = outcome;
484
+ return;
485
+ }
486
+ }
487
+ }
488
+ function walletCause(cause) {
489
+ if (!isWalletError(cause)) return {};
490
+ return {
491
+ cause: {
492
+ type: "wallet",
493
+ error: RedactedWalletError.fromWalletError(cause)
494
+ }
495
+ };
496
+ }
497
+ var WALLET_ERROR_TYPES = /* @__PURE__ */ new Set([
498
+ "user_rejected",
499
+ "insufficient_funds",
500
+ "contract_reverted",
501
+ "timeout",
502
+ "unknown"
503
+ ]);
504
+ function isWalletError(value) {
505
+ if (typeof value !== "object" || value === null) return false;
506
+ const type = value.type;
507
+ return typeof type === "string" && WALLET_ERROR_TYPES.has(type);
508
+ }
509
+
397
510
  // src/client/core/checkout/coin-list/client-token-sale-namespace.ts
398
511
  var ClientCoinListTokenSaleNamespaceImpl = class extends CoinListTokenSaleNamespaceImpl {
399
512
  constructor(ctx, erc20) {
@@ -401,7 +514,17 @@ var ClientCoinListTokenSaleNamespaceImpl = class extends CoinListTokenSaleNamesp
401
514
  this.erc20 = erc20;
402
515
  }
403
516
  execute(params) {
404
- return executeTokenSale({ ...params, erc20: this.erc20, tokenSale: this });
517
+ return withFlowLogging(
518
+ this.log,
519
+ "execute",
520
+ params.onProgress,
521
+ (onProgress) => executeTokenSale({
522
+ ...params,
523
+ onProgress,
524
+ erc20: this.erc20,
525
+ tokenSale: this
526
+ })
527
+ );
405
528
  }
406
529
  };
407
530
 
@@ -515,10 +638,25 @@ var ClientOndoNamespaceImpl = class extends OndoNamespaceImpl {
515
638
  this.erc20 = erc20;
516
639
  }
517
640
  prepareSwap(params) {
518
- return prepareOndoSwap({ ...params, ondo: this, erc20: this.erc20 });
641
+ return withFlowLogging(
642
+ this.log,
643
+ "prepareSwap",
644
+ params.onProgress,
645
+ (onProgress) => prepareOndoSwap({
646
+ ...params,
647
+ onProgress,
648
+ ondo: this,
649
+ erc20: this.erc20
650
+ })
651
+ );
519
652
  }
520
653
  executeSwap(params) {
521
- return executeOndoSwap(params);
654
+ return withFlowLogging(
655
+ this.log,
656
+ "executeSwap",
657
+ params.onProgress,
658
+ (onProgress) => executeOndoSwap({ ...params, onProgress })
659
+ );
522
660
  }
523
661
  };
524
662
 
@@ -711,10 +849,25 @@ var ClientSuperstateSwapNamespaceImpl = class extends SuperstateSwapNamespaceImp
711
849
  this.wallets = wallets;
712
850
  }
713
851
  execute(params) {
714
- return executeSwap({ ...params, swap: this, erc20: this.erc20 });
852
+ return withFlowLogging(
853
+ this.log,
854
+ "execute",
855
+ params.onProgress,
856
+ (onProgress) => executeSwap({ ...params, onProgress, swap: this, erc20: this.erc20 })
857
+ );
715
858
  }
716
859
  authorizeWallet(params) {
717
- return authorizeWallet({ ...params, swap: this, wallets: this.wallets });
860
+ return withFlowLogging(
861
+ this.log,
862
+ "authorizeWallet",
863
+ params.onProgress,
864
+ (onProgress) => authorizeWallet({
865
+ ...params,
866
+ onProgress,
867
+ swap: this,
868
+ wallets: this.wallets
869
+ })
870
+ );
718
871
  }
719
872
  };
720
873
 
@@ -740,12 +893,6 @@ function requirementPath(requirement) {
740
893
  switch (requirement.type) {
741
894
  case "kyc_approved":
742
895
  return VERIFY_IDENTITY_PATH;
743
- case "identity_verified":
744
- return VERIFY_IDENTITY_VERIFIED_PATH;
745
- case "proof_of_address":
746
- return VERIFY_IDENTITY_PROOF_OF_ADDRESS_PATH;
747
- case "source_of_funds":
748
- return VERIFY_IDENTITY_SOURCE_OF_FUNDS_PATH;
749
896
  case "accreditation":
750
897
  return VERIFY_IDENTITY_ACCREDITATION_PATH;
751
898
  case "external_wallet":
@@ -770,7 +917,14 @@ function requirementPath(requirement) {
770
917
 
771
918
  // src/client/core/support/client-support-namespace.ts
772
919
  var ClientSupportNamespaceImpl = class {
920
+ constructor(logger = null) {
921
+ this.log = internalLogger(logger, "SUPPORT");
922
+ }
773
923
  contact() {
924
+ this.log.child({ op: "contact" }).info(() => ({
925
+ msg: "opening the support ticket page",
926
+ fields: { supportUrl: SUPPORT_NEW_TICKET_URL }
927
+ }));
774
928
  openInNewTab(SUPPORT_NEW_TICKET_URL);
775
929
  }
776
930
  };
@@ -781,15 +935,18 @@ var CoinListClientImpl = class {
781
935
  this._config = _config;
782
936
  /** Cached access token: undefined = loading, null = no token, AccessToken = logged in */
783
937
  this._accessToken = void 0;
938
+ const logger = _config.logger ?? null;
784
939
  this.api = new ApiClient(
785
940
  {
786
941
  baseUrl: _config.baseUrl || PUBLIC_API_BASE_URL,
787
942
  xApiVersion: API_VERSION
788
943
  },
789
- this.fetchAccessToken.bind(this)
944
+ this.fetchAccessToken.bind(this),
945
+ logger
790
946
  );
791
947
  const ctx = {
792
948
  api: this.api,
949
+ logger,
793
950
  ensureUserAuthenticated: async () => this.ensureAuthenticated()
794
951
  };
795
952
  this.auth = new ClientAuthNamespaceImpl(_config, {
@@ -813,9 +970,10 @@ var CoinListClientImpl = class {
813
970
  );
814
971
  this.ondo = new ClientOndoNamespaceImpl(ctx, this.erc20);
815
972
  this.tokens = new TokensNamespaceImpl(
816
- _config.tokensBaseUrl ?? NABU_BASE_URL
973
+ _config.tokensBaseUrl ?? NABU_BASE_URL,
974
+ logger
817
975
  );
818
- this.support = new ClientSupportNamespaceImpl();
976
+ this.support = new ClientSupportNamespaceImpl(logger);
819
977
  }
820
978
  async init() {
821
979
  await this.fetchAccessToken(true);
@@ -856,16 +1014,27 @@ function useLocale() {
856
1014
  return useContext(CoinListLocaleContext);
857
1015
  }
858
1016
 
1017
+ // src/client/hooks/shared/useLogger.ts
1018
+ import { createContext as createContext2, useContext as useContext2, useMemo } from "react";
1019
+ var CoinListLoggerContext = createContext2(null);
1020
+ function useLogger(hook) {
1021
+ const logger = useContext2(CoinListLoggerContext);
1022
+ return useMemo(
1023
+ () => internalLogger(logger, "HOOKS").child({ hook }),
1024
+ [logger, hook]
1025
+ );
1026
+ }
1027
+
859
1028
  // src/client/CoinListProvider.tsx
860
1029
  import { jsx } from "react/jsx-runtime";
861
- var CoinListContext = createContext2(null);
1030
+ var CoinListContext = createContext3(null);
862
1031
  function CoinListContextProvider({
863
1032
  config,
864
1033
  locale,
865
1034
  children
866
1035
  }) {
867
1036
  const [isReady, setIsReady] = useState(false);
868
- const coinlist = useMemo(() => createCoinListClient(config), [config]);
1037
+ const coinlist = useMemo2(() => createCoinListClient(config), [config]);
869
1038
  useEffect(() => {
870
1039
  let isCancelled = false;
871
1040
  if (coinlist.auth.getState() === "unknown") {
@@ -885,22 +1054,23 @@ function CoinListContextProvider({
885
1054
  isCancelled = true;
886
1055
  };
887
1056
  }, [coinlist]);
888
- const value = useMemo(() => ({ coinlist, isReady }), [coinlist, isReady]);
889
- return /* @__PURE__ */ jsx(CoinListContext.Provider, { value, children: /* @__PURE__ */ jsx(CoinListLocaleContext.Provider, { value: locale ?? DEFAULT_LOCALE, children }) });
1057
+ const value = useMemo2(() => ({ coinlist, isReady }), [coinlist, isReady]);
1058
+ const logger = config.logger ?? null;
1059
+ return /* @__PURE__ */ jsx(CoinListContext.Provider, { value, children: /* @__PURE__ */ jsx(CoinListLocaleContext.Provider, { value: locale ?? DEFAULT_LOCALE, children: /* @__PURE__ */ jsx(CoinListLoggerContext.Provider, { value: logger, children }) }) });
890
1060
  }
891
1061
  var CoinListProvider = CoinListContextProvider;
892
1062
 
893
1063
  // src/client/CoinListStyleScope.tsx
894
- import { createContext as createContext3, useContext as useContext2 } from "react";
1064
+ import { createContext as createContext4, useContext as useContext3 } from "react";
895
1065
 
896
1066
  // src/client/generated/sdk-styles.gen.ts
897
1067
  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}}';
898
1068
 
899
1069
  // src/client/CoinListStyleScope.tsx
900
1070
  import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
901
- var ScopeContext = createContext3(false);
1071
+ var ScopeContext = createContext4(false);
902
1072
  function CoinListStyleScope({ children }) {
903
- const alreadyScoped = useContext2(ScopeContext);
1073
+ const alreadyScoped = useContext3(ScopeContext);
904
1074
  if (alreadyScoped) {
905
1075
  return /* @__PURE__ */ jsx2(Fragment, { children });
906
1076
  }
@@ -1348,12 +1518,12 @@ function CoinListSignInCardView({
1348
1518
  }
1349
1519
 
1350
1520
  // src/client/hooks/auth/useCoinListSignInCardViewModel.ts
1351
- import { useCallback, useMemo as useMemo2 } from "react";
1521
+ import { useCallback, useMemo as useMemo3 } from "react";
1352
1522
 
1353
1523
  // src/client/hooks/useCoinList.ts
1354
- import { useContext as useContext3 } from "react";
1524
+ import { useContext as useContext4 } from "react";
1355
1525
  function useCoinList() {
1356
- const context = useContext3(CoinListContext);
1526
+ const context = useContext4(CoinListContext);
1357
1527
  if (context === null) {
1358
1528
  throw new CoinListClientInitializationError();
1359
1529
  }
@@ -1374,7 +1544,7 @@ var ERROR_MESSAGE = "Error signing in. Please try again.";
1374
1544
  function useCoinListSignInCardViewModel(options = {}) {
1375
1545
  const { status = "idle", onSignIn, onClose } = options;
1376
1546
  const { coinlist } = useCoinList();
1377
- const state = useMemo2(() => {
1547
+ const state = useMemo3(() => {
1378
1548
  const closable = onClose !== void 0;
1379
1549
  return status === "error" ? { type: "error", message: ERROR_MESSAGE, closable } : { type: "idle", closable };
1380
1550
  }, [status, onClose]);
@@ -1436,12 +1606,13 @@ function CheckoutAmountInput({
1436
1606
  invalid = false,
1437
1607
  disabled = false,
1438
1608
  prefix,
1439
- suffix,
1609
+ prefixTone = "primary",
1440
1610
  action,
1441
1611
  className
1442
1612
  }) {
1443
1613
  const inputId = useId();
1444
1614
  const toneClass = invalid ? "clcosdk:text-error" : "clcosdk:text-text-primary";
1615
+ const prefixToneClass = prefixTone === "muted" ? "clcosdk:text-text-secondary" : toneClass;
1445
1616
  return /* @__PURE__ */ jsx12(CoinListStyleScope, { children: /* @__PURE__ */ jsxs8(
1446
1617
  "div",
1447
1618
  {
@@ -1471,7 +1642,7 @@ function CheckoutAmountInput({
1471
1642
  className: cn(
1472
1643
  typeClasses.h4,
1473
1644
  "clcosdk:shrink-0 clcosdk:font-medium",
1474
- toneClass
1645
+ prefixToneClass
1475
1646
  ),
1476
1647
  children: prefix
1477
1648
  }
@@ -1495,16 +1666,6 @@ function CheckoutAmountInput({
1495
1666
  toneClass
1496
1667
  )
1497
1668
  }
1498
- ),
1499
- suffix && /* @__PURE__ */ jsx12(
1500
- "span",
1501
- {
1502
- className: cn(
1503
- typeClasses.h4,
1504
- "clcosdk:shrink-0 clcosdk:font-medium clcosdk:text-text-secondary"
1505
- ),
1506
- children: suffix
1507
- }
1508
1669
  )
1509
1670
  ] }),
1510
1671
  action
@@ -1864,7 +2025,8 @@ function ActiveView({
1864
2025
  placeholder: AMOUNT_PLACEHOLDER,
1865
2026
  invalid: state.error !== null,
1866
2027
  disabled: isLoading,
1867
- suffix: selectedAsset?.symbol,
2028
+ prefix: selectedAsset?.symbol,
2029
+ prefixTone: "muted",
1868
2030
  action: selectedAsset && /* @__PURE__ */ jsx18(
1869
2031
  MaxButton,
1870
2032
  {
@@ -2499,7 +2661,8 @@ function ActiveView2({
2499
2661
  }
2500
2662
  )
2501
2663
  ] }),
2502
- state.error ? /* @__PURE__ */ jsx27(QuoteLine, { tone: "error", children: state.error }) : /* @__PURE__ */ jsx27(QuoteStatusLine, { quote: state.quote, onEvent }),
2664
+ state.error !== null && /* @__PURE__ */ jsx27(QuoteLine, { tone: "error", children: state.error }),
2665
+ /* @__PURE__ */ jsx27(QuoteStatusLine, { quote: state.quote, onEvent }),
2503
2666
  /* @__PURE__ */ jsx27(
2504
2667
  ClButton,
2505
2668
  {
@@ -4919,6 +5082,7 @@ function ondoLoadErrorReason(error) {
4919
5082
  function useOndoSwapTransaction(options) {
4920
5083
  const { request, data, enabled } = options;
4921
5084
  const { coinlist, isReady } = useCoinList();
5085
+ const log = useLogger("useOndoSwapTransaction");
4922
5086
  const [state, setState] = useState5(
4923
5087
  () => data === void 0 ? { type: "LOADING" } : {
4924
5088
  type: "CONTENT",
@@ -4944,6 +5108,10 @@ function useOndoSwapTransaction(options) {
4944
5108
  try {
4945
5109
  const transaction = await coinlist.ondo.buildSwapTransaction(params);
4946
5110
  if (currentFetchId !== fetchIdRef.current) return;
5111
+ log.debug(() => ({
5112
+ msg: "settled",
5113
+ fields: { state: "CONTENT" }
5114
+ }));
4947
5115
  setState({
4948
5116
  type: "CONTENT",
4949
5117
  transaction,
@@ -4953,13 +5121,17 @@ function useOndoSwapTransaction(options) {
4953
5121
  } catch (error) {
4954
5122
  if (currentFetchId !== fetchIdRef.current) return;
4955
5123
  const reason = ondoLoadErrorReason(error);
5124
+ log.failure(
5125
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
5126
+ error
5127
+ );
4956
5128
  setState(
4957
5129
  (previous) => previous.type === "CONTENT" ? { ...previous, isRefreshing: false, refreshError: reason } : { type: "ERROR", reason }
4958
5130
  );
4959
5131
  } finally {
4960
5132
  isFetchingRef.current = false;
4961
5133
  }
4962
- }, [coinlist, isReady, enabled]);
5134
+ }, [coinlist, isReady, enabled, log]);
4963
5135
  useEffect5(() => {
4964
5136
  if (data === void 0) return;
4965
5137
  ++fetchIdRef.current;
@@ -5297,6 +5469,7 @@ function useOndoWalletSelectViewModel({
5297
5469
  onComplete,
5298
5470
  onEdit
5299
5471
  }) {
5472
+ const log = useLogger("useOndoWalletSelectViewModel");
5300
5473
  const [selected, setSelected] = useState7(null);
5301
5474
  const [error, setError] = useState7(null);
5302
5475
  const networkName = getNetworkName(chain);
@@ -5341,7 +5514,11 @@ function useOndoWalletSelectViewModel({
5341
5514
  setError(null);
5342
5515
  try {
5343
5516
  await wallets.connectExternal();
5344
- } catch {
5517
+ } catch (error2) {
5518
+ log.failure(
5519
+ () => ({ msg: "the host connectExternal handler threw" }),
5520
+ error2
5521
+ );
5345
5522
  setError(CONNECT_FAILED);
5346
5523
  return;
5347
5524
  }
@@ -5436,11 +5613,13 @@ function useOndoPrice(options) {
5436
5613
  enabled
5437
5614
  } = options;
5438
5615
  const { coinlist, isReady } = useCoinList();
5616
+ const log = useLogger("useOndoPrice");
5439
5617
  const [state, setState] = useState8(
5440
5618
  () => data === void 0 ? LOADING : { type: "CONTENT", quote: data, isRefreshing: false }
5441
5619
  );
5442
5620
  const fetchIdRef = useRef5(0);
5443
5621
  const isFetchingRef = useRef5(false);
5622
+ const hasQuoteRef = useRef5(data !== void 0);
5444
5623
  const sizeKey = quoteSizeKey(size);
5445
5624
  useEffect8(() => {
5446
5625
  if (!isReady || !enabled) return;
@@ -5456,11 +5635,31 @@ function useOndoPrice(options) {
5456
5635
  try {
5457
5636
  const quote = await coinlist.ondo.getQuote({ symbol, side, ...size2 });
5458
5637
  if (currentFetchId !== fetchIdRef.current) return;
5638
+ log.debug(() => ({
5639
+ msg: "settled",
5640
+ fields: { state: "CONTENT" }
5641
+ }));
5642
+ hasQuoteRef.current = true;
5459
5643
  setState({ type: "CONTENT", quote, isRefreshing: false });
5460
5644
  } catch (error) {
5461
5645
  if (currentFetchId !== fetchIdRef.current) return;
5646
+ const reason = ondoLoadErrorReason(error);
5647
+ if (hasQuoteRef.current) {
5648
+ log.warning(
5649
+ () => ({
5650
+ msg: "poll failed; keeping the last quote",
5651
+ fields: { reason }
5652
+ }),
5653
+ error
5654
+ );
5655
+ } else {
5656
+ log.failure(
5657
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
5658
+ error
5659
+ );
5660
+ }
5462
5661
  setState(
5463
- (previous) => previous.type === "CONTENT" ? { ...previous, isRefreshing: false } : { type: "ERROR", reason: ondoLoadErrorReason(error) }
5662
+ (previous) => previous.type === "CONTENT" ? { ...previous, isRefreshing: false } : { type: "ERROR", reason }
5464
5663
  );
5465
5664
  } finally {
5466
5665
  if (currentFetchId === fetchIdRef.current) {
@@ -5474,7 +5673,7 @@ function useOndoPrice(options) {
5474
5673
  clearInterval(interval);
5475
5674
  ++fetchIdRef.current;
5476
5675
  };
5477
- }, [coinlist, isReady, enabled, symbol, side, sizeKey, pollIntervalMs]);
5676
+ }, [coinlist, isReady, enabled, symbol, side, sizeKey, pollIntervalMs, log]);
5478
5677
  return { state };
5479
5678
  }
5480
5679
  function quoteSizeKey(size) {
@@ -5506,11 +5705,13 @@ function useOndoTradingStatus(options) {
5506
5705
  enabled
5507
5706
  } = options;
5508
5707
  const { coinlist, isReady } = useCoinList();
5708
+ const log = useLogger("useOndoTradingStatus");
5509
5709
  const [state, setState] = useState9(
5510
5710
  () => data === void 0 ? LOADING2 : { type: "CONTENT", status: data }
5511
5711
  );
5512
5712
  const fetchIdRef = useRef6(0);
5513
5713
  const isFetchingRef = useRef6(false);
5714
+ const hasStatusRef = useRef6(data !== void 0);
5514
5715
  useEffect9(() => {
5515
5716
  if (!isReady || !enabled) return;
5516
5717
  const currentFetchId = ++fetchIdRef.current;
@@ -5521,11 +5722,31 @@ function useOndoTradingStatus(options) {
5521
5722
  try {
5522
5723
  const status = await coinlist.ondo.getTradingStatus({ symbol, side });
5523
5724
  if (currentFetchId !== fetchIdRef.current) return;
5725
+ log.debug(() => ({
5726
+ msg: "settled",
5727
+ fields: { state: "CONTENT", status: status.type }
5728
+ }));
5729
+ hasStatusRef.current = true;
5524
5730
  setState({ type: "CONTENT", status });
5525
5731
  } catch (error) {
5526
5732
  if (currentFetchId !== fetchIdRef.current) return;
5733
+ const reason = ondoLoadErrorReason(error);
5734
+ if (hasStatusRef.current) {
5735
+ log.warning(
5736
+ () => ({
5737
+ msg: "poll failed; keeping the last status",
5738
+ fields: { reason }
5739
+ }),
5740
+ error
5741
+ );
5742
+ } else {
5743
+ log.failure(
5744
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
5745
+ error
5746
+ );
5747
+ }
5527
5748
  setState(
5528
- (previous) => previous.type === "CONTENT" ? previous : { type: "ERROR", reason: ondoLoadErrorReason(error) }
5749
+ (previous) => previous.type === "CONTENT" ? previous : { type: "ERROR", reason }
5529
5750
  );
5530
5751
  } finally {
5531
5752
  if (currentFetchId === fetchIdRef.current) {
@@ -5539,7 +5760,7 @@ function useOndoTradingStatus(options) {
5539
5760
  clearInterval(interval);
5540
5761
  ++fetchIdRef.current;
5541
5762
  };
5542
- }, [coinlist, isReady, enabled, symbol, side, pollIntervalMs]);
5763
+ }, [coinlist, isReady, enabled, symbol, side, pollIntervalMs, log]);
5543
5764
  return { state };
5544
5765
  }
5545
5766
 
@@ -5951,6 +6172,7 @@ var LOADING_STATE = { type: "LOADING" };
5951
6172
  function useSwapOutputToken(options) {
5952
6173
  const { contractAddress, chain, enabled } = options;
5953
6174
  const { coinlist, isReady } = useCoinList();
6175
+ const log = useLogger("useSwapOutputToken");
5954
6176
  const [outputTokenState, setOutputTokenState] = useState12(LOADING_STATE);
5955
6177
  const [retryCount, setRetryCount] = useState12(0);
5956
6178
  const fetchIdRef = useRef7(0);
@@ -5968,9 +6190,17 @@ function useSwapOutputToken(options) {
5968
6190
  chain
5969
6191
  });
5970
6192
  if (currentFetchId !== fetchIdRef.current) return;
6193
+ log.debug(() => ({
6194
+ msg: "settled",
6195
+ fields: { state: "CONTENT", symbol: outputToken.symbol }
6196
+ }));
5971
6197
  setOutputTokenState({ type: "CONTENT", outputToken });
5972
- } catch {
6198
+ } catch (error) {
5973
6199
  if (currentFetchId !== fetchIdRef.current) return;
6200
+ log.failure(
6201
+ () => ({ msg: "settled", fields: { state: "ERROR" } }),
6202
+ error
6203
+ );
5974
6204
  setOutputTokenState({ type: "ERROR" });
5975
6205
  }
5976
6206
  };
@@ -5978,7 +6208,7 @@ function useSwapOutputToken(options) {
5978
6208
  return () => {
5979
6209
  ++fetchIdRef.current;
5980
6210
  };
5981
- }, [coinlist, isReady, contractAddress, chain, enabled, retryCount]);
6211
+ }, [coinlist, isReady, contractAddress, chain, enabled, retryCount, log]);
5982
6212
  return { outputTokenState, refetch };
5983
6213
  }
5984
6214
 
@@ -5995,6 +6225,7 @@ function useSwapQuote(options) {
5995
6225
  enabled
5996
6226
  } = options;
5997
6227
  const { coinlist, isReady } = useCoinList();
6228
+ const log = useLogger("useSwapQuote");
5998
6229
  const [quote, setQuote] = useState13(null);
5999
6230
  const [isLoading, setIsLoading] = useState13(true);
6000
6231
  const [isRefreshing, setIsRefreshing] = useState13(false);
@@ -6035,7 +6266,11 @@ function useSwapQuote(options) {
6035
6266
  hasQuoteRef.current = true;
6036
6267
  setIsLoading(false);
6037
6268
  }
6038
- } catch {
6269
+ } catch (error) {
6270
+ log.warning(
6271
+ () => ({ msg: "poll failed; retrying on the next tick" }),
6272
+ error
6273
+ );
6039
6274
  } finally {
6040
6275
  if (currentFetchId === fetchIdRef.current) {
6041
6276
  isFetchingRef.current = false;
@@ -6060,7 +6295,8 @@ function useSwapQuote(options) {
6060
6295
  inputTokenAddress,
6061
6296
  outputTokenDecimals,
6062
6297
  pollIntervalMs,
6063
- enabled
6298
+ enabled,
6299
+ log
6064
6300
  ]);
6065
6301
  return { quote, isLoading, isRefreshing };
6066
6302
  }
@@ -6409,6 +6645,7 @@ function useSuperstateWalletViewModel({
6409
6645
  onEdit
6410
6646
  }) {
6411
6647
  const { coinlist, isReady } = useCoinList();
6648
+ const log = useLogger("useSuperstateWalletViewModel");
6412
6649
  const [selected, setSelected] = useState15(null);
6413
6650
  const [phase, setPhase] = useState15(null);
6414
6651
  const [error, setError] = useState15(null);
@@ -6489,7 +6726,11 @@ function useSuperstateWalletViewModel({
6489
6726
  setError(null);
6490
6727
  try {
6491
6728
  await wallets.connectExternal();
6492
- } catch {
6729
+ } catch (error2) {
6730
+ log.failure(
6731
+ () => ({ msg: "the host connectExternal handler threw" }),
6732
+ error2
6733
+ );
6493
6734
  setError(CONNECT_FAILED2);
6494
6735
  return;
6495
6736
  }
@@ -7186,13 +7427,14 @@ function EmptyState() {
7186
7427
  }
7187
7428
 
7188
7429
  // src/client/hooks/offers/grid/useOffersGridViewModel.ts
7189
- import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
7430
+ import { useCallback as useCallback4, useMemo as useMemo4 } from "react";
7190
7431
 
7191
7432
  // src/client/hooks/offers/data/useOffers.ts
7192
7433
  import { useEffect as useEffect15, useState as useState17 } from "react";
7193
7434
  var LOADING_STATE2 = { type: "LOADING" };
7194
7435
  function useOffers(options = {}) {
7195
7436
  const { coinlist, isReady } = useCoinList();
7437
+ const log = useLogger("useOffers");
7196
7438
  const { data: serverOffers } = options;
7197
7439
  const [offersState, setOffersState] = useState17(
7198
7440
  serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE2
@@ -7215,18 +7457,26 @@ function useOffers(options = {}) {
7215
7457
  setOffersState(LOADING_STATE2);
7216
7458
  coinlist.offers.list().then((offers) => {
7217
7459
  if (!isCancelled) {
7460
+ log.debug(() => ({
7461
+ msg: "settled",
7462
+ fields: { state: "CONTENT", count: offers.length }
7463
+ }));
7218
7464
  setOffersState({ type: "CONTENT", offers });
7219
7465
  }
7220
7466
  }).catch((error) => {
7221
7467
  if (!isCancelled) {
7222
7468
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
7469
+ log.failure(
7470
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
7471
+ error
7472
+ );
7223
7473
  setOffersState({ type: "ERROR", reason });
7224
7474
  }
7225
7475
  });
7226
7476
  return () => {
7227
7477
  isCancelled = true;
7228
7478
  };
7229
- }, [coinlist, isReady, serverOffers]);
7479
+ }, [coinlist, isReady, serverOffers, log]);
7230
7480
  return { offersState };
7231
7481
  }
7232
7482
 
@@ -7258,7 +7508,7 @@ function useOffersGridViewModel(options = {}) {
7258
7508
  const { data, onOfferClick } = options;
7259
7509
  const { offersState } = useOffers({ data });
7260
7510
  const locale = useLocale();
7261
- const state = useMemo3(
7511
+ const state = useMemo4(
7262
7512
  () => toUiState(offersState, locale, onOfferClick !== void 0),
7263
7513
  [offersState, locale, onOfferClick]
7264
7514
  );
@@ -7901,7 +8151,7 @@ function toError(error) {
7901
8151
  }
7902
8152
 
7903
8153
  // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
7904
- import { useCallback as useCallback6, useEffect as useEffect17, useMemo as useMemo4, useRef as useRef10 } from "react";
8154
+ import { useCallback as useCallback6, useEffect as useEffect17, useMemo as useMemo5, useRef as useRef10 } from "react";
7905
8155
 
7906
8156
  // src/client/hooks/requirements/data/useKycToken.ts
7907
8157
  import { useCallback as useCallback5, useEffect as useEffect16, useRef as useRef9, useState as useState19 } from "react";
@@ -7909,6 +8159,7 @@ var IDLE_STATE = { type: "IDLE" };
7909
8159
  var LOADING_STATE3 = { type: "LOADING" };
7910
8160
  function useKycToken(levelName, reset) {
7911
8161
  const { coinlist } = useCoinList();
8162
+ const log = useLogger("useKycToken");
7912
8163
  const [kycTokenState, setKycTokenState] = useState19(IDLE_STATE);
7913
8164
  const resetPendingRef = useRef9(reset === true);
7914
8165
  const tokenIssuedRef = useRef9(false);
@@ -7926,14 +8177,22 @@ function useKycToken(levelName, reset) {
7926
8177
  });
7927
8178
  resetPendingRef.current = false;
7928
8179
  tokenIssuedRef.current = true;
8180
+ log.debug(() => ({
8181
+ msg: "settled",
8182
+ fields: { state: "CONTENT" }
8183
+ }));
7929
8184
  setKycTokenState({ type: "CONTENT", token: kycToken.token });
7930
8185
  return kycToken.token;
7931
8186
  } catch (error) {
7932
8187
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
8188
+ log.failure(
8189
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
8190
+ error
8191
+ );
7933
8192
  setKycTokenState({ type: "ERROR", reason });
7934
8193
  throw error;
7935
8194
  }
7936
- }, [coinlist, levelName]);
8195
+ }, [coinlist, levelName, log]);
7937
8196
  return { kycTokenState, fetchToken };
7938
8197
  }
7939
8198
 
@@ -7952,7 +8211,7 @@ function useIdentityVerificationViewModel(options = {}) {
7952
8211
  fetchToken().catch(() => {
7953
8212
  });
7954
8213
  }, [fetchToken]);
7955
- const state = useMemo4(() => {
8214
+ const state = useMemo5(() => {
7956
8215
  switch (kycTokenState.type) {
7957
8216
  case "IDLE":
7958
8217
  case "LOADING":
@@ -8240,7 +8499,7 @@ function SignOnlyScreen({
8240
8499
  }
8241
8500
 
8242
8501
  // src/client/hooks/requirements/tax-document/useTaxDocumentModalViewModel.ts
8243
- import { useCallback as useCallback8, useEffect as useEffect19, useMemo as useMemo5 } from "react";
8502
+ import { useCallback as useCallback8, useEffect as useEffect19, useMemo as useMemo6 } from "react";
8244
8503
 
8245
8504
  // src/client/hooks/requirements/data/useTaxDocument.ts
8246
8505
  import { useCallback as useCallback7, useEffect as useEffect18, useState as useState20 } from "react";
@@ -8317,6 +8576,7 @@ function useTaxDocument({
8317
8576
  isOpen
8318
8577
  }) {
8319
8578
  const { coinlist, isReady } = useCoinList();
8579
+ const log = useLogger("useTaxDocument");
8320
8580
  const [state, setState] = useState20(LOADING_STATE4);
8321
8581
  useEffect18(() => {
8322
8582
  let isCancelled = false;
@@ -8348,15 +8608,17 @@ function useTaxDocument({
8348
8608
  });
8349
8609
  }).catch((error) => {
8350
8610
  if (isCancelled) return;
8351
- setState({
8352
- type: "ERROR",
8353
- reason: error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error"
8354
- });
8611
+ const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
8612
+ log.failure(
8613
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
8614
+ error
8615
+ );
8616
+ setState({ type: "ERROR", reason });
8355
8617
  });
8356
8618
  return () => {
8357
8619
  isCancelled = true;
8358
8620
  };
8359
- }, [coinlist, isReady, isOpen]);
8621
+ }, [coinlist, isReady, isOpen, log]);
8360
8622
  const onEditField = useCallback7(
8361
8623
  (field, value) => {
8362
8624
  setState(
@@ -8413,12 +8675,13 @@ function useTaxDocument({
8413
8675
  fields: state.type === "REVIEW" ? toSubmissionFields(state.fields, state.addressParts) : {}
8414
8676
  }).then((submission) => {
8415
8677
  setState({ type: "SUBMITTED", submission });
8416
- }).catch(() => {
8678
+ }).catch((error) => {
8679
+ log.failure(() => ({ msg: "signing the tax document failed" }), error);
8417
8680
  setState(
8418
8681
  (prev) => prev.type === "REVIEW" || prev.type === "SIGN_ONLY" ? { ...prev, sign: { type: "idle", error: SIGN_FAILED_MESSAGE } } : prev
8419
8682
  );
8420
8683
  });
8421
- }, [state, coinlist]);
8684
+ }, [state, coinlist, log]);
8422
8685
  return { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign };
8423
8686
  }
8424
8687
 
@@ -8445,7 +8708,7 @@ function useTaxDocumentModalViewModel({
8445
8708
  onClose();
8446
8709
  }
8447
8710
  }, [state]);
8448
- const uiState = useMemo5(() => {
8711
+ const uiState = useMemo6(() => {
8449
8712
  if (!isOpen || state.type === "SUBMITTED") {
8450
8713
  return { type: "hidden" };
8451
8714
  }
@@ -8667,7 +8930,7 @@ function Screen2({
8667
8930
  }
8668
8931
 
8669
8932
  // src/client/hooks/requirements/wallet/useConnectWalletModalViewModel.ts
8670
- import { useCallback as useCallback10, useEffect as useEffect21, useMemo as useMemo6 } from "react";
8933
+ import { useCallback as useCallback10, useEffect as useEffect21, useMemo as useMemo7 } from "react";
8671
8934
 
8672
8935
  // src/client/hooks/requirements/data/useConnectWallet.ts
8673
8936
  import { useCallback as useCallback9, useEffect as useEffect20, useRef as useRef11, useState as useState21 } from "react";
@@ -8886,7 +9149,7 @@ function useConnectWalletModalViewModel({
8886
9149
  onClose();
8887
9150
  }
8888
9151
  }, [state]);
8889
- const uiState = useMemo6(() => {
9152
+ const uiState = useMemo7(() => {
8890
9153
  if (!isOpen || state.type === "CONNECTED") {
8891
9154
  return { type: "hidden" };
8892
9155
  }
@@ -8952,7 +9215,7 @@ function ConnectWalletModalContainer({
8952
9215
  }
8953
9216
 
8954
9217
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
8955
- import { useCallback as useCallback13, useEffect as useEffect24, useMemo as useMemo7, useRef as useRef12, useState as useState24 } from "react";
9218
+ import { useCallback as useCallback13, useEffect as useEffect24, useMemo as useMemo8, useRef as useRef12, useState as useState24 } from "react";
8956
9219
 
8957
9220
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.types.ts
8958
9221
  var RequirementItemUi = {
@@ -9014,6 +9277,7 @@ var EMPTY_STATE = {
9014
9277
  };
9015
9278
  function useOptionAddresses(offerId, offerOptionId, options = {}) {
9016
9279
  const { coinlist, isReady } = useCoinList();
9280
+ const log = useLogger("useOptionAddresses");
9017
9281
  const { data, enabled = true } = options;
9018
9282
  const [addressesState, setAddressesState] = useState22(
9019
9283
  data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE5
@@ -9059,18 +9323,26 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
9059
9323
  setAddressesState(LOADING_STATE5);
9060
9324
  coinlist.wallets.list({ offerId, offerOptionId }).then((addresses) => {
9061
9325
  if (!isCancelled) {
9326
+ log.debug(() => ({
9327
+ msg: "settled",
9328
+ fields: { state: "CONTENT", count: addresses.length }
9329
+ }));
9062
9330
  setAddressesState({ type: "CONTENT", addresses });
9063
9331
  }
9064
9332
  }).catch((error) => {
9065
9333
  if (!isCancelled) {
9066
9334
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
9335
+ log.failure(
9336
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
9337
+ error
9338
+ );
9067
9339
  setAddressesState({ type: "ERROR", reason });
9068
9340
  }
9069
9341
  });
9070
9342
  return () => {
9071
9343
  isCancelled = true;
9072
9344
  };
9073
- }, [coinlist, isReady, enabled, offerId, offerOptionId, fetchKey]);
9345
+ }, [coinlist, isReady, enabled, offerId, offerOptionId, fetchKey, log]);
9074
9346
  return { addressesState, refetch, disconnect };
9075
9347
  }
9076
9348
 
@@ -9079,6 +9351,7 @@ import { useCallback as useCallback12, useEffect as useEffect23, useState as use
9079
9351
  var LOADING_STATE6 = { type: "LOADING" };
9080
9352
  function useRequirements(offerId, options = {}) {
9081
9353
  const { coinlist, isReady } = useCoinList();
9354
+ const log = useLogger("useRequirements");
9082
9355
  const { data } = options;
9083
9356
  const [requirementsState, setRequirementsState] = useState23(
9084
9357
  data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE6
@@ -9112,6 +9385,14 @@ function useRequirements(offerId, options = {}) {
9112
9385
  coinlist.requirements.statuses(offerId)
9113
9386
  ]).then(([requirementsByOptionId, statuses]) => {
9114
9387
  if (!isCancelled) {
9388
+ log.debug(() => ({
9389
+ msg: "settled",
9390
+ fields: {
9391
+ state: "CONTENT",
9392
+ options: Object.keys(requirementsByOptionId).length,
9393
+ statuses: statuses.length
9394
+ }
9395
+ }));
9115
9396
  setRequirementsState({
9116
9397
  type: "CONTENT",
9117
9398
  requirements: requirementsByOptionId,
@@ -9121,22 +9402,23 @@ function useRequirements(offerId, options = {}) {
9121
9402
  }).catch((error) => {
9122
9403
  if (!isCancelled) {
9123
9404
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
9405
+ log.failure(
9406
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
9407
+ error
9408
+ );
9124
9409
  setRequirementsState({ type: "ERROR", reason });
9125
9410
  }
9126
9411
  });
9127
9412
  return () => {
9128
9413
  isCancelled = true;
9129
9414
  };
9130
- }, [coinlist, isReady, offerId, fetchKey]);
9415
+ }, [coinlist, isReady, offerId, fetchKey, log]);
9131
9416
  return { requirementsState, refetch };
9132
9417
  }
9133
9418
 
9134
9419
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
9135
9420
  var DEFAULT_LABELS = {
9136
9421
  kyc_approved: "KYC Verification",
9137
- identity_verified: "Identity Verification",
9138
- proof_of_address: "Proof of Address",
9139
- source_of_funds: "Source of Funds",
9140
9422
  external_wallet: "External Wallet",
9141
9423
  whitelisted_wallet: "Whitelisted Wallet",
9142
9424
  jurisdiction: "Jurisdiction Check",
@@ -9145,9 +9427,6 @@ var DEFAULT_LABELS = {
9145
9427
  };
9146
9428
  var DEFAULT_DESCRIPTIONS = {
9147
9429
  kyc_approved: "Complete Know Your Customer verification.",
9148
- identity_verified: "Verify your identity.",
9149
- proof_of_address: "Provide proof of your residential address.",
9150
- source_of_funds: "Provide documentation for your source of funds.",
9151
9430
  external_wallet: "Connect an external wallet.",
9152
9431
  whitelisted_wallet: "Connect a whitelisted wallet.",
9153
9432
  jurisdiction: "Confirm your jurisdiction eligibility.",
@@ -9176,6 +9455,7 @@ function useRequirementsChecklistViewModel(options) {
9176
9455
  data,
9177
9456
  identityVerificationOptions
9178
9457
  } = options;
9458
+ const log = useLogger("useRequirementsChecklistViewModel");
9179
9459
  const { coinlist } = useCoinList();
9180
9460
  const { requirementsState, refetch } = useRequirements(offerId, { data });
9181
9461
  const [expandedId, setExpandedId] = useState24(null);
@@ -9227,6 +9507,9 @@ function useRequirementsChecklistViewModel(options) {
9227
9507
  )?.status;
9228
9508
  if (current !== void 0 && current !== statusBeforeSubmit) break;
9229
9509
  } catch (_) {
9510
+ log.debug(() => ({
9511
+ msg: "status poll tick failed; retrying until deadline"
9512
+ }));
9230
9513
  }
9231
9514
  }
9232
9515
  if (isMountedRef.current) {
@@ -9235,13 +9518,13 @@ function useRequirementsChecklistViewModel(options) {
9235
9518
  }
9236
9519
  })();
9237
9520
  },
9238
- [coinlist, offerId, refetch]
9521
+ [coinlist, offerId, refetch, log]
9239
9522
  );
9240
- const requirements = useMemo7(
9523
+ const requirements = useMemo8(
9241
9524
  () => requirementsState.type === "CONTENT" ? requirementsState.requirements[optionId] ?? [] : [],
9242
9525
  [requirementsState, optionId]
9243
9526
  );
9244
- const statusById = useMemo7(() => {
9527
+ const statusById = useMemo8(() => {
9245
9528
  if (requirementsState.type !== "CONTENT") {
9246
9529
  return /* @__PURE__ */ new Map();
9247
9530
  }
@@ -9250,7 +9533,7 @@ function useRequirementsChecklistViewModel(options) {
9250
9533
  requirementsState.statuses.filter((s) => ids.has(s.id)).map((s) => [s.id, s])
9251
9534
  );
9252
9535
  }, [requirementsState, requirements]);
9253
- const state = useMemo7(() => {
9536
+ const state = useMemo8(() => {
9254
9537
  switch (requirementsState.type) {
9255
9538
  case "LOADING":
9256
9539
  return { type: "loading" };
@@ -9514,10 +9797,27 @@ function RequirementsChecklistContainer({
9514
9797
  ] });
9515
9798
  }
9516
9799
 
9800
+ // src/client/core/observability/pino-client-logger.ts
9801
+ import { pino } from "pino";
9802
+ function pinoClientLogger(options) {
9803
+ return loggerOverPino(
9804
+ // `name` as a child binding rather than pino's `name` option: the option
9805
+ // is honoured by pino's node build and silently dropped by its browser
9806
+ // build, so a binding is the only spelling that identifies the SDK in
9807
+ // both environments.
9808
+ pino({
9809
+ level: PINO_LEVEL[options.level],
9810
+ browser: { asObject: true }
9811
+ }).child({ name: SDK_LOGGER_NAME }),
9812
+ options.level
9813
+ );
9814
+ }
9815
+
9517
9816
  // src/client/hooks/auth/useCompleteOAuth.ts
9518
9817
  import { useEffect as useEffect25, useRef as useRef13 } from "react";
9519
9818
  function useCompleteOAuth(options) {
9520
9819
  const { coinlist } = useCoinList();
9820
+ const log = useLogger("useCompleteOAuth");
9521
9821
  const postOAuthCompleteRef = useRef13(options.postOAuthComplete);
9522
9822
  const onFailureRef = useRef13(options.onFailure);
9523
9823
  const onSuccessRef = useRef13(options.onSuccess);
@@ -9532,8 +9832,16 @@ function useCompleteOAuth(options) {
9532
9832
  if (hasStartedExchangeRef.current) return;
9533
9833
  const oauthResult = coinlist.auth.completeOAuth();
9534
9834
  if (oauthResult.type === "error") {
9835
+ log.error(() => ({
9836
+ msg: "oauth callback rejected",
9837
+ fields: { reason: oauthResult.reason }
9838
+ }));
9535
9839
  void Promise.resolve(onFailureRef.current(oauthResult.reason)).catch(
9536
- () => {
9840
+ (error) => {
9841
+ log.failure(
9842
+ () => ({ msg: "the host onFailure handler threw" }),
9843
+ error
9844
+ );
9537
9845
  }
9538
9846
  );
9539
9847
  return;
@@ -9548,15 +9856,27 @@ function useCompleteOAuth(options) {
9548
9856
  });
9549
9857
  if (cancelled) return;
9550
9858
  if (!ok) {
9859
+ log.error(() => ({
9860
+ msg: "the host postOAuthComplete handler reported failure",
9861
+ fields: { reason: "complete_request_failed" }
9862
+ }));
9551
9863
  hasStartedExchangeRef.current = false;
9552
9864
  await onFailureRef.current("complete_request_failed");
9553
9865
  return;
9554
9866
  }
9555
9867
  await coinlist.init();
9556
9868
  if (cancelled) return;
9869
+ log.info(() => ({ msg: "session established" }));
9557
9870
  await onSuccessRef.current();
9558
- } catch {
9871
+ } catch (error) {
9559
9872
  if (cancelled) return;
9873
+ log.failure(
9874
+ () => ({
9875
+ msg: "settled",
9876
+ fields: { state: "ERROR", reason: "complete_request_failed" }
9877
+ }),
9878
+ error
9879
+ );
9560
9880
  hasStartedExchangeRef.current = false;
9561
9881
  await onFailureRef.current("complete_request_failed");
9562
9882
  }
@@ -9565,7 +9885,7 @@ function useCompleteOAuth(options) {
9565
9885
  cancelled = true;
9566
9886
  hasStartedExchangeRef.current = false;
9567
9887
  };
9568
- }, [coinlist]);
9888
+ }, [coinlist, log]);
9569
9889
  }
9570
9890
 
9571
9891
  // src/client/hooks/checkout/coin-list/token-sale/data/useParticipations.ts
@@ -9573,6 +9893,7 @@ import { useEffect as useEffect26, useState as useState25 } from "react";
9573
9893
  var LOADING_STATE7 = { type: "LOADING" };
9574
9894
  function useParticipations(offerId, options = {}) {
9575
9895
  const { coinlist, isReady } = useCoinList();
9896
+ const log = useLogger("useParticipations");
9576
9897
  const { data } = options;
9577
9898
  const [participationsState, setParticipationsState] = useState25(
9578
9899
  data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE7
@@ -9595,18 +9916,26 @@ function useParticipations(offerId, options = {}) {
9595
9916
  setParticipationsState(LOADING_STATE7);
9596
9917
  coinlist.tokenSale.list(offerId).then((participations) => {
9597
9918
  if (!isCancelled) {
9919
+ log.debug(() => ({
9920
+ msg: "settled",
9921
+ fields: { state: "CONTENT", count: participations.length }
9922
+ }));
9598
9923
  setParticipationsState({ type: "CONTENT", participations });
9599
9924
  }
9600
9925
  }).catch((error) => {
9601
9926
  if (!isCancelled) {
9602
9927
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
9928
+ log.failure(
9929
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
9930
+ error
9931
+ );
9603
9932
  setParticipationsState({ type: "ERROR", reason });
9604
9933
  }
9605
9934
  });
9606
9935
  return () => {
9607
9936
  isCancelled = true;
9608
9937
  };
9609
- }, [coinlist, isReady, offerId, data]);
9938
+ }, [coinlist, isReady, offerId, data, log]);
9610
9939
  return { participationsState };
9611
9940
  }
9612
9941
 
@@ -9615,6 +9944,7 @@ import { useEffect as useEffect27, useState as useState26 } from "react";
9615
9944
  var LOADING_STATE8 = { type: "LOADING" };
9616
9945
  function useOfferDetails(offerId, options = {}) {
9617
9946
  const { coinlist, isReady } = useCoinList();
9947
+ const log = useLogger("useOfferDetails");
9618
9948
  const { data } = options;
9619
9949
  const [offerDetailsState, setOfferDetailsState] = useState26(
9620
9950
  data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE8
@@ -9637,18 +9967,26 @@ function useOfferDetails(offerId, options = {}) {
9637
9967
  setOfferDetailsState(LOADING_STATE8);
9638
9968
  coinlist.offers.get(offerId).then((offerDetail) => {
9639
9969
  if (!isCancelled) {
9970
+ log.debug(() => ({
9971
+ msg: "settled",
9972
+ fields: { state: "CONTENT", offerId: offerDetail.id }
9973
+ }));
9640
9974
  setOfferDetailsState({ type: "CONTENT", offerDetail });
9641
9975
  }
9642
9976
  }).catch((error) => {
9643
9977
  if (!isCancelled) {
9644
9978
  const reason = error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
9979
+ log.failure(
9980
+ () => ({ msg: "settled", fields: { state: "ERROR", reason } }),
9981
+ error
9982
+ );
9645
9983
  setOfferDetailsState({ type: "ERROR", reason });
9646
9984
  }
9647
9985
  });
9648
9986
  return () => {
9649
9987
  isCancelled = true;
9650
9988
  };
9651
- }, [coinlist, isReady, offerId, data]);
9989
+ }, [coinlist, isReady, offerId, data, log]);
9652
9990
  return { offerDetailsState };
9653
9991
  }
9654
9992
 
@@ -9659,6 +9997,7 @@ var LOADING_STATE9 = { type: "LOADING" };
9659
9997
  function useTokenMetadata(options) {
9660
9998
  const { chain, address, data, enabled = true } = options;
9661
9999
  const { coinlist, isReady } = useCoinList();
10000
+ const log = useLogger("useTokenMetadata");
9662
10001
  const [state, setState] = useState27(
9663
10002
  () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE9
9664
10003
  );
@@ -9677,17 +10016,32 @@ function useTokenMetadata(options) {
9677
10016
  setState(LOADING_STATE9);
9678
10017
  coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
9679
10018
  if (!isCancelled) {
10019
+ log.debug(() => ({
10020
+ msg: "settled",
10021
+ fields: {
10022
+ state: "CONTENT",
10023
+ listed: tokenMetadata !== null,
10024
+ symbol: tokenMetadata?.symbol ?? null
10025
+ }
10026
+ }));
9680
10027
  setState({ type: "CONTENT", tokenMetadata });
9681
10028
  }
9682
- }).catch(() => {
10029
+ }).catch((error) => {
9683
10030
  if (!isCancelled) {
10031
+ log.failure(
10032
+ () => ({
10033
+ msg: "settled",
10034
+ fields: { state: "ERROR", reason: "generic-error" }
10035
+ }),
10036
+ error
10037
+ );
9684
10038
  setState({ type: "ERROR", reason: "generic-error" });
9685
10039
  }
9686
10040
  });
9687
10041
  return () => {
9688
10042
  isCancelled = true;
9689
10043
  };
9690
- }, [coinlist, isReady, enabled, chain, address, data, refetchCount]);
10044
+ }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
9691
10045
  return {
9692
10046
  // LOADING would be a lie while disabled: nothing is in flight and nothing
9693
10047
  // will replace it. Settled states (a seed, a previous answer) survive.
@@ -9734,6 +10088,7 @@ export {
9734
10088
  OndoReviewView,
9735
10089
  OndoSidebarView,
9736
10090
  OndoWalletSelectView,
10091
+ RedactedWalletError,
9737
10092
  RequirementItem,
9738
10093
  RequirementItemUi,
9739
10094
  RequirementStatus,
@@ -9766,6 +10121,7 @@ export {
9766
10121
  formatMonthYear,
9767
10122
  offerIconUrl,
9768
10123
  ondoLoadErrorReason,
10124
+ pinoClientLogger,
9769
10125
  prepareOndoSwap,
9770
10126
  quoteIsStale,
9771
10127
  quoteOverAsks,