@coinlist-co/react 0.12.2-rc.7b430dd → 0.12.2-rc.a59b344

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{chunk-DCW7NQXH.js → chunk-4IZ2F732.js} +52 -19
  2. package/dist/chunk-4IZ2F732.js.map +1 -0
  3. package/dist/{chunk-MOE5S6CE.js → chunk-NBO5E2RO.js} +152 -6
  4. package/dist/chunk-NBO5E2RO.js.map +1 -0
  5. package/dist/{chunk-VH34YC3Q.js → chunk-UJYSXXJF.js} +168 -3
  6. package/dist/chunk-UJYSXXJF.js.map +1 -0
  7. package/dist/client/index.cjs +469 -145
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +114 -35
  10. package/dist/client/index.d.ts +114 -35
  11. package/dist/client/index.js +297 -114
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/server/index.cjs +507 -116
  14. package/dist/server/index.cjs.map +1 -1
  15. package/dist/server/index.d.cts +65 -41
  16. package/dist/server/index.d.ts +65 -41
  17. package/dist/server/index.js +321 -65
  18. package/dist/server/index.js.map +1 -1
  19. package/dist/time-CFocgYyl.d.cts +50 -0
  20. package/dist/time-DvgN98Q9.d.ts +50 -0
  21. package/dist/{token-registry-snapshot-BNBNuDu1.d.ts → token-registry-snapshot-BsAfBL_b.d.ts} +9 -7
  22. package/dist/{token-registry-snapshot-CqI6dXM_.d.cts → token-registry-snapshot-Cc_eA5zM.d.cts} +9 -7
  23. package/dist/{tokens-namespace-CIWBtgt2.d.cts → tokens-namespace-D_XSpiS-.d.cts} +154 -19
  24. package/dist/{tokens-namespace-CIWBtgt2.d.ts → tokens-namespace-D_XSpiS-.d.ts} +154 -19
  25. package/dist/universal/index.cjs +333 -40
  26. package/dist/universal/index.cjs.map +1 -1
  27. package/dist/universal/index.d.cts +358 -5
  28. package/dist/universal/index.d.ts +358 -5
  29. package/dist/universal/index.js +28 -2
  30. package/package.json +1 -1
  31. package/dist/chunk-DCW7NQXH.js.map +0 -1
  32. package/dist/chunk-MOE5S6CE.js.map +0 -1
  33. package/dist/chunk-VH34YC3Q.js.map +0 -1
@@ -4,8 +4,10 @@ import {
4
4
  PINO_LEVEL,
5
5
  SDK_LOGGER_NAME,
6
6
  loggerOverPino,
7
- publicClients
8
- } from "../chunk-DCW7NQXH.js";
7
+ notifySessionExpired,
8
+ publicClients,
9
+ systemDelay
10
+ } from "../chunk-4IZ2F732.js";
9
11
  import {
10
12
  AuthorizationCode,
11
13
  CodeVerifier,
@@ -34,12 +36,13 @@ import {
34
36
  decodeSwappedOutputAmount,
35
37
  formattedPricePerShare,
36
38
  generatePKCEParams,
39
+ isOndoNotTradableError,
37
40
  isSwapAvailable,
38
41
  offerDisplayTokens,
39
42
  ondoQuoteOfferDeadline,
40
43
  superstateSwapContractAddress,
41
44
  swapSpender
42
- } from "../chunk-VH34YC3Q.js";
45
+ } from "../chunk-UJYSXXJF.js";
43
46
  import {
44
47
  API_VERSION,
45
48
  AssetDecimals,
@@ -58,6 +61,7 @@ import {
58
61
  HEADER_USER_AGENT,
59
62
  HttpError,
60
63
  KycToken,
64
+ Millis,
61
65
  NA_AMOUNT_ASSET_UI,
62
66
  NotAuthenticatedError,
63
67
  OAUTH_PAGE_PATH,
@@ -67,6 +71,7 @@ import {
67
71
  RequirementsNamespaceImpl,
68
72
  SUPERSTATE_SWAP_ABI,
69
73
  SUPPORT_NEW_TICKET_URL,
74
+ SentWith,
70
75
  SuperstateSwapNamespaceImpl,
71
76
  TokensNamespaceImpl,
72
77
  VERIFY_IDENTITY_ACCREDITATION_PATH,
@@ -80,15 +85,17 @@ import {
80
85
  formatAmount,
81
86
  formatBpsAsPercent,
82
87
  formatRawAmount,
88
+ formatShareAmount,
83
89
  formattedUsdPrice,
84
90
  getNetworkName,
85
91
  getUUIDv4,
86
92
  internalLogger,
93
+ isRejectedToken,
87
94
  parseBlockchainAmount,
88
95
  shortenAddress,
89
96
  txExplorerUrl,
90
97
  usdAmount
91
- } from "../chunk-MOE5S6CE.js";
98
+ } from "../chunk-NBO5E2RO.js";
92
99
 
93
100
  // src/client/CoinListProvider.tsx
94
101
  import {
@@ -148,6 +155,159 @@ var ApiClient = class {
148
155
  }
149
156
  };
150
157
 
158
+ // src/client/core/auth/client-access-token.ts
159
+ var CONFIRM_DELAY = Millis.of(1e3);
160
+ var Generation = {
161
+ initial: 0,
162
+ next: (generation) => generation + 1
163
+ };
164
+ var ClientAccessToken = class {
165
+ constructor(env) {
166
+ this.env = env;
167
+ this.state = { type: "unknown" };
168
+ this.hostCall = null;
169
+ /**
170
+ * Bumped by {@link clear}. A host call that started before a logout must not
171
+ * log the user back in when it lands, so every write checks it first. A 401
172
+ * that arrives after the logout never starts one: `'logged-out'` refuses it.
173
+ */
174
+ this.generation = Generation.initial;
175
+ this.log = internalLogger(env.logger, "AUTH").child({
176
+ op: "getAccessToken"
177
+ });
178
+ }
179
+ authState() {
180
+ return this.state.type;
181
+ }
182
+ /**
183
+ * Asks the host for the current token, whatever is cached.
184
+ *
185
+ * Never answers from a host call already in flight: one started before a
186
+ * login (the mount's `init()`, racing the OAuth callback's) would hand back
187
+ * the answer from before the session cookie existed. It waits for that call
188
+ * to settle instead, so that call's verdict still lands, then asks afresh.
189
+ * A logout while it waits still wins.
190
+ *
191
+ * @throws whatever the host's `getAccessToken` throws.
192
+ */
193
+ async load() {
194
+ const generation = this.generation;
195
+ if (this.hostCall !== null) {
196
+ await this.hostCall.catch(() => null);
197
+ }
198
+ await this.ask(SentWith.noUserToken, generation);
199
+ return this.authState();
200
+ }
201
+ /**
202
+ * The HTTP pipeline's token source: see {@link TokenTrigger}.
203
+ *
204
+ * @throws whatever the host's `getAccessToken` throws.
205
+ */
206
+ async get(trigger) {
207
+ const decision = decideToken(this.state, trigger);
208
+ switch (decision.type) {
209
+ case "serve":
210
+ return decision.token;
211
+ case "ask":
212
+ return this.ask(decision.rejected, this.generation);
213
+ }
214
+ }
215
+ /** Forgets the token: `auth.logout()`. Never an expiry, so never notifies. */
216
+ clear() {
217
+ this.generation = Generation.next(this.generation);
218
+ this.hostCall = null;
219
+ this.state = { type: "logged-out" };
220
+ }
221
+ /**
222
+ * A request that carried no user token was not refused for a token, so the
223
+ * host's first answer stands. One that was is confirmed before it is
224
+ * believed.
225
+ */
226
+ async ask(rejected, generation) {
227
+ if (generation !== this.generation) {
228
+ return currentToken(this.state);
229
+ }
230
+ const first = await this.callHost();
231
+ switch (rejected.type) {
232
+ case "no-user-token":
233
+ return this.commit(first, generation);
234
+ case "user-token":
235
+ return isFresh(first, rejected) ? this.commit(first, generation) : this.confirm(rejected, generation);
236
+ }
237
+ }
238
+ async confirm(rejected, generation) {
239
+ this.log.warn(() => ({
240
+ msg: "host returned no fresh token; asking again before signing out"
241
+ }));
242
+ await this.env.delay(CONFIRM_DELAY);
243
+ const second = await this.callHost();
244
+ return isFresh(second, rejected) ? this.commit(second, generation) : this.expire(generation);
245
+ }
246
+ /** The host's `getAccessToken`, joining a call already in flight. */
247
+ callHost() {
248
+ if (this.hostCall !== null) {
249
+ this.log.debug(() => ({ msg: "joined a host call already in flight" }));
250
+ return this.hostCall;
251
+ }
252
+ const call = (async () => this.env.getAccessToken())().finally(() => {
253
+ if (this.hostCall === call) {
254
+ this.hostCall = null;
255
+ }
256
+ });
257
+ this.hostCall = call;
258
+ return call;
259
+ }
260
+ commit(token, generation) {
261
+ if (generation !== this.generation) {
262
+ return currentToken(this.state);
263
+ }
264
+ this.state = token === null ? { type: "logged-out" } : { type: "logged-in", token };
265
+ return token;
266
+ }
267
+ expire(generation) {
268
+ if (generation !== this.generation) {
269
+ return null;
270
+ }
271
+ const wasLoggedIn = this.state.type === "logged-in";
272
+ this.state = { type: "logged-out" };
273
+ if (wasLoggedIn) {
274
+ this.log.info(() => ({ msg: "session expired" }));
275
+ notifySessionExpired(this.env.onSessionExpired, this.log);
276
+ }
277
+ return null;
278
+ }
279
+ };
280
+ function decideToken(state, trigger) {
281
+ switch (trigger.type) {
282
+ case "before-request":
283
+ return state.type === "unknown" ? { type: "ask", rejected: SentWith.noUserToken } : { type: "serve", token: currentToken(state) };
284
+ case "after-401":
285
+ switch (state.type) {
286
+ // A logout or an expiry verdict: only `load()` may log back in, so a
287
+ // 401 to a request sent before it must not ask the host again.
288
+ case "logged-out":
289
+ return { type: "serve", token: null };
290
+ // Another request may already have renewed since this one was sent.
291
+ case "logged-in":
292
+ return isRejectedToken(state.token, trigger.rejected) ? { type: "ask", rejected: trigger.rejected } : { type: "serve", token: state.token };
293
+ case "unknown":
294
+ return { type: "ask", rejected: trigger.rejected };
295
+ }
296
+ }
297
+ }
298
+ function currentToken(state) {
299
+ switch (state.type) {
300
+ case "logged-in":
301
+ return state.token;
302
+ case "unknown":
303
+ case "logged-out":
304
+ return null;
305
+ }
306
+ }
307
+ function isFresh(token, rejected) {
308
+ return token !== null && !isRejectedToken(token, rejected);
309
+ }
310
+
151
311
  // src/client/core/auth/client-auth-namespace.ts
152
312
  var OAUTH_STATE_KEY = "coinlist.oauth_state";
153
313
  var OAUTH_CODE_VERIFIER_KEY = "coinlist.oauth_code_verifier";
@@ -962,35 +1122,38 @@ var ClientSupportNamespaceImpl = class {
962
1122
 
963
1123
  // src/client/core/coinlist-client.ts
964
1124
  var CoinListClientImpl = class {
965
- constructor(_config) {
966
- this._config = _config;
967
- /** Cached access token: undefined = loading, null = no token, AccessToken = logged in */
968
- this._accessToken = void 0;
969
- const logger = _config.logger ?? null;
1125
+ constructor(config) {
1126
+ this.config = config;
1127
+ const logger = config.logger ?? null;
1128
+ const accessToken = new ClientAccessToken({
1129
+ getAccessToken: () => config.getAccessToken(),
1130
+ onSessionExpired: config.onSessionExpired,
1131
+ logger,
1132
+ ...systemDelay
1133
+ });
1134
+ this.accessToken = accessToken;
970
1135
  this.api = new ApiClient(
971
1136
  {
972
- baseUrl: _config.baseUrl || PUBLIC_API_BASE_URL,
1137
+ baseUrl: config.baseUrl || PUBLIC_API_BASE_URL,
973
1138
  xApiVersion: API_VERSION
974
1139
  },
975
- this.fetchAccessToken.bind(this),
1140
+ (trigger) => accessToken.get(trigger),
976
1141
  logger
977
1142
  );
978
1143
  const ctx = {
979
1144
  api: this.api,
980
- rpc: publicClients(this.api, _config.rpc, _config.logger ?? null),
1145
+ rpc: publicClients(this.api, config.rpc, config.logger ?? null),
981
1146
  logger,
982
1147
  ensureUserAuthenticated: async () => this.ensureAuthenticated()
983
1148
  };
984
- this.auth = new ClientAuthNamespaceImpl(_config, {
985
- getState: () => this.getAuthState(),
986
- clearAccessToken: () => {
987
- this._accessToken = null;
988
- }
1149
+ this.auth = new ClientAuthNamespaceImpl(config, {
1150
+ getState: () => accessToken.authState(),
1151
+ clearAccessToken: () => accessToken.clear()
989
1152
  });
990
1153
  this.offers = new OffersNamespaceImpl(ctx);
991
1154
  this.requirements = new ClientRequirementsNamespaceImpl(
992
1155
  ctx,
993
- _config.coinlistBaseUrl
1156
+ config.coinlistBaseUrl
994
1157
  );
995
1158
  this.wallets = new WalletsNamespaceImpl(ctx);
996
1159
  this.erc20 = new Erc20NamespaceImpl(ctx);
@@ -1002,34 +1165,16 @@ var CoinListClientImpl = class {
1002
1165
  );
1003
1166
  this.ondo = new ClientOndoNamespaceImpl(ctx, this.erc20);
1004
1167
  this.tokens = new TokensNamespaceImpl(
1005
- _config.tokensBaseUrl ?? NABU_BASE_URL,
1168
+ config.tokensBaseUrl ?? NABU_BASE_URL,
1006
1169
  logger
1007
1170
  );
1008
1171
  this.support = new ClientSupportNamespaceImpl(logger);
1009
1172
  }
1010
1173
  async init() {
1011
- await this.fetchAccessToken(true);
1012
- return this.getAuthState();
1013
- }
1014
- async fetchAccessToken(refresh) {
1015
- if (!refresh && this._accessToken !== void 0) return this._accessToken;
1016
- try {
1017
- const accessToken = await this._config.getAccessToken();
1018
- this._accessToken = accessToken;
1019
- return accessToken;
1020
- } catch (_) {
1021
- this._accessToken = null;
1022
- return null;
1023
- }
1024
- }
1025
- getAuthState() {
1026
- if (this._accessToken === void 0) {
1027
- return "unknown";
1028
- }
1029
- return this._accessToken !== null ? "logged-in" : "logged-out";
1174
+ return this.accessToken.load();
1030
1175
  }
1031
1176
  ensureAuthenticated() {
1032
- if (this.getAuthState() !== "logged-in") {
1177
+ if (this.accessToken.authState() !== "logged-in") {
1033
1178
  throw new NotAuthenticatedError();
1034
1179
  }
1035
1180
  }
@@ -2282,7 +2427,7 @@ function Modal({ label, onClose, children, className }) {
2282
2427
  }
2283
2428
 
2284
2429
  // src/client/components/checkout/shared/confirmation/CheckoutConfirmationDialog.tsx
2285
- import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2430
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2286
2431
  function CheckoutConfirmationDialog({
2287
2432
  icon,
2288
2433
  title: title2,
@@ -2308,10 +2453,7 @@ function CheckoutConfirmationDialog({
2308
2453
  }
2309
2454
  )
2310
2455
  ] }),
2311
- header && /* @__PURE__ */ jsxs14(Fragment4, { children: [
2312
- /* @__PURE__ */ jsx20(Divider, {}),
2313
- header
2314
- ] }),
2456
+ header,
2315
2457
  /* @__PURE__ */ jsx20(Divider, {}),
2316
2458
  /* @__PURE__ */ jsx20(CheckoutDetailList, { rows }),
2317
2459
  /* @__PURE__ */ jsx20("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:gap-3", children: actions })
@@ -2328,6 +2470,7 @@ function AssetSummaryRow({
2328
2470
  iconSize = 48,
2329
2471
  value,
2330
2472
  caption,
2473
+ wrapIdentity = false,
2331
2474
  className
2332
2475
  }) {
2333
2476
  return /* @__PURE__ */ jsx21(CoinListStyleScope, { children: /* @__PURE__ */ jsxs15(
@@ -2346,7 +2489,8 @@ function AssetSummaryRow({
2346
2489
  {
2347
2490
  className: cn(
2348
2491
  typeClasses.h4,
2349
- "clcosdk:truncate clcosdk:text-text-primary"
2492
+ "clcosdk:text-text-primary",
2493
+ wrapIdentity ? "clcosdk:break-words" : "clcosdk:truncate"
2350
2494
  ),
2351
2495
  children: asset.name
2352
2496
  }
@@ -2356,7 +2500,8 @@ function AssetSummaryRow({
2356
2500
  {
2357
2501
  className: cn(
2358
2502
  typeClasses.subhead,
2359
- "clcosdk:truncate clcosdk:text-text-secondary"
2503
+ "clcosdk:text-text-secondary",
2504
+ wrapIdentity ? "clcosdk:break-words" : "clcosdk:truncate"
2360
2505
  ),
2361
2506
  children: asset.symbol
2362
2507
  }
@@ -2399,9 +2544,9 @@ function AssetSummaryRow({
2399
2544
  }
2400
2545
 
2401
2546
  // src/client/components/checkout/ondo/buy/confirmation/OndoBuyOrderConfirmed.tsx
2402
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2547
+ import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2403
2548
  var TITLE2 = "Order confirmed";
2404
- var SHARES_RECEIVED_CAPTION = "shares received";
2549
+ var SHARES_RECEIVED_LABEL = "Shares received";
2405
2550
  var TOTAL_COST_LABEL = "Total cost";
2406
2551
  var PRICE_PER_SHARE_LABEL = "Price per share";
2407
2552
  var DELIVERED_TO_LABEL = "Delivered to";
@@ -2423,16 +2568,9 @@ function OndoBuyOrderConfirmed({
2423
2568
  icon: /* @__PURE__ */ jsx22(SuccessGlyph, {}),
2424
2569
  title: TITLE2,
2425
2570
  subtitle: subtitle(state.outputAsset.symbol),
2426
- header: /* @__PURE__ */ jsx22(
2427
- AssetSummaryRow,
2428
- {
2429
- asset: state.outputAsset,
2430
- value: state.outputAmount,
2431
- caption: SHARES_RECEIVED_CAPTION
2432
- }
2433
- ),
2571
+ header: /* @__PURE__ */ jsx22(AssetSummaryRow, { asset: state.outputAsset, wrapIdentity: true }),
2434
2572
  rows: detailRows(state),
2435
- actions: /* @__PURE__ */ jsxs16(Fragment5, { children: [
2573
+ actions: /* @__PURE__ */ jsxs16(Fragment4, { children: [
2436
2574
  /* @__PURE__ */ jsx22(ClButton, { variant: "gradient", fullWidth: true, onClick: onClose, children: DONE_LABEL }),
2437
2575
  /* @__PURE__ */ jsx22(ExplorerLink, { url: state.txExplorerUrl })
2438
2576
  ] }),
@@ -2443,6 +2581,7 @@ function OndoBuyOrderConfirmed({
2443
2581
  }
2444
2582
  function detailRows(state) {
2445
2583
  return [
2584
+ { label: SHARES_RECEIVED_LABEL, value: state.outputAmount },
2446
2585
  { label: TOTAL_COST_LABEL, value: state.totalCost },
2447
2586
  { label: PRICE_PER_SHARE_LABEL, value: state.pricePerShare },
2448
2587
  { label: DELIVERED_TO_LABEL, value: state.recipientAddress }
@@ -2883,6 +3022,8 @@ function InfoIcon() {
2883
3022
  import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
2884
3023
  var UNSUPPORTED_CHAIN_TITLE = "Not available on this network";
2885
3024
  var UNSUPPORTED_CHAIN_DESCRIPTION = "Ondo orders cannot be placed on the selected network.";
3025
+ var NOT_TRADABLE_TITLE = "Trading is closed right now";
3026
+ var NOT_TRADABLE_DESCRIPTION = "This asset cannot be traded at the moment. Come back when the market opens.";
2886
3027
  function OndoCheckoutError({
2887
3028
  reason,
2888
3029
  className
@@ -2924,6 +3065,8 @@ function title(reason) {
2924
3065
  switch (reason) {
2925
3066
  case "unsupported-chain":
2926
3067
  return UNSUPPORTED_CHAIN_TITLE;
3068
+ case "not-tradable":
3069
+ return NOT_TRADABLE_TITLE;
2927
3070
  default: {
2928
3071
  const exhaustive = reason;
2929
3072
  return exhaustive;
@@ -2934,6 +3077,8 @@ function description(reason) {
2934
3077
  switch (reason) {
2935
3078
  case "unsupported-chain":
2936
3079
  return UNSUPPORTED_CHAIN_DESCRIPTION;
3080
+ case "not-tradable":
3081
+ return NOT_TRADABLE_DESCRIPTION;
2937
3082
  default: {
2938
3083
  const exhaustive = reason;
2939
3084
  return exhaustive;
@@ -3139,7 +3284,7 @@ function PriceCaption({ price }) {
3139
3284
  import { Wallet } from "lucide-react";
3140
3285
 
3141
3286
  // src/client/components/checkout/shared/selection/SelectableOptionRow.tsx
3142
- import { Children, Fragment as Fragment6 } from "react";
3287
+ import { Children, Fragment as Fragment5 } from "react";
3143
3288
  import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
3144
3289
  function SelectableOptionRow({
3145
3290
  selected,
@@ -3226,7 +3371,7 @@ function OptionMetaRow({ children }) {
3226
3371
  const items = Children.toArray(children).filter(Boolean);
3227
3372
  return /* @__PURE__ */ jsx31("div", { className: "clcosdk:flex clcosdk:min-w-0 clcosdk:items-center clcosdk:gap-1.5", children: items.map((item, index) => (
3228
3373
  // biome-ignore lint/suspicious/noArrayIndexKey: positional separators, and the list is caller-authored JSX.
3229
- /* @__PURE__ */ jsxs21(Fragment6, { children: [
3374
+ /* @__PURE__ */ jsxs21(Fragment5, { children: [
3230
3375
  index > 0 && /* @__PURE__ */ jsx31(MetaDot, {}),
3231
3376
  item
3232
3377
  ] }, index)
@@ -4062,7 +4207,9 @@ import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef4
4062
4207
 
4063
4208
  // src/client/hooks/checkout/ondo/shared/data/ondo-load-error.ts
4064
4209
  function ondoLoadErrorReason(error) {
4065
- return error instanceof NotAuthenticatedError ? "not-authenticated" : "generic-error";
4210
+ if (error instanceof NotAuthenticatedError) return "not-authenticated";
4211
+ if (isOndoNotTradableError(error)) return "not-tradable";
4212
+ return "generic-error";
4066
4213
  }
4067
4214
 
4068
4215
  // src/client/hooks/checkout/ondo/buy/data/useOndoBuyTransaction.ts
@@ -4247,7 +4394,7 @@ function useOndoBuyReviewViewModel({
4247
4394
  tokenMetadata: outputTokenMetadata
4248
4395
  }),
4249
4396
  outputAmount: assetAmount(
4250
- formatAmount(built.receiveOutputAmount, locale),
4397
+ formatShareAmount(built.receiveOutputAmount, locale),
4251
4398
  ondoSymbol
4252
4399
  ),
4253
4400
  recipientAddress: shortenAddress(active.wallet.address),
@@ -4367,6 +4514,8 @@ function refreshErrorMessage(reason) {
4367
4514
  switch (reason) {
4368
4515
  case "not-authenticated":
4369
4516
  return "Sign in to refresh this quote.";
4517
+ case "not-tradable":
4518
+ return "Trading is paused for this asset. Try again when the market opens.";
4370
4519
  case "generic-error":
4371
4520
  return "Could not refresh the quote.";
4372
4521
  default: {
@@ -4494,6 +4643,9 @@ function quoteSizeFromKey(key) {
4494
4643
 
4495
4644
  // src/client/hooks/checkout/ondo/shared/data/useOndoTradingStatus.ts
4496
4645
  import { useEffect as useEffect9, useRef as useRef7, useState as useState8 } from "react";
4646
+ function isNotTradable(state) {
4647
+ return state.type === "CONTENT" && state.status.type === "not-tradable";
4648
+ }
4497
4649
  var LOADING2 = { type: "LOADING" };
4498
4650
  function useOndoTradingStatus(options) {
4499
4651
  const {
@@ -4563,6 +4715,30 @@ function useOndoTradingStatus(options) {
4563
4715
  return { state };
4564
4716
  }
4565
4717
 
4718
+ // src/client/hooks/checkout/ondo/shared/ondo-checkout-error.types.ts
4719
+ var OndoCheckoutErrorReason = {
4720
+ /**
4721
+ * Which reason, if any, replaces the whole checkout. `null` means the steps
4722
+ * render.
4723
+ *
4724
+ * `unsupported-chain` wins because it is settled at mount: no market state
4725
+ * can make a chain with no contract tradable. `not-tradable` needs both a
4726
+ * market *known* to be closed and a user still at the start of the flow,
4727
+ * with no order confirmation on screen. Past the first step a pause belongs
4728
+ * to the step it interrupts, and a just-placed order's dialog must not be
4729
+ * hidden by a market that closed after it filled.
4730
+ */
4731
+ of: ({
4732
+ swappableHere,
4733
+ notTradable,
4734
+ atEntry
4735
+ }) => {
4736
+ if (!swappableHere) return "unsupported-chain";
4737
+ if (notTradable && atEntry) return "not-tradable";
4738
+ return null;
4739
+ }
4740
+ };
4741
+
4566
4742
  // src/client/hooks/checkout/ondo/shared/sidebar/useOndoSidebarViewModel.ts
4567
4743
  var MARKET_OPEN = "Market open";
4568
4744
  var MARKET_CLOSED2 = "Market closed";
@@ -4881,18 +5057,19 @@ function useOndoBuyCheckoutViewModel({
4881
5057
  const [orderConfirmed, setOrderConfirmed] = useState11(null);
4882
5058
  const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
4883
5059
  const live = enabled && swappableHere;
4884
- const { state: priceState } = useOndoPrice({
5060
+ const { state: tradingStatusState } = useOndoTradingStatus({
4885
5061
  symbol: ondoSymbol,
4886
5062
  side: "buy",
4887
- size: priceSize(step),
4888
5063
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
4889
5064
  enabled: live
4890
5065
  });
4891
- const { state: tradingStatusState } = useOndoTradingStatus({
5066
+ const notTradable = isNotTradable(tradingStatusState);
5067
+ const { state: priceState } = useOndoPrice({
4892
5068
  symbol: ondoSymbol,
4893
5069
  side: "buy",
5070
+ size: priceSize(step),
4894
5071
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
4895
- enabled: live
5072
+ enabled: live && !notTradable
4896
5073
  });
4897
5074
  const { state: outputTokenMetadataState } = useCheckoutOfferTokenMetadata({
4898
5075
  offer,
@@ -4970,7 +5147,12 @@ function useOndoBuyCheckoutViewModel({
4970
5147
  priceState,
4971
5148
  tradingStatusState
4972
5149
  });
4973
- const state = !swappableHere ? { type: "error", reason: "unsupported-chain" } : {
5150
+ const errorReason = OndoCheckoutErrorReason.of({
5151
+ swappableHere,
5152
+ notTradable,
5153
+ atEntry: step.type === "wallet" && orderConfirmed === null
5154
+ });
5155
+ const state = errorReason !== null ? { type: "error", reason: errorReason } : {
4974
5156
  type: "content",
4975
5157
  wallet: walletState,
4976
5158
  amount: amountState,
@@ -5066,7 +5248,7 @@ function toOrderConfirmedUi({
5066
5248
  tokenMetadata: outputTokenMetadata
5067
5249
  }),
5068
5250
  outputAmount: assetAmount(
5069
- formatAmount(order.transaction.receiveOutputAmount, locale),
5251
+ formatShareAmount(order.transaction.receiveOutputAmount, locale),
5070
5252
  ondoSymbol
5071
5253
  ),
5072
5254
  totalCost: assetAmount(
@@ -5316,9 +5498,9 @@ function MaxButton2({
5316
5498
 
5317
5499
  // src/client/components/checkout/ondo/sell/confirmation/OndoSellOrderConfirmed.tsx
5318
5500
  import { Check as Check2, ExternalLink as ExternalLink2 } from "lucide-react";
5319
- import { Fragment as Fragment7, jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
5501
+ import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
5320
5502
  var TITLE7 = "Order confirmed";
5321
- var SHARES_SOLD_CAPTION = "shares sold";
5503
+ var SHARES_SOLD_LABEL = "Shares sold";
5322
5504
  var RECEIVED_LABEL = "Received";
5323
5505
  var PRICE_PER_SHARE_LABEL3 = "Price per share";
5324
5506
  var DELIVERED_TO_LABEL2 = "Delivered to";
@@ -5341,21 +5523,12 @@ function OndoSellOrderConfirmed({
5341
5523
  title: TITLE7,
5342
5524
  subtitle: subtitle2(state.soldAsset.symbol, state.proceedsSymbol),
5343
5525
  header: (
5344
- // The asset row leads with what was *sold*, where the buy dialog
5345
- // leads with what arrived. The proceeds are a detail row below,
5346
- // because the position that changed is the thing the user is looking
5347
- // for.
5348
- /* @__PURE__ */ jsx36(
5349
- AssetSummaryRow,
5350
- {
5351
- asset: state.soldAsset,
5352
- value: state.soldAmount,
5353
- caption: SHARES_SOLD_CAPTION
5354
- }
5355
- )
5526
+ // The header names what was sold. The quantity is a detail row, so a
5527
+ // long fund name and a long share count each get the full width.
5528
+ /* @__PURE__ */ jsx36(AssetSummaryRow, { asset: state.soldAsset, wrapIdentity: true })
5356
5529
  ),
5357
5530
  rows: detailRows3(state),
5358
- actions: /* @__PURE__ */ jsxs25(Fragment7, { children: [
5531
+ actions: /* @__PURE__ */ jsxs25(Fragment6, { children: [
5359
5532
  /* @__PURE__ */ jsx36(ClButton, { variant: "gradient", fullWidth: true, onClick: onClose, children: DONE_LABEL2 }),
5360
5533
  /* @__PURE__ */ jsx36(ExplorerLink2, { url: state.txExplorerUrl })
5361
5534
  ] }),
@@ -5366,6 +5539,7 @@ function OndoSellOrderConfirmed({
5366
5539
  }
5367
5540
  function detailRows3(state) {
5368
5541
  return [
5542
+ { label: SHARES_SOLD_LABEL, value: state.soldAmount },
5369
5543
  { label: RECEIVED_LABEL, value: state.proceeds },
5370
5544
  { label: PRICE_PER_SHARE_LABEL3, value: state.pricePerShare },
5371
5545
  { label: DELIVERED_TO_LABEL2, value: state.recipientAddress }
@@ -6435,6 +6609,8 @@ function refreshErrorMessage2(reason) {
6435
6609
  switch (reason) {
6436
6610
  case "not-authenticated":
6437
6611
  return "Sign in to refresh this quote.";
6612
+ case "not-tradable":
6613
+ return "Trading is paused for this asset. Try again when the market opens.";
6438
6614
  case "generic-error":
6439
6615
  return "Could not refresh the quote.";
6440
6616
  default: {
@@ -6488,18 +6664,19 @@ function useOndoSellCheckoutViewModel({
6488
6664
  const [orderConfirmed, setOrderConfirmed] = useState16(null);
6489
6665
  const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
6490
6666
  const live = enabled && swappableHere;
6491
- const { state: priceState } = useOndoPrice({
6667
+ const { state: tradingStatusState } = useOndoTradingStatus({
6492
6668
  symbol: ondoSymbol,
6493
6669
  side: "sell",
6494
- size: priceSize2(step),
6495
6670
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
6496
6671
  enabled: live
6497
6672
  });
6498
- const { state: tradingStatusState } = useOndoTradingStatus({
6673
+ const notTradable = isNotTradable(tradingStatusState);
6674
+ const { state: priceState } = useOndoPrice({
6499
6675
  symbol: ondoSymbol,
6500
6676
  side: "sell",
6677
+ size: priceSize2(step),
6501
6678
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
6502
- enabled: live
6679
+ enabled: live && !notTradable
6503
6680
  });
6504
6681
  const { state: inputTokenMetadataState } = useCheckoutOfferTokenMetadata({
6505
6682
  offer,
@@ -6577,7 +6754,14 @@ function useOndoSellCheckoutViewModel({
6577
6754
  priceState,
6578
6755
  tradingStatusState
6579
6756
  });
6580
- const state = !swappableHere ? { type: "error", reason: "unsupported-chain" } : {
6757
+ const errorReason = OndoCheckoutErrorReason.of({
6758
+ swappableHere,
6759
+ notTradable,
6760
+ // The step the flow opened on, which for a preselected wallet is the
6761
+ // amount rather than a wallet step it never had.
6762
+ atEntry: step.type === initialStep.type && orderConfirmed === null
6763
+ });
6764
+ const state = errorReason !== null ? { type: "error", reason: errorReason } : {
6581
6765
  type: "content",
6582
6766
  wallet: hasWalletStep ? walletState : null,
6583
6767
  amount: amountState,
@@ -6687,7 +6871,7 @@ function toOrderConfirmedUi2({
6687
6871
  tokenMetadata: inputTokenMetadata
6688
6872
  }),
6689
6873
  soldAmount: assetAmount(
6690
- formatAmount(order.transaction.spendInputAmount, locale),
6874
+ formatShareAmount(order.transaction.spendInputAmount, locale),
6691
6875
  ondoSymbol
6692
6876
  ),
6693
6877
  // The expected proceeds rather than the floor: this dialog reports a sale
@@ -6923,10 +7107,10 @@ function MaxButton3({ onClick }) {
6923
7107
 
6924
7108
  // src/client/components/checkout/superstate/swap/confirmation/SuperstateOrderConfirmed.tsx
6925
7109
  import { Check as Check3, ExternalLink as ExternalLink3 } from "lucide-react";
6926
- import { Fragment as Fragment8, jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
7110
+ import { Fragment as Fragment7, jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
6927
7111
  var TITLE10 = "Order confirmed";
6928
7112
  var TOTAL_COST_LABEL2 = "Total cost";
6929
- var SHARES_RECEIVED_LABEL = "Shares received";
7113
+ var SHARES_RECEIVED_LABEL2 = "Shares received";
6930
7114
  var SHARES_RECEIVED_ESTIMATED_LABEL = "Shares received (estimated)";
6931
7115
  var PRICE_PER_SHARE_LABEL5 = "Price per share";
6932
7116
  var PRICE_PER_SHARE_ESTIMATED_LABEL = "Price per share (estimated)";
@@ -6949,15 +7133,9 @@ function SuperstateOrderConfirmed({
6949
7133
  icon: /* @__PURE__ */ jsx41(SuccessGlyph3, {}),
6950
7134
  title: TITLE10,
6951
7135
  subtitle: subtitle3(state.asset.symbol),
6952
- header: /* @__PURE__ */ jsx41(
6953
- AssetSummaryRow,
6954
- {
6955
- asset: state.asset,
6956
- caption: `Issued by ${state.issuer}`
6957
- }
6958
- ),
7136
+ header: /* @__PURE__ */ jsx41(AssetSummaryRow, { asset: state.asset, wrapIdentity: true }),
6959
7137
  rows: detailRows4(state),
6960
- actions: /* @__PURE__ */ jsxs29(Fragment8, { children: [
7138
+ actions: /* @__PURE__ */ jsxs29(Fragment7, { children: [
6961
7139
  /* @__PURE__ */ jsx41(ClButton, { variant: "gradient", fullWidth: true, onClick: onClose, children: DONE_LABEL3 }),
6962
7140
  /* @__PURE__ */ jsx41(ExplorerLink3, { url: state.txExplorerUrl })
6963
7141
  ] }),
@@ -6971,7 +7149,7 @@ function detailRows4(state) {
6971
7149
  return [
6972
7150
  { label: TOTAL_COST_LABEL2, value: state.totalCost },
6973
7151
  {
6974
- label: confirmed ? SHARES_RECEIVED_LABEL : SHARES_RECEIVED_ESTIMATED_LABEL,
7152
+ label: confirmed ? SHARES_RECEIVED_LABEL2 : SHARES_RECEIVED_ESTIMATED_LABEL,
6975
7153
  value: state.outputAmount
6976
7154
  },
6977
7155
  {
@@ -9043,7 +9221,6 @@ function toOrderConfirmedUi3({
9043
9221
  networkName: getNetworkName(chain),
9044
9222
  iconUrl: assetIconUrl
9045
9223
  }),
9046
- issuer: SUPERSTATE_ISSUER_NAME,
9047
9224
  outputAmount: assetAmount(
9048
9225
  formatAmount(order.outputAmount, locale),
9049
9226
  order.outputAsset.symbol
@@ -9121,7 +9298,8 @@ function CheckoutContainer({
9121
9298
  className
9122
9299
  }
9123
9300
  ),
9124
- tokenSale: (tokenSaleOffer) => config["coinlist::token_sale"].render(tokenSaleOffer)
9301
+ tokenSale: (tokenSaleOffer) => config["coinlist::token_sale"].render(tokenSaleOffer),
9302
+ centrifugeVault: (vaultOffer) => config["centrifuge::vault"].render(vaultOffer)
9125
9303
  });
9126
9304
  }
9127
9305
  function OndoCheckoutContainer({
@@ -9169,6 +9347,8 @@ function renderOffer(offer, branches) {
9169
9347
  return branches.superstate(offer);
9170
9348
  case "coinlist::token_sale":
9171
9349
  return branches.tokenSale(offer);
9350
+ case "centrifuge::vault":
9351
+ return branches.centrifugeVault(offer);
9172
9352
  default: {
9173
9353
  const exhaustive = offer;
9174
9354
  return exhaustive;
@@ -9189,7 +9369,7 @@ function renderOndoSide(side, branches) {
9189
9369
  }
9190
9370
 
9191
9371
  // src/client/components/design-system/ThemedImage.tsx
9192
- import { Fragment as Fragment9, jsx as jsx49, jsxs as jsxs35 } from "react/jsx-runtime";
9372
+ import { Fragment as Fragment8, jsx as jsx49, jsxs as jsxs35 } from "react/jsx-runtime";
9193
9373
  function ThemedImage({
9194
9374
  light,
9195
9375
  dark,
@@ -9214,7 +9394,7 @@ function ThemedImage({
9214
9394
  }
9215
9395
  );
9216
9396
  }
9217
- return /* @__PURE__ */ jsxs35(Fragment9, { children: [
9397
+ return /* @__PURE__ */ jsxs35(Fragment8, { children: [
9218
9398
  /* @__PURE__ */ jsx49(
9219
9399
  "img",
9220
9400
  {
@@ -9770,6 +9950,7 @@ function saleWindow(offer) {
9770
9950
  case "superstate::swap":
9771
9951
  return { tagline: offer.tagline, startsAt: offer.startsAt };
9772
9952
  case "ondo::swap":
9953
+ case "centrifuge::vault":
9773
9954
  return { tagline: null, startsAt: null };
9774
9955
  default: {
9775
9956
  const exhaustive = offer;
@@ -10302,7 +10483,7 @@ function StepStatusIcon({ status, className }) {
10302
10483
  }
10303
10484
 
10304
10485
  // src/client/components/requirements/RequirementItem.tsx
10305
- import { Fragment as Fragment10, jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
10486
+ import { Fragment as Fragment9, jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
10306
10487
  var DEFAULT_PENDING = "Under review. We'll notify you when complete.";
10307
10488
  var DEFAULT_REJECTED = "Verification rejected.";
10308
10489
  var SUPPORT_LINK = "Contact support";
@@ -10357,7 +10538,7 @@ function RejectedMessage({
10357
10538
  return message;
10358
10539
  }
10359
10540
  if (linkAt === -1) {
10360
- return /* @__PURE__ */ jsxs41(Fragment10, { children: [
10541
+ return /* @__PURE__ */ jsxs41(Fragment9, { children: [
10361
10542
  message,
10362
10543
  " ",
10363
10544
  /* @__PURE__ */ jsx59(
@@ -10372,7 +10553,7 @@ function RejectedMessage({
10372
10553
  "."
10373
10554
  ] });
10374
10555
  }
10375
- return /* @__PURE__ */ jsxs41(Fragment10, { children: [
10556
+ return /* @__PURE__ */ jsxs41(Fragment9, { children: [
10376
10557
  message.slice(0, linkAt),
10377
10558
  /* @__PURE__ */ jsx59(
10378
10559
  "button",
@@ -10395,7 +10576,7 @@ function WalletActionZone({
10395
10576
  onRemoveWallet
10396
10577
  }) {
10397
10578
  if (multiWallet) {
10398
- return /* @__PURE__ */ jsxs41(Fragment10, { children: [
10579
+ return /* @__PURE__ */ jsxs41(Fragment9, { children: [
10399
10580
  /* @__PURE__ */ jsx59(
10400
10581
  ConnectedWalletList,
10401
10582
  {
@@ -10416,7 +10597,7 @@ function WalletActionZone({
10416
10597
  }
10417
10598
  if (status === "completed") {
10418
10599
  const connected = connectedWallets[0];
10419
- return /* @__PURE__ */ jsxs41(Fragment10, { children: [
10600
+ return /* @__PURE__ */ jsxs41(Fragment9, { children: [
10420
10601
  onAction !== null && /* @__PURE__ */ jsx59(
10421
10602
  ClButton,
10422
10603
  {
@@ -10449,7 +10630,7 @@ function WalletActionZone({
10449
10630
  ] });
10450
10631
  }
10451
10632
  if (status === "rejected") {
10452
- return /* @__PURE__ */ jsxs41(Fragment10, { children: [
10633
+ return /* @__PURE__ */ jsxs41(Fragment9, { children: [
10453
10634
  onAction !== null && /* @__PURE__ */ jsx59(ClButton, { size: "sm", className: "clcosdk:self-start", onClick: onAction, children: "Connect wallet" }),
10454
10635
  /* @__PURE__ */ jsx59(
10455
10636
  AlertBanner,
@@ -10571,7 +10752,7 @@ function RequirementItem({
10571
10752
  }
10572
10753
 
10573
10754
  // src/client/components/requirements/RequirementsChecklistView.tsx
10574
- import { Fragment as Fragment11, jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
10755
+ import { Fragment as Fragment10, jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
10575
10756
  function RequirementsChecklistView(props) {
10576
10757
  return /* @__PURE__ */ jsx60(CoinListStyleScope, { children: /* @__PURE__ */ jsx60(RequirementsChecklistViewBody, { ...props }) });
10577
10758
  }
@@ -10641,7 +10822,7 @@ function RequirementsChecklistViewBody({
10641
10822
  onClick: () => onEvent({ type: "ON_CONTINUE" }),
10642
10823
  children: "Continue"
10643
10824
  }
10644
- ) : /* @__PURE__ */ jsxs42(Fragment11, { children: [
10825
+ ) : /* @__PURE__ */ jsxs42(Fragment10, { children: [
10645
10826
  /* @__PURE__ */ jsx60("div", { className: "clcosdk:flex clcosdk:flex-col clcosdk:divide-y clcosdk:divide-divider", children: state.items.map((row, index) => /* @__PURE__ */ jsx60(
10646
10827
  RequirementItem,
10647
10828
  {
@@ -12250,7 +12431,7 @@ function toVerificationUi(verifyingRequirementId, statusById, identityVerificati
12250
12431
  }
12251
12432
 
12252
12433
  // src/client/components/requirements/RequirementsChecklistContainer.tsx
12253
- import { Fragment as Fragment12, jsx as jsx66, jsxs as jsxs46 } from "react/jsx-runtime";
12434
+ import { Fragment as Fragment11, jsx as jsx66, jsxs as jsxs46 } from "react/jsx-runtime";
12254
12435
  function RequirementsChecklistContainer({
12255
12436
  loading,
12256
12437
  error,
@@ -12262,7 +12443,7 @@ function RequirementsChecklistContainer({
12262
12443
  ...options,
12263
12444
  enabled
12264
12445
  });
12265
- return /* @__PURE__ */ jsxs46(Fragment12, { children: [
12446
+ return /* @__PURE__ */ jsxs46(Fragment11, { children: [
12266
12447
  /* @__PURE__ */ jsx66(
12267
12448
  RequirementsChecklistView,
12268
12449
  {
@@ -12273,7 +12454,7 @@ function RequirementsChecklistContainer({
12273
12454
  className
12274
12455
  }
12275
12456
  ),
12276
- state.type === "content" && /* @__PURE__ */ jsxs46(Fragment12, { children: [
12457
+ state.type === "content" && /* @__PURE__ */ jsxs46(Fragment11, { children: [
12277
12458
  /* @__PURE__ */ jsx66(
12278
12459
  TaxDocumentModalContainer,
12279
12460
  {
@@ -12588,6 +12769,7 @@ export {
12588
12769
  OndoBuyOrderConfirmed,
12589
12770
  OndoBuyReviewView,
12590
12771
  OndoCheckoutError,
12772
+ OndoCheckoutErrorReason,
12591
12773
  OndoSellAmountView,
12592
12774
  OndoSellCheckoutContainer,
12593
12775
  OndoSellCheckoutView,
@@ -12627,6 +12809,7 @@ export {
12627
12809
  formatCountdown,
12628
12810
  formatMonthYear,
12629
12811
  formatSaleCardCountdown,
12812
+ isNotTradable,
12630
12813
  offerAssetIconUrl,
12631
12814
  offerIconUrl,
12632
12815
  offerTokenIdentifier,