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

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.
@@ -109,7 +109,9 @@ __export(client_exports, {
109
109
  formatCountdown: () => formatCountdown,
110
110
  formatMonthYear: () => formatMonthYear,
111
111
  formatSaleCardCountdown: () => formatSaleCardCountdown,
112
+ offerAssetIconUrl: () => offerAssetIconUrl,
112
113
  offerIconUrl: () => offerIconUrl,
114
+ offerTokenIdentifier: () => offerTokenIdentifier,
113
115
  ondoLoadErrorReason: () => ondoLoadErrorReason,
114
116
  pinoClientLogger: () => pinoClientLogger,
115
117
  prepareOndoBuy: () => prepareOndoBuy,
@@ -118,6 +120,9 @@ __export(client_exports, {
118
120
  quoteOverAsks: () => quoteOverAsks,
119
121
  stablecoinIconUrl: () => stablecoinIconUrl,
120
122
  submitErc20Approval: () => submitErc20Approval,
123
+ tokenLogoUrl: () => tokenLogoUrl,
124
+ tokenMetadataOf: () => tokenMetadataOf,
125
+ useCheckoutOfferTokenMetadata: () => useCheckoutOfferTokenMetadata,
121
126
  useCoinList: () => useCoinList,
122
127
  useCoinListSignInCardViewModel: () => useCoinListSignInCardViewModel,
123
128
  useCompleteOAuth: () => useCompleteOAuth,
@@ -1299,8 +1304,9 @@ var SOLANA_CHAINS = {
1299
1304
  solana_mainnet: true,
1300
1305
  solana_devnet: true
1301
1306
  };
1307
+ var isChain = (value) => Object.keys(ETHEREUM_CHAINS).includes(value) || Object.keys(SOLANA_CHAINS).includes(value);
1302
1308
  var Chain = (value) => {
1303
- if (!Object.keys(ETHEREUM_CHAINS).includes(value) && !Object.keys(SOLANA_CHAINS).includes(value)) {
1309
+ if (!isChain(value)) {
1304
1310
  throw new ValidationError(`Unsupported chain: "${value}"`);
1305
1311
  }
1306
1312
  return value;
@@ -1875,7 +1881,7 @@ var Offer = {
1875
1881
  logoUrl: dto.logo_url,
1876
1882
  startsAt: new Date(dto.starts_at),
1877
1883
  endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1878
- tokens: dto.tokens.map(OfferToken.fromDto)
1884
+ tokens: OfferToken.listFromDto(dto.tokens)
1879
1885
  };
1880
1886
  }
1881
1887
  };
@@ -1884,7 +1890,19 @@ var OfferToken = {
1884
1890
  role: dto.role,
1885
1891
  chain: Chain(dto.chain),
1886
1892
  address: EvmContractAddress(dto.address)
1887
- })
1893
+ }),
1894
+ /**
1895
+ * Maps an offer's token list, dropping every token on a chain this SDK does
1896
+ * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
1897
+ * plain `.map` would throw out of `Offer.fromDto` and, through
1898
+ * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
1899
+ * one Base token blanked production's offers list. Dropping costs that
1900
+ * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
1901
+ * so nobody could have looked it up anyway.
1902
+ *
1903
+ * Same shape as `TokenMetadata.fromRegistryDto`.
1904
+ */
1905
+ listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
1888
1906
  };
1889
1907
 
1890
1908
  // src/shared/types/offer-detail.ts
@@ -1946,7 +1964,7 @@ var OfferDetail = {
1946
1964
  name: dto.name,
1947
1965
  asset: Asset.fromDto(dto.asset),
1948
1966
  fundingAssets: dto.funding_assets.map(Asset.fromDto),
1949
- tokens: dto.tokens.map(OfferToken.fromDto),
1967
+ tokens: OfferToken.listFromDto(dto.tokens),
1950
1968
  swapContracts: swapContracts.map(OfferSwapContract.fromDto),
1951
1969
  about: notBlankStringOrNull(dto.about),
1952
1970
  tagline: dto.tagline,
@@ -4647,7 +4665,7 @@ function CoinListSignInCardContainer({
4647
4665
  }
4648
4666
 
4649
4667
  // src/client/components/checkout/CheckoutContainer.tsx
4650
- var import_react34 = require("react");
4668
+ var import_react35 = require("react");
4651
4669
 
4652
4670
  // src/client/components/checkout/shared/amount/CheckoutAmountInput.tsx
4653
4671
  var import_react8 = require("react");
@@ -8445,7 +8463,7 @@ function ErrorView4({
8445
8463
  }
8446
8464
 
8447
8465
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
8448
- var import_react22 = require("react");
8466
+ var import_react23 = require("react");
8449
8467
 
8450
8468
  // src/client/hooks/checkout/ondo/buy/amount/useOndoBuyAmountViewModel.ts
8451
8469
  var import_react15 = require("react");
@@ -8472,6 +8490,26 @@ function stablecoinIconUrl(symbol) {
8472
8490
  function offerIconUrl(offer) {
8473
8491
  return offer.logoUrl === "" ? null : AssetIconUrl(offer.logoUrl);
8474
8492
  }
8493
+ function tokenLogoUrl(logo, minWidth = 40) {
8494
+ switch (logo.kind) {
8495
+ case "VECTOR":
8496
+ return AssetIconUrl(logo.url);
8497
+ case "RASTER": {
8498
+ const chosen = logo.variants.reduce(
8499
+ (smallest, variant) => variant.width >= minWidth && (smallest === null || variant.width < smallest.width) ? variant : smallest,
8500
+ null
8501
+ );
8502
+ return AssetIconUrl((chosen ?? logo.original).url);
8503
+ }
8504
+ default: {
8505
+ const exhaustive = logo;
8506
+ return exhaustive;
8507
+ }
8508
+ }
8509
+ }
8510
+ function offerAssetIconUrl(offer, tokenMetadata) {
8511
+ return (tokenMetadata ? tokenLogoUrl(tokenMetadata.logo) : null) ?? offerIconUrl(offer);
8512
+ }
8475
8513
 
8476
8514
  // src/client/hooks/checkout/shared/checkout-ui.types.ts
8477
8515
  var CheckoutAssetUi = {
@@ -8480,10 +8518,10 @@ var CheckoutAssetUi = {
8480
8518
  * name and symbol, the caller supplies the chain it is being traded on and
8481
8519
  * whatever icon it has for it.
8482
8520
  *
8483
- * `iconUrl` is a caller's parameter rather than the token's own because a
8484
- * token does not carry one - the SDK ships no icon registry, and the only
8485
- * source is the offer being bought. Which is also why it defaults to `null`:
8486
- * the input asset a user pays with has no offer behind it.
8521
+ * `iconUrl` is a caller's parameter rather than the token's own because an
8522
+ * `Erc20Asset` does not carry one, and which source supplies it is the
8523
+ * caller's to decide. Which is also why it defaults to `null`: the input
8524
+ * asset a user pays with has no offer behind it.
8487
8525
  *
8488
8526
  * An asset sourced from the offer rather than from a token has its own
8489
8527
  * companion, {@link fromOffer}. One companion per source, not one per call
@@ -8500,7 +8538,7 @@ var CheckoutAssetUi = {
8500
8538
  }),
8501
8539
  /**
8502
8540
  * The view of the asset an offer sells: the offer supplies its name and the
8503
- * only icon the SDK has, the caller supplies the symbol and the chain.
8541
+ * fallback artwork, the caller supplies the symbol and the chain.
8504
8542
  *
8505
8543
  * `symbol` is a parameter rather than `offer.asset.code` because the symbol a
8506
8544
  * provider trades under is the provider's, not the catalogue's - Ondo's
@@ -8508,14 +8546,26 @@ var CheckoutAssetUi = {
8508
8546
  * asset stands in. Keeping it out here is what lets one companion serve every
8509
8547
  * provider instead of forking per provider.
8510
8548
  *
8549
+ * The icon is resolved from the public token registry when `tokenMetadata`
8550
+ * carries a listed token — `useCheckoutOfferTokenMetadata` fetches it,
8551
+ * keyed by the token `OfferDetail.tokens` lists for this chain — and falls
8552
+ * back to the offer's own logo otherwise. `null` covers every way the
8553
+ * registry answer can be absent (unlisted, not settled, lookup failed);
8554
+ * which one it is stays the concern of the hook's state machine, not of
8555
+ * this model, because the icon is the same either way.
8556
+ *
8511
8557
  * Deliberately no decimals. An offer names an asset; it does not answer for
8512
8558
  * the scale of any particular quantity, and every amount a checkout renders
8513
8559
  * arrives as a `BlockchainAmount` carrying its own.
8514
8560
  */
8515
- fromOffer: (offer, { symbol, networkName }) => ({
8561
+ fromOffer: (offer, {
8562
+ symbol,
8563
+ networkName,
8564
+ tokenMetadata
8565
+ }) => ({
8516
8566
  name: offer.name,
8517
8567
  symbol,
8518
- iconUrl: offerIconUrl(offer),
8568
+ iconUrl: offerAssetIconUrl(offer, tokenMetadata),
8519
8569
  network: { name: networkName, iconUrl: null }
8520
8570
  })
8521
8571
  };
@@ -9036,6 +9086,7 @@ function useOndoBuyReviewViewModel({
9036
9086
  ondoSymbol,
9037
9087
  chain,
9038
9088
  offer,
9089
+ outputTokenMetadata,
9039
9090
  enabled = true,
9040
9091
  onComplete
9041
9092
  }) {
@@ -9088,7 +9139,8 @@ function useOndoBuyReviewViewModel({
9088
9139
  type: "active",
9089
9140
  outputAsset: CheckoutAssetUi.fromOffer(offer, {
9090
9141
  symbol: ondoSymbol,
9091
- networkName: getNetworkName(chain)
9142
+ networkName: getNetworkName(chain),
9143
+ tokenMetadata: outputTokenMetadata
9092
9144
  }),
9093
9145
  outputAmount: assetAmount(
9094
9146
  formatAmount(built.receiveOutputAmount, locale),
@@ -9419,6 +9471,7 @@ function useOndoSidebarViewModel({
9419
9471
  offer,
9420
9472
  ondoSymbol,
9421
9473
  chain,
9474
+ tokenMetadata,
9422
9475
  priceState,
9423
9476
  tradingStatusState
9424
9477
  }) {
@@ -9426,7 +9479,8 @@ function useOndoSidebarViewModel({
9426
9479
  const state = {
9427
9480
  asset: CheckoutAssetUi.fromOffer(offer, {
9428
9481
  symbol: ondoSymbol,
9429
- networkName: getNetworkName(chain)
9482
+ networkName: getNetworkName(chain),
9483
+ tokenMetadata
9430
9484
  }),
9431
9485
  // No frontline endpoint carries any of these today, and the detail list
9432
9486
  // drops a null row rather than dashing it.
@@ -9616,6 +9670,99 @@ function toConfirmedWalletUi(wallets, wallet) {
9616
9670
  };
9617
9671
  }
9618
9672
 
9673
+ // src/client/hooks/shared/useTokenMetadata.ts
9674
+ var import_react22 = require("react");
9675
+ var DISABLED_STATE = { type: "DISABLED" };
9676
+ var LOADING_STATE = { type: "LOADING" };
9677
+ function useTokenMetadata(options) {
9678
+ const { chain, address, data, enabled = true } = options;
9679
+ const { coinlist, isReady } = useCoinList();
9680
+ const log = useLogger("useTokenMetadata");
9681
+ const [state, setState] = (0, import_react22.useState)(
9682
+ () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE
9683
+ );
9684
+ const [refetchCount, setRefetchCount] = (0, import_react22.useState)(0);
9685
+ const refetch = (0, import_react22.useCallback)(() => {
9686
+ setRefetchCount((count) => count + 1);
9687
+ }, []);
9688
+ (0, import_react22.useEffect)(() => {
9689
+ let isCancelled = false;
9690
+ const seedActive = data !== void 0 && refetchCount === 0;
9691
+ if (!isReady || !enabled || seedActive) {
9692
+ return () => {
9693
+ isCancelled = true;
9694
+ };
9695
+ }
9696
+ setState(LOADING_STATE);
9697
+ coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
9698
+ if (!isCancelled) {
9699
+ log.debug(() => ({
9700
+ msg: "settled",
9701
+ fields: {
9702
+ state: "CONTENT",
9703
+ listed: tokenMetadata !== null,
9704
+ symbol: tokenMetadata?.symbol ?? null
9705
+ }
9706
+ }));
9707
+ setState({ type: "CONTENT", tokenMetadata });
9708
+ }
9709
+ }).catch((error) => {
9710
+ if (!isCancelled) {
9711
+ log.failure(
9712
+ () => ({
9713
+ msg: "settled",
9714
+ fields: { state: "ERROR", reason: "generic-error" }
9715
+ }),
9716
+ error
9717
+ );
9718
+ setState({ type: "ERROR", reason: "generic-error" });
9719
+ }
9720
+ });
9721
+ return () => {
9722
+ isCancelled = true;
9723
+ };
9724
+ }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
9725
+ return {
9726
+ // LOADING would be a lie while disabled: nothing is in flight and nothing
9727
+ // will replace it. Settled states (a seed, a previous answer) survive.
9728
+ state: !enabled && state.type === "LOADING" ? DISABLED_STATE : state,
9729
+ refetch
9730
+ };
9731
+ }
9732
+
9733
+ // src/client/hooks/checkout/shared/data/useCheckoutOfferTokenMetadata.ts
9734
+ var NO_TOKEN_ADDRESS = EvmContractAddress(
9735
+ "0x0000000000000000000000000000000000000000"
9736
+ );
9737
+ function offerTokenIdentifier(offer, chain) {
9738
+ const byChain = offer.tokens.filter((token) => token.chain === chain);
9739
+ const asset = byChain.find((token) => token.role === "swap") ?? byChain.find((token) => token.role === "distribution");
9740
+ return asset === void 0 ? null : { chain, address: asset.address };
9741
+ }
9742
+ function tokenMetadataOf(state) {
9743
+ return state.type === "CONTENT" ? state.tokenMetadata : null;
9744
+ }
9745
+ function useCheckoutOfferTokenMetadata({
9746
+ offer,
9747
+ chain,
9748
+ data,
9749
+ enabled = true
9750
+ }) {
9751
+ const identifier = offerTokenIdentifier(offer, chain);
9752
+ const { state } = useTokenMetadata({
9753
+ // Primitive keys, not the identifier object: the underlying hook re-fetches
9754
+ // only when `(chain, address)` changes, so a host that rebuilds the offer
9755
+ // object per render does not refetch the registry per render.
9756
+ chain: identifier?.chain ?? chain,
9757
+ address: identifier?.address ?? NO_TOKEN_ADDRESS,
9758
+ // Nothing to look up when the offer lists no token here: seed "not
9759
+ // listed" and never fire a request against the placeholder address.
9760
+ enabled: enabled && identifier !== null,
9761
+ data: data !== void 0 ? data : identifier === null ? null : void 0
9762
+ });
9763
+ return { state };
9764
+ }
9765
+
9619
9766
  // src/client/hooks/checkout/ondo/buy/useOndoBuyCheckoutViewModel.ts
9620
9767
  function useOndoBuyCheckoutViewModel({
9621
9768
  offer,
@@ -9626,8 +9773,8 @@ function useOndoBuyCheckoutViewModel({
9626
9773
  onOrderConfirmed
9627
9774
  }) {
9628
9775
  const locale = useLocale();
9629
- const [step, setStep] = (0, import_react22.useState)({ type: "wallet" });
9630
- const [orderConfirmed, setOrderConfirmed] = (0, import_react22.useState)({ type: "hidden" });
9776
+ const [step, setStep] = (0, import_react23.useState)({ type: "wallet" });
9777
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react23.useState)(null);
9631
9778
  const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
9632
9779
  const live = enabled && swappableHere;
9633
9780
  const { state: priceState } = useOndoPrice({
@@ -9643,6 +9790,20 @@ function useOndoBuyCheckoutViewModel({
9643
9790
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
9644
9791
  enabled: live
9645
9792
  });
9793
+ const { state: outputTokenMetadataState } = useCheckoutOfferTokenMetadata({
9794
+ offer,
9795
+ chain,
9796
+ enabled: live
9797
+ });
9798
+ const outputTokenMetadata = tokenMetadataOf(outputTokenMetadataState);
9799
+ const orderConfirmedUi = (order) => order === null ? { type: "hidden" } : toOrderConfirmedUi({
9800
+ order,
9801
+ chain,
9802
+ locale,
9803
+ offer,
9804
+ ondoSymbol,
9805
+ outputTokenMetadata
9806
+ });
9646
9807
  const { state: walletState, onEvent: onWalletEvent } = useOndoWalletSelectViewModel({
9647
9808
  stepInput: walletStepInput(step),
9648
9809
  wallets,
@@ -9689,11 +9850,10 @@ function useOndoBuyCheckoutViewModel({
9689
9850
  ondoSymbol,
9690
9851
  chain,
9691
9852
  offer,
9853
+ outputTokenMetadata,
9692
9854
  enabled: live,
9693
9855
  onComplete: (order) => {
9694
- setOrderConfirmed(
9695
- toOrderConfirmedUi({ order, chain, locale, offer, ondoSymbol })
9696
- );
9856
+ setOrderConfirmed(order);
9697
9857
  setStep({ type: "wallet" });
9698
9858
  onOrderConfirmed?.(order);
9699
9859
  }
@@ -9702,6 +9862,7 @@ function useOndoBuyCheckoutViewModel({
9702
9862
  offer,
9703
9863
  ondoSymbol,
9704
9864
  chain,
9865
+ tokenMetadata: outputTokenMetadata,
9705
9866
  priceState,
9706
9867
  tradingStatusState
9707
9868
  });
@@ -9711,7 +9872,7 @@ function useOndoBuyCheckoutViewModel({
9711
9872
  amount: amountState,
9712
9873
  review: reviewState,
9713
9874
  sidebar: sidebarState,
9714
- orderConfirmed
9875
+ orderConfirmed: orderConfirmedUi(orderConfirmed)
9715
9876
  };
9716
9877
  const onEvent = (event) => {
9717
9878
  switch (event.type) {
@@ -9735,7 +9896,7 @@ function useOndoBuyCheckoutViewModel({
9735
9896
  onReviewEvent(event);
9736
9897
  return;
9737
9898
  case "ON_CLOSE_ORDER_CONFIRMED":
9738
- setOrderConfirmed({ type: "hidden" });
9899
+ setOrderConfirmed(null);
9739
9900
  return;
9740
9901
  default: {
9741
9902
  const exhaustive = event;
@@ -9789,14 +9950,16 @@ function toOrderConfirmedUi({
9789
9950
  chain,
9790
9951
  locale,
9791
9952
  offer,
9792
- ondoSymbol
9953
+ ondoSymbol,
9954
+ outputTokenMetadata
9793
9955
  }) {
9794
9956
  const inputSymbol = TOKEN_REGISTRY.erc20(order.inputAsset).symbol;
9795
9957
  return {
9796
9958
  type: "visible",
9797
9959
  outputAsset: CheckoutAssetUi.fromOffer(offer, {
9798
9960
  symbol: ondoSymbol,
9799
- networkName: getNetworkName(chain)
9961
+ networkName: getNetworkName(chain),
9962
+ tokenMetadata: outputTokenMetadata
9800
9963
  }),
9801
9964
  outputAmount: assetAmount(
9802
9965
  formatAmount(order.transaction.receiveOutputAmount, locale),
@@ -9816,13 +9979,13 @@ function toOrderConfirmedUi({
9816
9979
  }
9817
9980
 
9818
9981
  // src/client/hooks/checkout/ondo/sell/useOndoSellCheckoutViewModel.ts
9819
- var import_react27 = require("react");
9982
+ var import_react28 = require("react");
9820
9983
 
9821
9984
  // src/client/hooks/checkout/ondo/sell/amount/useOndoSellAmountViewModel.ts
9822
- var import_react24 = require("react");
9985
+ var import_react25 = require("react");
9823
9986
 
9824
9987
  // src/client/hooks/shared/erc20/useErc20Balance.ts
9825
- var import_react23 = require("react");
9988
+ var import_react24 = require("react");
9826
9989
  function useErc20Balance(options) {
9827
9990
  const {
9828
9991
  tokenAddress,
@@ -9833,12 +9996,12 @@ function useErc20Balance(options) {
9833
9996
  } = options;
9834
9997
  const { coinlist, isReady } = useCoinList();
9835
9998
  const log = useLogger("useErc20Balance");
9836
- const [balance, setBalance] = (0, import_react23.useState)(null);
9837
- const [isLoading, setIsLoading] = (0, import_react23.useState)(true);
9838
- const fetchIdRef = (0, import_react23.useRef)(0);
9839
- const isFetchingRef = (0, import_react23.useRef)(false);
9840
- const hasReadRef = (0, import_react23.useRef)(false);
9841
- (0, import_react23.useEffect)(() => {
9999
+ const [balance, setBalance] = (0, import_react24.useState)(null);
10000
+ const [isLoading, setIsLoading] = (0, import_react24.useState)(true);
10001
+ const fetchIdRef = (0, import_react24.useRef)(0);
10002
+ const isFetchingRef = (0, import_react24.useRef)(false);
10003
+ const hasReadRef = (0, import_react24.useRef)(false);
10004
+ (0, import_react24.useEffect)(() => {
9842
10005
  if (!isReady) return;
9843
10006
  setBalance(null);
9844
10007
  hasReadRef.current = false;
@@ -9915,16 +10078,17 @@ function useOndoSellAmountViewModel({
9915
10078
  ondoSymbol,
9916
10079
  chain,
9917
10080
  offer,
10081
+ inputTokenMetadata,
9918
10082
  enabled = true,
9919
10083
  onComplete,
9920
10084
  onEdit
9921
10085
  }) {
9922
10086
  const { coinlist } = useCoinList();
9923
10087
  const locale = useLocale();
9924
- const [amountInput, setAmountInput] = (0, import_react24.useState)("");
9925
- const [error, setError] = (0, import_react24.useState)(null);
9926
- const [phase, setPhase] = (0, import_react24.useState)(null);
9927
- const preparationIdRef = (0, import_react24.useRef)(0);
10088
+ const [amountInput, setAmountInput] = (0, import_react25.useState)("");
10089
+ const [error, setError] = (0, import_react25.useState)(null);
10090
+ const [phase, setPhase] = (0, import_react25.useState)(null);
10091
+ const preparationIdRef = (0, import_react25.useRef)(0);
9928
10092
  const isActive = stepInput.type === "active";
9929
10093
  const networkName = getNetworkName(chain);
9930
10094
  const sellAsset2 = isActive ? stepInput.sellAsset : null;
@@ -9935,7 +10099,7 @@ function useOndoSellAmountViewModel({
9935
10099
  chain,
9936
10100
  enabled: enabled && isActive && sellAsset2 !== null
9937
10101
  });
9938
- (0, import_react24.useEffect)(() => {
10102
+ (0, import_react25.useEffect)(() => {
9939
10103
  if (stepInput.type === "incomplete") {
9940
10104
  ++preparationIdRef.current;
9941
10105
  setAmountInput("");
@@ -9961,7 +10125,8 @@ function useOndoSellAmountViewModel({
9961
10125
  type: "complete",
9962
10126
  asset: CheckoutAssetUi.fromOffer(offer, {
9963
10127
  symbol: stepInput.inputAsset,
9964
- networkName
10128
+ networkName,
10129
+ tokenMetadata: inputTokenMetadata
9965
10130
  }),
9966
10131
  amountFormatted: assetAmount(
9967
10132
  formatAmount(stepInput.amount, locale),
@@ -9983,7 +10148,8 @@ function useOndoSellAmountViewModel({
9983
10148
  return {
9984
10149
  asset: CheckoutAssetUi.fromOffer(offer, {
9985
10150
  symbol: ondoSymbol,
9986
- networkName
10151
+ networkName,
10152
+ tokenMetadata: inputTokenMetadata
9987
10153
  }),
9988
10154
  balance: assetAmount(formatAmount(amount, locale), ondoSymbol),
9989
10155
  rawBalance: balance
@@ -10170,15 +10336,15 @@ function preparationErrorMessage2(error) {
10170
10336
  }
10171
10337
 
10172
10338
  // src/client/hooks/checkout/ondo/sell/review/useOndoSellReviewViewModel.ts
10173
- var import_react26 = require("react");
10339
+ var import_react27 = require("react");
10174
10340
 
10175
10341
  // src/client/hooks/checkout/ondo/sell/data/useOndoSellTransaction.ts
10176
- var import_react25 = require("react");
10342
+ var import_react26 = require("react");
10177
10343
  function useOndoSellTransaction(options) {
10178
10344
  const { request, data, enabled } = options;
10179
10345
  const { coinlist, isReady } = useCoinList();
10180
10346
  const log = useLogger("useOndoSellTransaction");
10181
- const [state, setState] = (0, import_react25.useState)(
10347
+ const [state, setState] = (0, import_react26.useState)(
10182
10348
  () => data === void 0 ? { type: "LOADING" } : {
10183
10349
  type: "CONTENT",
10184
10350
  transaction: data,
@@ -10186,12 +10352,12 @@ function useOndoSellTransaction(options) {
10186
10352
  refreshError: null
10187
10353
  }
10188
10354
  );
10189
- const fetchIdRef = (0, import_react25.useRef)(0);
10190
- const isFetchingRef = (0, import_react25.useRef)(false);
10355
+ const fetchIdRef = (0, import_react26.useRef)(0);
10356
+ const isFetchingRef = (0, import_react26.useRef)(false);
10191
10357
  const requestKey = request === null ? null : stableKey2(request);
10192
- const requestRef = (0, import_react25.useRef)(request);
10358
+ const requestRef = (0, import_react26.useRef)(request);
10193
10359
  requestRef.current = request;
10194
- const build = (0, import_react25.useCallback)(async () => {
10360
+ const build = (0, import_react26.useCallback)(async () => {
10195
10361
  const params = requestRef.current;
10196
10362
  if (!isReady || !enabled || params === null) return;
10197
10363
  if (isFetchingRef.current) return;
@@ -10227,7 +10393,7 @@ function useOndoSellTransaction(options) {
10227
10393
  isFetchingRef.current = false;
10228
10394
  }
10229
10395
  }, [coinlist, isReady, enabled, log]);
10230
- (0, import_react25.useEffect)(() => {
10396
+ (0, import_react26.useEffect)(() => {
10231
10397
  if (data === void 0) return;
10232
10398
  ++fetchIdRef.current;
10233
10399
  setState({
@@ -10238,14 +10404,14 @@ function useOndoSellTransaction(options) {
10238
10404
  });
10239
10405
  }, [data]);
10240
10406
  const hasSeed = data !== void 0;
10241
- (0, import_react25.useEffect)(() => {
10407
+ (0, import_react26.useEffect)(() => {
10242
10408
  if (hasSeed || requestKey === null) return;
10243
10409
  build();
10244
10410
  return () => {
10245
10411
  ++fetchIdRef.current;
10246
10412
  };
10247
10413
  }, [build, requestKey, hasSeed]);
10248
- const refetch = (0, import_react25.useCallback)(() => {
10414
+ const refetch = (0, import_react26.useCallback)(() => {
10249
10415
  build();
10250
10416
  }, [build]);
10251
10417
  return { state, refetch };
@@ -10270,8 +10436,8 @@ function useOndoSellReviewViewModel({
10270
10436
  }) {
10271
10437
  const { coinlist } = useCoinList();
10272
10438
  const locale = useLocale();
10273
- const [phase, setPhase] = (0, import_react26.useState)(null);
10274
- const [error, setError] = (0, import_react26.useState)(null);
10439
+ const [phase, setPhase] = (0, import_react27.useState)(null);
10440
+ const [error, setError] = (0, import_react27.useState)(null);
10275
10441
  const isActive = stepInput.type === "active";
10276
10442
  const { state: transactionState, refetch } = useOndoSellTransaction({
10277
10443
  request: isActive ? {
@@ -10283,8 +10449,8 @@ function useOndoSellReviewViewModel({
10283
10449
  data: isActive ? stepInput.transaction : void 0,
10284
10450
  enabled: enabled && isActive
10285
10451
  });
10286
- const executionIdRef = (0, import_react26.useRef)(0);
10287
- (0, import_react26.useEffect)(() => {
10452
+ const executionIdRef = (0, import_react27.useRef)(0);
10453
+ (0, import_react27.useEffect)(() => {
10288
10454
  if (stepInput.type === "incomplete") {
10289
10455
  ++executionIdRef.current;
10290
10456
  setError(null);
@@ -10494,12 +10660,12 @@ function useOndoSellCheckoutViewModel({
10494
10660
  onOrderConfirmed
10495
10661
  }) {
10496
10662
  const locale = useLocale();
10497
- const [initialStep] = (0, import_react27.useState)(
10663
+ const [initialStep] = (0, import_react28.useState)(
10498
10664
  () => wallets.preselected === null ? { type: "wallet" } : { type: "amount", wallet: wallets.preselected }
10499
10665
  );
10500
- const [step, setStep] = (0, import_react27.useState)(initialStep);
10666
+ const [step, setStep] = (0, import_react28.useState)(initialStep);
10501
10667
  const hasWalletStep = initialStep.type === "wallet";
10502
- const [orderConfirmed, setOrderConfirmed] = (0, import_react27.useState)({ type: "hidden" });
10668
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react28.useState)(null);
10503
10669
  const swappableHere = swapSpender(offer.swapContracts, chain) !== null;
10504
10670
  const live = enabled && swappableHere;
10505
10671
  const { state: priceState } = useOndoPrice({
@@ -10515,6 +10681,20 @@ function useOndoSellCheckoutViewModel({
10515
10681
  pollIntervalMs: ONDO_POLL_INTERVAL_MS,
10516
10682
  enabled: live
10517
10683
  });
10684
+ const { state: inputTokenMetadataState } = useCheckoutOfferTokenMetadata({
10685
+ offer,
10686
+ chain,
10687
+ enabled: live
10688
+ });
10689
+ const inputTokenMetadata = tokenMetadataOf(inputTokenMetadataState);
10690
+ const orderConfirmedUi = (order) => order === null ? { type: "hidden" } : toOrderConfirmedUi2({
10691
+ order,
10692
+ chain,
10693
+ locale,
10694
+ offer,
10695
+ ondoSymbol,
10696
+ inputTokenMetadata
10697
+ });
10518
10698
  const { state: walletState, onEvent: onWalletEvent } = useOndoWalletSelectViewModel({
10519
10699
  stepInput: walletStepInput2(step),
10520
10700
  wallets,
@@ -10531,6 +10711,7 @@ function useOndoSellCheckoutViewModel({
10531
10711
  ondoSymbol,
10532
10712
  chain,
10533
10713
  offer,
10714
+ inputTokenMetadata,
10534
10715
  enabled: live,
10535
10716
  // Both transitions read the step through the updater rather than the one
10536
10717
  // this render closed over. Preparing an amount takes an approval to mine,
@@ -10563,9 +10744,7 @@ function useOndoSellCheckoutViewModel({
10563
10744
  chain,
10564
10745
  enabled: live,
10565
10746
  onComplete: (order) => {
10566
- setOrderConfirmed(
10567
- toOrderConfirmedUi2({ order, chain, locale, offer, ondoSymbol })
10568
- );
10747
+ setOrderConfirmed(order);
10569
10748
  setStep(initialStep);
10570
10749
  onOrderConfirmed?.(order);
10571
10750
  }
@@ -10574,6 +10753,7 @@ function useOndoSellCheckoutViewModel({
10574
10753
  offer,
10575
10754
  ondoSymbol,
10576
10755
  chain,
10756
+ tokenMetadata: inputTokenMetadata,
10577
10757
  priceState,
10578
10758
  tradingStatusState
10579
10759
  });
@@ -10583,7 +10763,7 @@ function useOndoSellCheckoutViewModel({
10583
10763
  amount: amountState,
10584
10764
  review: reviewState,
10585
10765
  sidebar: sidebarState,
10586
- orderConfirmed
10766
+ orderConfirmed: orderConfirmedUi(orderConfirmed)
10587
10767
  };
10588
10768
  const onEvent = (event) => {
10589
10769
  switch (event.type) {
@@ -10607,7 +10787,7 @@ function useOndoSellCheckoutViewModel({
10607
10787
  onReviewEvent(event);
10608
10788
  return;
10609
10789
  case "ON_CLOSE_SELL_ORDER_CONFIRMED":
10610
- setOrderConfirmed({ type: "hidden" });
10790
+ setOrderConfirmed(null);
10611
10791
  return;
10612
10792
  default: {
10613
10793
  const exhaustive = event;
@@ -10675,14 +10855,16 @@ function toOrderConfirmedUi2({
10675
10855
  chain,
10676
10856
  locale,
10677
10857
  offer,
10678
- ondoSymbol
10858
+ ondoSymbol,
10859
+ inputTokenMetadata
10679
10860
  }) {
10680
10861
  const settlementSymbol = TOKEN_REGISTRY.erc20(ONDO_SETTLEMENT_ASSET).symbol;
10681
10862
  return {
10682
10863
  type: "visible",
10683
10864
  soldAsset: CheckoutAssetUi.fromOffer(offer, {
10684
10865
  symbol: ondoSymbol,
10685
- networkName: getNetworkName(chain)
10866
+ networkName: getNetworkName(chain),
10867
+ tokenMetadata: inputTokenMetadata
10686
10868
  }),
10687
10869
  soldAmount: assetAmount(
10688
10870
  formatAmount(order.transaction.spendInputAmount, locale),
@@ -10706,10 +10888,10 @@ function toOrderConfirmedUi2({
10706
10888
  }
10707
10889
 
10708
10890
  // src/client/hooks/checkout/superstate/swap/useSuperstateSwapCheckoutViewModel.ts
10709
- var import_react33 = require("react");
10891
+ var import_react34 = require("react");
10710
10892
 
10711
10893
  // src/client/hooks/checkout/superstate/swap/amount/useSuperstateAmountViewModel.ts
10712
- var import_react28 = require("react");
10894
+ var import_react29 = require("react");
10713
10895
  var NO_WALLET3 = EvmWalletAddress(
10714
10896
  "0x0000000000000000000000000000000000000000"
10715
10897
  );
@@ -10723,11 +10905,11 @@ function useSuperstateAmountViewModel({
10723
10905
  enabled = true
10724
10906
  }) {
10725
10907
  const locale = useLocale();
10726
- const [amountInput, setAmountInput] = (0, import_react28.useState)("");
10727
- const [selectedAsset, setSelectedAsset] = (0, import_react28.useState)(
10908
+ const [amountInput, setAmountInput] = (0, import_react29.useState)("");
10909
+ const [selectedAsset, setSelectedAsset] = (0, import_react29.useState)(
10728
10910
  SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]
10729
10911
  );
10730
- const [error, setError] = (0, import_react28.useState)(null);
10912
+ const [error, setError] = (0, import_react29.useState)(null);
10731
10913
  const isActive = stepInput.type === "active";
10732
10914
  const networkName = getNetworkName(chain);
10733
10915
  const { balances, isLoading: balancesLoading } = useErc20TokenBalances({
@@ -10740,7 +10922,7 @@ function useSuperstateAmountViewModel({
10740
10922
  // on this step satisfies the first and not the second.
10741
10923
  enabled: enabled && isActive
10742
10924
  });
10743
- (0, import_react28.useEffect)(() => {
10925
+ (0, import_react29.useEffect)(() => {
10744
10926
  if (stepInput.type === "incomplete") {
10745
10927
  setAmountInput("");
10746
10928
  setSelectedAsset(SUPERSTATE_SUPPORTED_INPUT_ASSETS[0]);
@@ -10911,20 +11093,20 @@ function toInputAssetUi2({
10911
11093
  }
10912
11094
 
10913
11095
  // src/client/hooks/checkout/superstate/swap/data/useSwapOutputToken.ts
10914
- var import_react29 = require("react");
10915
- var LOADING_STATE = { type: "LOADING" };
11096
+ var import_react30 = require("react");
11097
+ var LOADING_STATE2 = { type: "LOADING" };
10916
11098
  function useSwapOutputToken(options) {
10917
11099
  const { contractAddress, chain, enabled } = options;
10918
11100
  const { coinlist, isReady } = useCoinList();
10919
11101
  const log = useLogger("useSwapOutputToken");
10920
- const [outputTokenState, setOutputTokenState] = (0, import_react29.useState)(LOADING_STATE);
10921
- const [retryCount, setRetryCount] = (0, import_react29.useState)(0);
10922
- const fetchIdRef = (0, import_react29.useRef)(0);
10923
- const refetch = (0, import_react29.useCallback)(() => {
10924
- setOutputTokenState(LOADING_STATE);
11102
+ const [outputTokenState, setOutputTokenState] = (0, import_react30.useState)(LOADING_STATE2);
11103
+ const [retryCount, setRetryCount] = (0, import_react30.useState)(0);
11104
+ const fetchIdRef = (0, import_react30.useRef)(0);
11105
+ const refetch = (0, import_react30.useCallback)(() => {
11106
+ setOutputTokenState(LOADING_STATE2);
10925
11107
  setRetryCount((count) => count + 1);
10926
11108
  }, []);
10927
- (0, import_react29.useEffect)(() => {
11109
+ (0, import_react30.useEffect)(() => {
10928
11110
  if (!enabled || !isReady) return;
10929
11111
  const currentFetchId = ++fetchIdRef.current;
10930
11112
  const load = async () => {
@@ -10957,7 +11139,7 @@ function useSwapOutputToken(options) {
10957
11139
  }
10958
11140
 
10959
11141
  // src/client/hooks/checkout/superstate/swap/data/useSwapQuote.ts
10960
- var import_react30 = require("react");
11142
+ var import_react31 = require("react");
10961
11143
  function useSwapQuote(options) {
10962
11144
  const {
10963
11145
  contractAddress,
@@ -10970,13 +11152,13 @@ function useSwapQuote(options) {
10970
11152
  } = options;
10971
11153
  const { coinlist, isReady } = useCoinList();
10972
11154
  const log = useLogger("useSwapQuote");
10973
- const [quote, setQuote] = (0, import_react30.useState)(null);
10974
- const [isLoading, setIsLoading] = (0, import_react30.useState)(true);
10975
- const [isRefreshing, setIsRefreshing] = (0, import_react30.useState)(false);
10976
- const isFetchingRef = (0, import_react30.useRef)(false);
10977
- const hasQuoteRef = (0, import_react30.useRef)(false);
10978
- const fetchIdRef = (0, import_react30.useRef)(0);
10979
- (0, import_react30.useEffect)(() => {
11155
+ const [quote, setQuote] = (0, import_react31.useState)(null);
11156
+ const [isLoading, setIsLoading] = (0, import_react31.useState)(true);
11157
+ const [isRefreshing, setIsRefreshing] = (0, import_react31.useState)(false);
11158
+ const isFetchingRef = (0, import_react31.useRef)(false);
11159
+ const hasQuoteRef = (0, import_react31.useRef)(false);
11160
+ const fetchIdRef = (0, import_react31.useRef)(0);
11161
+ (0, import_react31.useEffect)(() => {
10980
11162
  if (!isReady) return;
10981
11163
  if (!enabled) {
10982
11164
  setIsLoading(false);
@@ -11046,7 +11228,7 @@ function useSwapQuote(options) {
11046
11228
  }
11047
11229
 
11048
11230
  // src/client/hooks/checkout/superstate/swap/review/useSuperstateReviewViewModel.ts
11049
- var import_react31 = require("react");
11231
+ var import_react32 = require("react");
11050
11232
  function useSuperstateReviewViewModel({
11051
11233
  stepInput,
11052
11234
  contractAddress,
@@ -11056,11 +11238,11 @@ function useSuperstateReviewViewModel({
11056
11238
  }) {
11057
11239
  const { coinlist, isReady } = useCoinList();
11058
11240
  const locale = useLocale();
11059
- const [slippageBps, setSlippageBps] = (0, import_react31.useState)(DEFAULT_SLIPPAGE_BPS);
11060
- const [slippageExpanded, setSlippageExpanded] = (0, import_react31.useState)(false);
11061
- const [phase, setPhase] = (0, import_react31.useState)(null);
11062
- const [error, setError] = (0, import_react31.useState)(null);
11063
- (0, import_react31.useEffect)(() => {
11241
+ const [slippageBps, setSlippageBps] = (0, import_react32.useState)(DEFAULT_SLIPPAGE_BPS);
11242
+ const [slippageExpanded, setSlippageExpanded] = (0, import_react32.useState)(false);
11243
+ const [phase, setPhase] = (0, import_react32.useState)(null);
11244
+ const [error, setError] = (0, import_react32.useState)(null);
11245
+ (0, import_react32.useEffect)(() => {
11064
11246
  if (stepInput.type === "incomplete") {
11065
11247
  setSlippageBps(DEFAULT_SLIPPAGE_BPS);
11066
11248
  setSlippageExpanded(false);
@@ -11389,7 +11571,7 @@ function priceUi(quote, outputToken, locale) {
11389
11571
  }
11390
11572
 
11391
11573
  // src/client/hooks/checkout/superstate/swap/wallet/useSuperstateWalletViewModel.ts
11392
- var import_react32 = require("react");
11574
+ var import_react33 = require("react");
11393
11575
  var CONNECT_FAILED2 = "Could not connect that wallet. Please try again.";
11394
11576
  function useSuperstateWalletViewModel({
11395
11577
  stepInput,
@@ -11402,12 +11584,12 @@ function useSuperstateWalletViewModel({
11402
11584
  }) {
11403
11585
  const { coinlist, isReady } = useCoinList();
11404
11586
  const log = useLogger("useSuperstateWalletViewModel");
11405
- const [selected, setSelected] = (0, import_react32.useState)(null);
11406
- const [phase, setPhase] = (0, import_react32.useState)(null);
11407
- const [error, setError] = (0, import_react32.useState)(null);
11587
+ const [selected, setSelected] = (0, import_react33.useState)(null);
11588
+ const [phase, setPhase] = (0, import_react33.useState)(null);
11589
+ const [error, setError] = (0, import_react33.useState)(null);
11408
11590
  const networkName = getNetworkName(chain);
11409
11591
  const selectedWallet = resolveWallet2(wallets, selected);
11410
- (0, import_react32.useEffect)(() => {
11592
+ (0, import_react33.useEffect)(() => {
11411
11593
  if (stepInput.type === "completed") {
11412
11594
  setPhase(null);
11413
11595
  setError(null);
@@ -11626,12 +11808,20 @@ function useSuperstateSwapCheckoutViewModel({
11626
11808
  }) {
11627
11809
  const locale = useLocale();
11628
11810
  const contractAddress = superstateSwapContractAddress(chain);
11629
- const assetIconUrl = offerIconUrl(offer);
11630
- const [step, setStep] = (0, import_react33.useState)({ type: "wallet" });
11631
- const [orderConfirmed, setOrderConfirmed] = (0, import_react33.useState)({ type: "hidden" });
11811
+ const [step, setStep] = (0, import_react34.useState)({ type: "wallet" });
11812
+ const [orderConfirmed, setOrderConfirmed] = (0, import_react34.useState)(null);
11632
11813
  const { inputAmount, inputTokenAddress } = quoteInput(step, chain);
11633
11814
  const live = enabled && contractAddress !== null;
11634
11815
  const contract = contractAddress ?? NO_CONTRACT;
11816
+ const { state: offerTokenMetadataState } = useCheckoutOfferTokenMetadata({
11817
+ offer,
11818
+ chain,
11819
+ enabled: live
11820
+ });
11821
+ const assetIconUrl = offerAssetIconUrl(
11822
+ offer,
11823
+ tokenMetadataOf(offerTokenMetadataState)
11824
+ );
11635
11825
  const { outputTokenState, refetch: refetchOutputToken } = useSwapOutputToken({
11636
11826
  contractAddress: contract,
11637
11827
  chain,
@@ -11688,9 +11878,7 @@ function useSuperstateSwapCheckoutViewModel({
11688
11878
  chain,
11689
11879
  assetIconUrl,
11690
11880
  onComplete: (order) => {
11691
- setOrderConfirmed(
11692
- toOrderConfirmedUi3({ order, chain, locale, assetIconUrl })
11693
- );
11881
+ setOrderConfirmed(order);
11694
11882
  setStep({ type: "wallet" });
11695
11883
  onOrderConfirmed?.(order);
11696
11884
  }
@@ -11716,7 +11904,15 @@ function useSuperstateSwapCheckoutViewModel({
11716
11904
  amount: amountState,
11717
11905
  review: reviewState,
11718
11906
  sidebar: sidebarState,
11719
- orderConfirmed
11907
+ // Derived here rather than in the review completion callback, so a
11908
+ // registry lookup that settles while the order is being placed still
11909
+ // reaches the dialog instead of the fallback icon that closure captured.
11910
+ orderConfirmed: orderConfirmed === null ? { type: "hidden" } : toOrderConfirmedUi3({
11911
+ order: orderConfirmed,
11912
+ chain,
11913
+ locale,
11914
+ assetIconUrl
11915
+ })
11720
11916
  };
11721
11917
  };
11722
11918
  const onEvent = (event) => {
@@ -11741,7 +11937,7 @@ function useSuperstateSwapCheckoutViewModel({
11741
11937
  onReviewEvent(event);
11742
11938
  return;
11743
11939
  case "ON_CLOSE_ORDER_CONFIRMED":
11744
- setOrderConfirmed({ type: "hidden" });
11940
+ setOrderConfirmed(null);
11745
11941
  return;
11746
11942
  case "ON_RETRY_LOAD":
11747
11943
  refetchOutputToken();
@@ -11856,7 +12052,7 @@ function CheckoutContainer({
11856
12052
  enabled = true,
11857
12053
  className
11858
12054
  }) {
11859
- const [side] = (0, import_react34.useState)(() => config["ondo::swap"].side());
12055
+ const [side] = (0, import_react35.useState)(() => config["ondo::swap"].side());
11860
12056
  const isOndo = offer.type === "ondo::swap";
11861
12057
  const ondoSymbol = config["ondo::swap"].symbol(offer);
11862
12058
  const ondoBuy = useOndoBuyCheckoutViewModel({
@@ -12429,23 +12625,23 @@ function EmptyState() {
12429
12625
  }
12430
12626
 
12431
12627
  // src/client/hooks/offers/grid/useOffersGridViewModel.ts
12432
- var import_react36 = require("react");
12628
+ var import_react37 = require("react");
12433
12629
 
12434
12630
  // src/client/hooks/offers/data/useOffers.ts
12435
- var import_react35 = require("react");
12436
- var LOADING_STATE2 = { type: "LOADING" };
12631
+ var import_react36 = require("react");
12632
+ var LOADING_STATE3 = { type: "LOADING" };
12437
12633
  function useOffers(options = {}) {
12438
12634
  const { coinlist, isReady } = useCoinList();
12439
12635
  const log = useLogger("useOffers");
12440
12636
  const { data: serverOffers } = options;
12441
- const [offersState, setOffersState] = (0, import_react35.useState)(
12442
- serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE2
12637
+ const [offersState, setOffersState] = (0, import_react36.useState)(
12638
+ serverOffers !== void 0 ? { type: "CONTENT", offers: serverOffers } : LOADING_STATE3
12443
12639
  );
12444
- (0, import_react35.useEffect)(() => {
12640
+ (0, import_react36.useEffect)(() => {
12445
12641
  let isCancelled = false;
12446
12642
  if (!isReady) {
12447
12643
  if (serverOffers === void 0) {
12448
- setOffersState(LOADING_STATE2);
12644
+ setOffersState(LOADING_STATE3);
12449
12645
  }
12450
12646
  return () => {
12451
12647
  isCancelled = true;
@@ -12456,7 +12652,7 @@ function useOffers(options = {}) {
12456
12652
  isCancelled = true;
12457
12653
  };
12458
12654
  }
12459
- setOffersState(LOADING_STATE2);
12655
+ setOffersState(LOADING_STATE3);
12460
12656
  coinlist.offers.list().then((offers) => {
12461
12657
  if (!isCancelled) {
12462
12658
  log.debug(() => ({
@@ -12507,11 +12703,11 @@ var GENERIC_ERROR_MESSAGE = "Unable to load offers right now. Please try again."
12507
12703
  function useOffersGridViewModel(options = {}) {
12508
12704
  const { data, onOfferClick } = options;
12509
12705
  const { offersState } = useOffers({ data });
12510
- const state = (0, import_react36.useMemo)(
12706
+ const state = (0, import_react37.useMemo)(
12511
12707
  () => toUiState(offersState, onOfferClick !== void 0),
12512
12708
  [offersState, onOfferClick]
12513
12709
  );
12514
- const onEvent = (0, import_react36.useCallback)(
12710
+ const onEvent = (0, import_react37.useCallback)(
12515
12711
  (event) => {
12516
12712
  switch (event.type) {
12517
12713
  case "ON_OFFER_CLICK": {
@@ -12572,13 +12768,13 @@ function OffersGridContainer({
12572
12768
  }
12573
12769
 
12574
12770
  // src/client/components/requirements/checklist/ConnectedWalletList.tsx
12575
- var import_react37 = require("react");
12771
+ var import_react38 = require("react");
12576
12772
  var import_jsx_runtime56 = require("react/jsx-runtime");
12577
12773
  function ConnectedWalletRow({
12578
12774
  wallet,
12579
12775
  onRemove
12580
12776
  }) {
12581
- const [state, setState] = (0, import_react37.useState)("idle");
12777
+ const [state, setState] = (0, import_react38.useState)("idle");
12582
12778
  const remove = async () => {
12583
12779
  if (!onRemove) return;
12584
12780
  setState("removing");
@@ -13148,25 +13344,25 @@ function toError(error) {
13148
13344
  }
13149
13345
 
13150
13346
  // src/client/hooks/requirements/identity-verification/useIdentityVerificationViewModel.ts
13151
- var import_react39 = require("react");
13347
+ var import_react40 = require("react");
13152
13348
 
13153
13349
  // src/client/hooks/requirements/data/useKycToken.ts
13154
- var import_react38 = require("react");
13350
+ var import_react39 = require("react");
13155
13351
  var IDLE_STATE = { type: "IDLE" };
13156
- var LOADING_STATE3 = { type: "LOADING" };
13352
+ var LOADING_STATE4 = { type: "LOADING" };
13157
13353
  function useKycToken(levelName, reset) {
13158
13354
  const { coinlist } = useCoinList();
13159
13355
  const log = useLogger("useKycToken");
13160
- const [kycTokenState, setKycTokenState] = (0, import_react38.useState)(IDLE_STATE);
13161
- const resetPendingRef = (0, import_react38.useRef)(reset === true);
13162
- const tokenIssuedRef = (0, import_react38.useRef)(false);
13163
- (0, import_react38.useEffect)(() => {
13356
+ const [kycTokenState, setKycTokenState] = (0, import_react39.useState)(IDLE_STATE);
13357
+ const resetPendingRef = (0, import_react39.useRef)(reset === true);
13358
+ const tokenIssuedRef = (0, import_react39.useRef)(false);
13359
+ (0, import_react39.useEffect)(() => {
13164
13360
  if (!tokenIssuedRef.current) {
13165
13361
  resetPendingRef.current = reset === true;
13166
13362
  }
13167
13363
  }, [reset]);
13168
- const fetchToken = (0, import_react38.useCallback)(async () => {
13169
- setKycTokenState(LOADING_STATE3);
13364
+ const fetchToken = (0, import_react39.useCallback)(async () => {
13365
+ setKycTokenState(LOADING_STATE4);
13170
13366
  try {
13171
13367
  const kycToken = await coinlist.requirements.createKycToken({
13172
13368
  levelName,
@@ -13199,8 +13395,8 @@ var GENERIC_ERROR_MESSAGE2 = "Unable to start identity verification right now. P
13199
13395
  function useIdentityVerificationViewModel(options = {}) {
13200
13396
  const { levelName, reset, locale, onSubmitted, onError } = options;
13201
13397
  const { kycTokenState, fetchToken } = useKycToken(levelName, reset);
13202
- const fetchedRef = (0, import_react39.useRef)(false);
13203
- (0, import_react39.useEffect)(() => {
13398
+ const fetchedRef = (0, import_react40.useRef)(false);
13399
+ (0, import_react40.useEffect)(() => {
13204
13400
  if (fetchedRef.current) {
13205
13401
  return;
13206
13402
  }
@@ -13208,7 +13404,7 @@ function useIdentityVerificationViewModel(options = {}) {
13208
13404
  fetchToken().catch(() => {
13209
13405
  });
13210
13406
  }, [fetchToken]);
13211
- const state = (0, import_react39.useMemo)(() => {
13407
+ const state = (0, import_react40.useMemo)(() => {
13212
13408
  switch (kycTokenState.type) {
13213
13409
  case "IDLE":
13214
13410
  case "LOADING":
@@ -13234,7 +13430,7 @@ function useIdentityVerificationViewModel(options = {}) {
13234
13430
  }
13235
13431
  }
13236
13432
  }, [kycTokenState, locale, fetchToken]);
13237
- const onEvent = (0, import_react39.useCallback)(
13433
+ const onEvent = (0, import_react40.useCallback)(
13238
13434
  (event) => {
13239
13435
  switch (event.type) {
13240
13436
  case "ON_RETRY":
@@ -13496,12 +13692,12 @@ function SignOnlyScreen({
13496
13692
  }
13497
13693
 
13498
13694
  // src/client/hooks/requirements/tax-document/useTaxDocumentModalViewModel.ts
13499
- var import_react41 = require("react");
13695
+ var import_react42 = require("react");
13500
13696
 
13501
13697
  // src/client/hooks/requirements/data/useTaxDocument.ts
13502
- var import_react40 = require("react");
13698
+ var import_react41 = require("react");
13503
13699
  var IDLE_SIGN = { type: "idle", error: null };
13504
- var LOADING_STATE4 = { type: "LOADING" };
13700
+ var LOADING_STATE5 = { type: "LOADING" };
13505
13701
  var SIGN_FAILED_MESSAGE = "Unable to sign document. Please try again.";
13506
13702
  var DOB_INVALID_MESSAGE = "Enter your date of birth as MM/DD/YYYY.";
13507
13703
  var FIELD_KEYS = {
@@ -13574,8 +13770,8 @@ function useTaxDocument({
13574
13770
  }) {
13575
13771
  const { coinlist, isReady } = useCoinList();
13576
13772
  const log = useLogger("useTaxDocument");
13577
- const [state, setState] = (0, import_react40.useState)(LOADING_STATE4);
13578
- (0, import_react40.useEffect)(() => {
13773
+ const [state, setState] = (0, import_react41.useState)(LOADING_STATE5);
13774
+ (0, import_react41.useEffect)(() => {
13579
13775
  let isCancelled = false;
13580
13776
  if (!isOpen) {
13581
13777
  return () => {
@@ -13583,12 +13779,12 @@ function useTaxDocument({
13583
13779
  };
13584
13780
  }
13585
13781
  if (!isReady) {
13586
- setState(LOADING_STATE4);
13782
+ setState(LOADING_STATE5);
13587
13783
  return () => {
13588
13784
  isCancelled = true;
13589
13785
  };
13590
13786
  }
13591
- setState(LOADING_STATE4);
13787
+ setState(LOADING_STATE5);
13592
13788
  coinlist.requirements.getPii().then((pii) => {
13593
13789
  if (isCancelled) return;
13594
13790
  if (pii.kind === "company") {
@@ -13616,7 +13812,7 @@ function useTaxDocument({
13616
13812
  isCancelled = true;
13617
13813
  };
13618
13814
  }, [coinlist, isReady, isOpen, log]);
13619
- const onEditField = (0, import_react40.useCallback)(
13815
+ const onEditField = (0, import_react41.useCallback)(
13620
13816
  (field, value) => {
13621
13817
  setState(
13622
13818
  (prev) => prev.type === "EDITING" ? { ...prev, fields: { ...prev.fields, [field]: value } } : prev
@@ -13624,7 +13820,7 @@ function useTaxDocument({
13624
13820
  },
13625
13821
  []
13626
13822
  );
13627
- const onStartEdit = (0, import_react40.useCallback)(() => {
13823
+ const onStartEdit = (0, import_react41.useCallback)(() => {
13628
13824
  setState(
13629
13825
  (prev) => prev.type === "REVIEW" ? {
13630
13826
  type: "EDITING",
@@ -13635,7 +13831,7 @@ function useTaxDocument({
13635
13831
  } : prev
13636
13832
  );
13637
13833
  }, []);
13638
- const onSaveEdit = (0, import_react40.useCallback)(() => {
13834
+ const onSaveEdit = (0, import_react41.useCallback)(() => {
13639
13835
  setState(
13640
13836
  (prev) => prev.type === "EDITING" ? {
13641
13837
  type: "REVIEW",
@@ -13646,7 +13842,7 @@ function useTaxDocument({
13646
13842
  } : prev
13647
13843
  );
13648
13844
  }, []);
13649
- const onCancelEdit = (0, import_react40.useCallback)(() => {
13845
+ const onCancelEdit = (0, import_react41.useCallback)(() => {
13650
13846
  setState(
13651
13847
  (prev) => prev.type === "EDITING" ? {
13652
13848
  type: "REVIEW",
@@ -13657,7 +13853,7 @@ function useTaxDocument({
13657
13853
  } : prev
13658
13854
  );
13659
13855
  }, []);
13660
- const onSign = (0, import_react40.useCallback)(() => {
13856
+ const onSign = (0, import_react41.useCallback)(() => {
13661
13857
  if (state.type !== "REVIEW" && state.type !== "SIGN_ONLY") return;
13662
13858
  if (state.type === "REVIEW" && state.fields.dob.trim() !== "" && !isValidUsDate(state.fields.dob)) {
13663
13859
  setState({
@@ -13699,19 +13895,19 @@ function useTaxDocumentModalViewModel({
13699
13895
  onSubmitted
13700
13896
  }) {
13701
13897
  const { state, onEditField, onStartEdit, onSaveEdit, onCancelEdit, onSign } = useTaxDocument({ isOpen });
13702
- (0, import_react41.useEffect)(() => {
13898
+ (0, import_react42.useEffect)(() => {
13703
13899
  if (state.type === "SUBMITTED") {
13704
13900
  onSubmitted?.(state.submission);
13705
13901
  onClose();
13706
13902
  }
13707
13903
  }, [state]);
13708
- const uiState = (0, import_react41.useMemo)(() => {
13904
+ const uiState = (0, import_react42.useMemo)(() => {
13709
13905
  if (!isOpen || state.type === "SUBMITTED") {
13710
13906
  return { type: "hidden" };
13711
13907
  }
13712
13908
  return { type: "content", title: toTitle(state), screen: toScreen(state) };
13713
13909
  }, [isOpen, state]);
13714
- const onEvent = (0, import_react41.useCallback)(
13910
+ const onEvent = (0, import_react42.useCallback)(
13715
13911
  (event) => {
13716
13912
  switch (event.type) {
13717
13913
  case "ON_CLOSE":
@@ -13817,14 +14013,14 @@ function TaxDocumentModalContainer({
13817
14013
  }
13818
14014
 
13819
14015
  // src/client/components/requirements/wallet/ConnectWalletModalView.tsx
13820
- var import_react42 = require("react");
14016
+ var import_react43 = require("react");
13821
14017
  var import_jsx_runtime65 = require("react/jsx-runtime");
13822
14018
  function ConnectWalletModalView({
13823
14019
  state,
13824
14020
  onEvent,
13825
14021
  className
13826
14022
  }) {
13827
- const titleId = (0, import_react42.useId)();
14023
+ const titleId = (0, import_react43.useId)();
13828
14024
  if (state.type === "hidden") {
13829
14025
  return null;
13830
14026
  }
@@ -13927,10 +14123,10 @@ function Screen2({
13927
14123
  }
13928
14124
 
13929
14125
  // src/client/hooks/requirements/wallet/useConnectWalletModalViewModel.ts
13930
- var import_react44 = require("react");
14126
+ var import_react45 = require("react");
13931
14127
 
13932
14128
  // src/client/hooks/requirements/data/useConnectWallet.ts
13933
- var import_react43 = require("react");
14129
+ var import_react44 = require("react");
13934
14130
 
13935
14131
  // src/client/core/wallets/connect-external-wallet.ts
13936
14132
  var DEFAULT_STATEMENT = "Sign this message to prove you own this wallet. This does not cost gas or move funds.";
@@ -14061,24 +14257,24 @@ function useConnectWallet({
14061
14257
  statement
14062
14258
  }) {
14063
14259
  const { coinlist } = useCoinList();
14064
- const [state, setState] = (0, import_react43.useState)(
14260
+ const [state, setState] = (0, import_react44.useState)(
14065
14261
  () => wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
14066
14262
  );
14067
- const attempt = (0, import_react43.useRef)(0);
14068
- (0, import_react43.useEffect)(() => {
14263
+ const attempt = (0, import_react44.useRef)(0);
14264
+ (0, import_react44.useEffect)(() => {
14069
14265
  attempt.current += 1;
14070
14266
  if (!isOpen) return;
14071
14267
  setState(
14072
14268
  wallet ? { type: "READY", address: wallet.address, sign: IDLE_SIGN2 } : { type: "NEEDS_WALLET" }
14073
14269
  );
14074
14270
  }, [isOpen, wallet?.address]);
14075
- (0, import_react43.useEffect)(
14271
+ (0, import_react44.useEffect)(
14076
14272
  () => () => {
14077
14273
  attempt.current += 1;
14078
14274
  },
14079
14275
  []
14080
14276
  );
14081
- const onSign = (0, import_react43.useCallback)(() => {
14277
+ const onSign = (0, import_react44.useCallback)(() => {
14082
14278
  if (!wallet || state.type !== "READY") return;
14083
14279
  attempt.current += 1;
14084
14280
  const gen = attempt.current;
@@ -14140,13 +14336,13 @@ function useConnectWalletModalViewModel({
14140
14336
  challengeType,
14141
14337
  statement
14142
14338
  });
14143
- (0, import_react44.useEffect)(() => {
14339
+ (0, import_react45.useEffect)(() => {
14144
14340
  if (state.type === "CONNECTED") {
14145
14341
  onConnected?.(state.binding);
14146
14342
  onClose();
14147
14343
  }
14148
14344
  }, [state]);
14149
- const uiState = (0, import_react44.useMemo)(() => {
14345
+ const uiState = (0, import_react45.useMemo)(() => {
14150
14346
  if (!isOpen || state.type === "CONNECTED") {
14151
14347
  return { type: "hidden" };
14152
14348
  }
@@ -14171,7 +14367,7 @@ function useConnectWalletModalViewModel({
14171
14367
  canRequestConnect
14172
14368
  };
14173
14369
  }, [isOpen, state, onRequestConnect]);
14174
- const onEvent = (0, import_react44.useCallback)(
14370
+ const onEvent = (0, import_react45.useCallback)(
14175
14371
  (event) => {
14176
14372
  switch (event.type) {
14177
14373
  case "ON_CLOSE":
@@ -14212,7 +14408,7 @@ function ConnectWalletModalContainer({
14212
14408
  }
14213
14409
 
14214
14410
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.ts
14215
- var import_react47 = require("react");
14411
+ var import_react48 = require("react");
14216
14412
 
14217
14413
  // src/client/hooks/requirements/checklist/useRequirementsChecklistViewModel.types.ts
14218
14414
  var RequirementItemUi = {
@@ -14266,8 +14462,8 @@ var ChecklistStatus = {
14266
14462
  };
14267
14463
 
14268
14464
  // src/client/hooks/requirements/data/useOptionAddresses.ts
14269
- var import_react45 = require("react");
14270
- var LOADING_STATE5 = { type: "LOADING" };
14465
+ var import_react46 = require("react");
14466
+ var LOADING_STATE6 = { type: "LOADING" };
14271
14467
  var EMPTY_STATE = {
14272
14468
  type: "CONTENT",
14273
14469
  addresses: []
@@ -14276,19 +14472,19 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14276
14472
  const { coinlist, isReady } = useCoinList();
14277
14473
  const log = useLogger("useOptionAddresses");
14278
14474
  const { data, enabled = true } = options;
14279
- const [addressesState, setAddressesState] = (0, import_react45.useState)(
14280
- data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE5
14475
+ const [addressesState, setAddressesState] = (0, import_react46.useState)(
14476
+ data !== void 0 ? { type: "CONTENT", addresses: data } : LOADING_STATE6
14281
14477
  );
14282
- const [fetchKey, setFetchKey] = (0, import_react45.useState)(0);
14283
- const refetch = (0, import_react45.useCallback)(() => setFetchKey((k) => k + 1), []);
14284
- const disconnect = (0, import_react45.useCallback)(
14478
+ const [fetchKey, setFetchKey] = (0, import_react46.useState)(0);
14479
+ const refetch = (0, import_react46.useCallback)(() => setFetchKey((k) => k + 1), []);
14480
+ const disconnect = (0, import_react46.useCallback)(
14285
14481
  async (addressId) => {
14286
14482
  await coinlist.wallets.remove({ offerId, addressId });
14287
14483
  refetch();
14288
14484
  },
14289
14485
  [coinlist, offerId, refetch]
14290
14486
  );
14291
- (0, import_react45.useEffect)(() => {
14487
+ (0, import_react46.useEffect)(() => {
14292
14488
  let isCancelled = false;
14293
14489
  if (!enabled) {
14294
14490
  setAddressesState(
@@ -14300,7 +14496,7 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14300
14496
  }
14301
14497
  if (!isReady) {
14302
14498
  if (data === void 0) {
14303
- setAddressesState(LOADING_STATE5);
14499
+ setAddressesState(LOADING_STATE6);
14304
14500
  }
14305
14501
  return () => {
14306
14502
  isCancelled = true;
@@ -14317,7 +14513,7 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14317
14513
  isCancelled = true;
14318
14514
  };
14319
14515
  }
14320
- setAddressesState(LOADING_STATE5);
14516
+ setAddressesState(LOADING_STATE6);
14321
14517
  coinlist.wallets.list({ offerId, offerOptionId }).then((addresses) => {
14322
14518
  if (!isCancelled) {
14323
14519
  log.debug(() => ({
@@ -14344,22 +14540,22 @@ function useOptionAddresses(offerId, offerOptionId, options = {}) {
14344
14540
  }
14345
14541
 
14346
14542
  // src/client/hooks/requirements/data/useRequirements.ts
14347
- var import_react46 = require("react");
14348
- var LOADING_STATE6 = { type: "LOADING" };
14543
+ var import_react47 = require("react");
14544
+ var LOADING_STATE7 = { type: "LOADING" };
14349
14545
  function useRequirements(offerId, options = {}) {
14350
14546
  const { coinlist, isReady } = useCoinList();
14351
14547
  const log = useLogger("useRequirements");
14352
14548
  const { data } = options;
14353
- const [requirementsState, setRequirementsState] = (0, import_react46.useState)(
14354
- data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE6
14549
+ const [requirementsState, setRequirementsState] = (0, import_react47.useState)(
14550
+ data !== void 0 ? { type: "CONTENT", ...data } : LOADING_STATE7
14355
14551
  );
14356
- const [fetchKey, setFetchKey] = (0, import_react46.useState)(0);
14357
- const refetch = (0, import_react46.useCallback)(() => setFetchKey((k) => k + 1), []);
14358
- (0, import_react46.useEffect)(() => {
14552
+ const [fetchKey, setFetchKey] = (0, import_react47.useState)(0);
14553
+ const refetch = (0, import_react47.useCallback)(() => setFetchKey((k) => k + 1), []);
14554
+ (0, import_react47.useEffect)(() => {
14359
14555
  let isCancelled = false;
14360
14556
  if (!isReady) {
14361
14557
  if (data === void 0) {
14362
- setRequirementsState(LOADING_STATE6);
14558
+ setRequirementsState(LOADING_STATE7);
14363
14559
  }
14364
14560
  return () => {
14365
14561
  isCancelled = true;
@@ -14376,7 +14572,7 @@ function useRequirements(offerId, options = {}) {
14376
14572
  isCancelled = true;
14377
14573
  };
14378
14574
  }
14379
- setRequirementsState(LOADING_STATE6);
14575
+ setRequirementsState(LOADING_STATE7);
14380
14576
  Promise.all([
14381
14577
  coinlist.requirements.forOffer(offerId),
14382
14578
  coinlist.requirements.statuses(offerId)
@@ -14455,19 +14651,19 @@ function useRequirementsChecklistViewModel(options) {
14455
14651
  const log = useLogger("useRequirementsChecklistViewModel");
14456
14652
  const { coinlist } = useCoinList();
14457
14653
  const { requirementsState, refetch } = useRequirements(offerId, { data });
14458
- const [expandedId, setExpandedId] = (0, import_react47.useState)(null);
14459
- const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react47.useState)(false);
14460
- const [connectWalletOpen, setConnectWalletOpen] = (0, import_react47.useState)(false);
14461
- const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react47.useState)(null);
14462
- const isMountedRef = (0, import_react47.useRef)(true);
14463
- (0, import_react47.useEffect)(() => {
14654
+ const [expandedId, setExpandedId] = (0, import_react48.useState)(null);
14655
+ const [taxDocumentOpen, setTaxDocumentOpen] = (0, import_react48.useState)(false);
14656
+ const [connectWalletOpen, setConnectWalletOpen] = (0, import_react48.useState)(false);
14657
+ const [verifyingRequirementId, setVerifyingRequirementId] = (0, import_react48.useState)(null);
14658
+ const isMountedRef = (0, import_react48.useRef)(true);
14659
+ (0, import_react48.useEffect)(() => {
14464
14660
  isMountedRef.current = true;
14465
14661
  return () => {
14466
14662
  isMountedRef.current = false;
14467
14663
  };
14468
14664
  }, []);
14469
- const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react47.useState)(false);
14470
- (0, import_react47.useEffect)(() => {
14665
+ const [hasWalletRequirement, setHasWalletRequirement] = (0, import_react48.useState)(false);
14666
+ (0, import_react48.useEffect)(() => {
14471
14667
  if (requirementsState.type === "CONTENT") {
14472
14668
  setHasWalletRequirement(
14473
14669
  (requirementsState.requirements[optionId] ?? []).some(
@@ -14483,14 +14679,14 @@ function useRequirementsChecklistViewModel(options) {
14483
14679
  } = useOptionAddresses(offerId, optionId, {
14484
14680
  enabled: hasWalletRequirement
14485
14681
  });
14486
- const removeWallet = (0, import_react47.useCallback)(
14682
+ const removeWallet = (0, import_react48.useCallback)(
14487
14683
  async (addressId) => {
14488
14684
  await disconnect(OfferOptionAddressId(addressId));
14489
14685
  refetch();
14490
14686
  },
14491
14687
  [disconnect, refetch]
14492
14688
  );
14493
- const awaitVerificationResult = (0, import_react47.useCallback)(
14689
+ const awaitVerificationResult = (0, import_react48.useCallback)(
14494
14690
  (requirementId, statusBeforeSubmit) => {
14495
14691
  void (async () => {
14496
14692
  const deadline = Date.now() + VERIFICATION_POLL_TIMEOUT_MS;
@@ -14517,11 +14713,11 @@ function useRequirementsChecklistViewModel(options) {
14517
14713
  },
14518
14714
  [coinlist, offerId, refetch, log]
14519
14715
  );
14520
- const requirements = (0, import_react47.useMemo)(
14716
+ const requirements = (0, import_react48.useMemo)(
14521
14717
  () => requirementsState.type === "CONTENT" ? requirementsState.requirements[optionId] ?? [] : [],
14522
14718
  [requirementsState, optionId]
14523
14719
  );
14524
- const statusById = (0, import_react47.useMemo)(() => {
14720
+ const statusById = (0, import_react48.useMemo)(() => {
14525
14721
  if (requirementsState.type !== "CONTENT") {
14526
14722
  return /* @__PURE__ */ new Map();
14527
14723
  }
@@ -14530,7 +14726,7 @@ function useRequirementsChecklistViewModel(options) {
14530
14726
  requirementsState.statuses.filter((s) => ids.has(s.id)).map((s) => [s.id, s])
14531
14727
  );
14532
14728
  }, [requirementsState, requirements]);
14533
- const state = (0, import_react47.useMemo)(() => {
14729
+ const state = (0, import_react48.useMemo)(() => {
14534
14730
  switch (requirementsState.type) {
14535
14731
  case "LOADING":
14536
14732
  return { type: "loading" };
@@ -14599,7 +14795,7 @@ function useRequirementsChecklistViewModel(options) {
14599
14795
  identityVerificationOptions,
14600
14796
  removeWallet
14601
14797
  ]);
14602
- const handleRequirementAction = (0, import_react47.useCallback)(
14798
+ const handleRequirementAction = (0, import_react48.useCallback)(
14603
14799
  (requirement) => {
14604
14800
  const inlineVerification = statusById.get(requirement.id)?.kycLevel !== void 0 && onRequirementActionOverride === void 0;
14605
14801
  if (inlineVerification) {
@@ -14631,7 +14827,7 @@ function useRequirementsChecklistViewModel(options) {
14631
14827
  coinlist
14632
14828
  ]
14633
14829
  );
14634
- const onEvent = (0, import_react47.useCallback)(
14830
+ const onEvent = (0, import_react48.useCallback)(
14635
14831
  (event) => {
14636
14832
  switch (event.type) {
14637
14833
  case "ON_TOGGLE_ITEM":
@@ -14939,18 +15135,18 @@ function pinoClientLogger(options) {
14939
15135
  }
14940
15136
 
14941
15137
  // src/client/hooks/auth/useCompleteOAuth.ts
14942
- var import_react48 = require("react");
15138
+ var import_react49 = require("react");
14943
15139
  function useCompleteOAuth(options) {
14944
15140
  const { coinlist } = useCoinList();
14945
15141
  const log = useLogger("useCompleteOAuth");
14946
- const postOAuthCompleteRef = (0, import_react48.useRef)(options.postOAuthComplete);
14947
- const onFailureRef = (0, import_react48.useRef)(options.onFailure);
14948
- const onSuccessRef = (0, import_react48.useRef)(options.onSuccess);
15142
+ const postOAuthCompleteRef = (0, import_react49.useRef)(options.postOAuthComplete);
15143
+ const onFailureRef = (0, import_react49.useRef)(options.onFailure);
15144
+ const onSuccessRef = (0, import_react49.useRef)(options.onSuccess);
14949
15145
  postOAuthCompleteRef.current = options.postOAuthComplete;
14950
15146
  onFailureRef.current = options.onFailure;
14951
15147
  onSuccessRef.current = options.onSuccess;
14952
- const hasStartedExchangeRef = (0, import_react48.useRef)(false);
14953
- (0, import_react48.useEffect)(() => {
15148
+ const hasStartedExchangeRef = (0, import_react49.useRef)(false);
15149
+ (0, import_react49.useEffect)(() => {
14954
15150
  if (typeof window === "undefined") return;
14955
15151
  const params = new URLSearchParams(window.location.search);
14956
15152
  if (!params.has("code") && !params.has("error")) return;
@@ -15014,20 +15210,20 @@ function useCompleteOAuth(options) {
15014
15210
  }
15015
15211
 
15016
15212
  // src/client/hooks/checkout/coin-list/token-sale/data/useParticipations.ts
15017
- var import_react49 = require("react");
15018
- var LOADING_STATE7 = { type: "LOADING" };
15213
+ var import_react50 = require("react");
15214
+ var LOADING_STATE8 = { type: "LOADING" };
15019
15215
  function useParticipations(offerId, options = {}) {
15020
15216
  const { coinlist, isReady } = useCoinList();
15021
15217
  const log = useLogger("useParticipations");
15022
15218
  const { data } = options;
15023
- const [participationsState, setParticipationsState] = (0, import_react49.useState)(
15024
- data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE7
15219
+ const [participationsState, setParticipationsState] = (0, import_react50.useState)(
15220
+ data !== void 0 ? { type: "CONTENT", participations: data } : LOADING_STATE8
15025
15221
  );
15026
- (0, import_react49.useEffect)(() => {
15222
+ (0, import_react50.useEffect)(() => {
15027
15223
  let isCancelled = false;
15028
15224
  if (!isReady) {
15029
15225
  if (data === void 0) {
15030
- setParticipationsState(LOADING_STATE7);
15226
+ setParticipationsState(LOADING_STATE8);
15031
15227
  }
15032
15228
  return () => {
15033
15229
  isCancelled = true;
@@ -15038,7 +15234,7 @@ function useParticipations(offerId, options = {}) {
15038
15234
  isCancelled = true;
15039
15235
  };
15040
15236
  }
15041
- setParticipationsState(LOADING_STATE7);
15237
+ setParticipationsState(LOADING_STATE8);
15042
15238
  coinlist.tokenSale.list(offerId).then((participations) => {
15043
15239
  if (!isCancelled) {
15044
15240
  log.debug(() => ({
@@ -15065,20 +15261,20 @@ function useParticipations(offerId, options = {}) {
15065
15261
  }
15066
15262
 
15067
15263
  // src/client/hooks/offers/data/useOfferDetails.ts
15068
- var import_react50 = require("react");
15069
- var LOADING_STATE8 = { type: "LOADING" };
15264
+ var import_react51 = require("react");
15265
+ var LOADING_STATE9 = { type: "LOADING" };
15070
15266
  function useOfferDetails(offerId, options = {}) {
15071
15267
  const { coinlist, isReady } = useCoinList();
15072
15268
  const log = useLogger("useOfferDetails");
15073
15269
  const { data } = options;
15074
- const [offerDetailsState, setOfferDetailsState] = (0, import_react50.useState)(
15075
- data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE8
15270
+ const [offerDetailsState, setOfferDetailsState] = (0, import_react51.useState)(
15271
+ data !== void 0 ? { type: "CONTENT", offerDetail: data } : LOADING_STATE9
15076
15272
  );
15077
- (0, import_react50.useEffect)(() => {
15273
+ (0, import_react51.useEffect)(() => {
15078
15274
  let isCancelled = false;
15079
15275
  if (!isReady) {
15080
15276
  if (data === void 0) {
15081
- setOfferDetailsState(LOADING_STATE8);
15277
+ setOfferDetailsState(LOADING_STATE9);
15082
15278
  }
15083
15279
  return () => {
15084
15280
  isCancelled = true;
@@ -15089,7 +15285,7 @@ function useOfferDetails(offerId, options = {}) {
15089
15285
  isCancelled = true;
15090
15286
  };
15091
15287
  }
15092
- setOfferDetailsState(LOADING_STATE8);
15288
+ setOfferDetailsState(LOADING_STATE9);
15093
15289
  coinlist.offers.get(offerId).then((offerDetail) => {
15094
15290
  if (!isCancelled) {
15095
15291
  log.debug(() => ({
@@ -15129,66 +15325,6 @@ var OfferAssetCardUi = {
15129
15325
  })
15130
15326
  };
15131
15327
 
15132
- // src/client/hooks/tokens/data/useTokenMetadata.ts
15133
- var import_react51 = require("react");
15134
- var DISABLED_STATE = { type: "DISABLED" };
15135
- var LOADING_STATE9 = { type: "LOADING" };
15136
- function useTokenMetadata(options) {
15137
- const { chain, address, data, enabled = true } = options;
15138
- const { coinlist, isReady } = useCoinList();
15139
- const log = useLogger("useTokenMetadata");
15140
- const [state, setState] = (0, import_react51.useState)(
15141
- () => data !== void 0 ? { type: "CONTENT", tokenMetadata: data } : LOADING_STATE9
15142
- );
15143
- const [refetchCount, setRefetchCount] = (0, import_react51.useState)(0);
15144
- const refetch = (0, import_react51.useCallback)(() => {
15145
- setRefetchCount((count) => count + 1);
15146
- }, []);
15147
- (0, import_react51.useEffect)(() => {
15148
- let isCancelled = false;
15149
- const seedActive = data !== void 0 && refetchCount === 0;
15150
- if (!isReady || !enabled || seedActive) {
15151
- return () => {
15152
- isCancelled = true;
15153
- };
15154
- }
15155
- setState(LOADING_STATE9);
15156
- coinlist.tokens.get({ chain, address }).then((tokenMetadata) => {
15157
- if (!isCancelled) {
15158
- log.debug(() => ({
15159
- msg: "settled",
15160
- fields: {
15161
- state: "CONTENT",
15162
- listed: tokenMetadata !== null,
15163
- symbol: tokenMetadata?.symbol ?? null
15164
- }
15165
- }));
15166
- setState({ type: "CONTENT", tokenMetadata });
15167
- }
15168
- }).catch((error) => {
15169
- if (!isCancelled) {
15170
- log.failure(
15171
- () => ({
15172
- msg: "settled",
15173
- fields: { state: "ERROR", reason: "generic-error" }
15174
- }),
15175
- error
15176
- );
15177
- setState({ type: "ERROR", reason: "generic-error" });
15178
- }
15179
- });
15180
- return () => {
15181
- isCancelled = true;
15182
- };
15183
- }, [coinlist, isReady, enabled, chain, address, data, refetchCount, log]);
15184
- return {
15185
- // LOADING would be a lie while disabled: nothing is in flight and nothing
15186
- // will replace it. Settled states (a seed, a previous answer) survive.
15187
- state: !enabled && state.type === "LOADING" ? DISABLED_STATE : state,
15188
- refetch
15189
- };
15190
- }
15191
-
15192
15328
  // src/client/ui/format/date.ts
15193
15329
  function formatMonthYear(date, locale) {
15194
15330
  return new Intl.DateTimeFormat(locale, {
@@ -15278,7 +15414,9 @@ function formatMonthYear(date, locale) {
15278
15414
  formatCountdown,
15279
15415
  formatMonthYear,
15280
15416
  formatSaleCardCountdown,
15417
+ offerAssetIconUrl,
15281
15418
  offerIconUrl,
15419
+ offerTokenIdentifier,
15282
15420
  ondoLoadErrorReason,
15283
15421
  pinoClientLogger,
15284
15422
  prepareOndoBuy,
@@ -15287,6 +15425,9 @@ function formatMonthYear(date, locale) {
15287
15425
  quoteOverAsks,
15288
15426
  stablecoinIconUrl,
15289
15427
  submitErc20Approval,
15428
+ tokenLogoUrl,
15429
+ tokenMetadataOf,
15430
+ useCheckoutOfferTokenMetadata,
15290
15431
  useCoinList,
15291
15432
  useCoinListSignInCardViewModel,
15292
15433
  useCompleteOAuth,