@rhinestone/deposit-modal 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/{DepositModalReown-JUJI7UHE.mjs → DepositModalReown-6RVLEM3B.mjs} +96 -26
  2. package/dist/{DepositModalReown-YQSO4SVY.cjs → DepositModalReown-TXTLVZIQ.cjs} +97 -27
  3. package/dist/caip-D8aRWdEY.d.cts +40 -0
  4. package/dist/caip-D8aRWdEY.d.ts +40 -0
  5. package/dist/{chunk-A223BLVC.mjs → chunk-53IFZGSF.mjs} +177 -21
  6. package/dist/{chunk-VQJHYWAE.cjs → chunk-7RNEYPI4.cjs} +836 -579
  7. package/dist/{chunk-ITFRTPGF.cjs → chunk-BLJMYCBF.cjs} +92 -90
  8. package/dist/{chunk-AYWEWI47.mjs → chunk-DYTRG4C7.mjs} +1 -1
  9. package/dist/{chunk-QGXAAFHU.mjs → chunk-G4FVZQOM.mjs} +23 -21
  10. package/dist/{chunk-SQOEHQNT.cjs → chunk-GWA6GFTI.cjs} +66 -63
  11. package/dist/{chunk-EEEQZOTJ.cjs → chunk-HCQWFL3A.cjs} +84 -101
  12. package/dist/{chunk-WUQZYQRK.mjs → chunk-ITAYM7SB.mjs} +784 -167
  13. package/dist/{chunk-YEBXUUH3.cjs → chunk-JPRV36DT.cjs} +2 -2
  14. package/dist/{chunk-EAUF7SGM.cjs → chunk-JYKMR6QI.cjs} +3 -3
  15. package/dist/{chunk-ILT2PITN.mjs → chunk-MZ53PDIX.mjs} +1 -1
  16. package/dist/{chunk-6U2H3R3T.cjs → chunk-NPSC5R22.cjs} +862 -245
  17. package/dist/{chunk-QLZ5RZTA.mjs → chunk-QRR3Y7EK.mjs} +1 -1
  18. package/dist/{chunk-H577RJN5.cjs → chunk-TENL4H64.cjs} +186 -30
  19. package/dist/{chunk-N3OHR3T2.mjs → chunk-TRD2FCAR.mjs} +363 -106
  20. package/dist/{chunk-7OQO6JDC.mjs → chunk-VRNRRN2U.mjs} +12 -9
  21. package/dist/{chunk-GYEUZSQP.mjs → chunk-WLDTBKRA.mjs} +14 -31
  22. package/dist/{chunk-XJE5MRY4.cjs → chunk-XVKBCDZI.cjs} +1 -1
  23. package/dist/claim.cjs +6 -6
  24. package/dist/claim.d.cts +3 -2
  25. package/dist/claim.d.ts +3 -2
  26. package/dist/claim.mjs +5 -5
  27. package/dist/{caip-523Zrc3r.d.cts → constants-FuzG3h4m.d.cts} +1 -18
  28. package/dist/{caip-523Zrc3r.d.ts → constants-FuzG3h4m.d.ts} +1 -18
  29. package/dist/constants.cjs +5 -3
  30. package/dist/constants.d.cts +3 -2
  31. package/dist/constants.d.ts +3 -2
  32. package/dist/constants.mjs +4 -2
  33. package/dist/deposit.cjs +8 -8
  34. package/dist/deposit.d.cts +3 -2
  35. package/dist/deposit.d.ts +3 -2
  36. package/dist/deposit.mjs +7 -7
  37. package/dist/index.cjs +12 -10
  38. package/dist/index.d.cts +3 -2
  39. package/dist/index.d.ts +3 -2
  40. package/dist/index.mjs +11 -9
  41. package/dist/polymarket.cjs +5 -5
  42. package/dist/polymarket.mjs +2 -2
  43. package/dist/styles.css +14 -0
  44. package/dist/{types-C0SGf-21.d.cts → types-C7wag_iL.d.cts} +4 -3
  45. package/dist/{types-C0SGf-21.d.ts → types-D4b6Cjox.d.ts} +4 -3
  46. package/dist/withdraw.cjs +6 -6
  47. package/dist/withdraw.d.cts +3 -2
  48. package/dist/withdraw.d.ts +3 -2
  49. package/dist/withdraw.mjs +5 -5
  50. package/package.json +1 -1
@@ -11,17 +11,16 @@ import {
11
11
  getEventTxHash,
12
12
  getExchangeLogo,
13
13
  getExchangeLogoSrc,
14
- getPublicClient,
15
14
  isDepositEvent,
16
15
  isFailedEvent,
17
16
  readDedupedAccountSetupResult,
18
17
  runAccountSetupDeduped,
19
18
  txRefsMatch,
20
19
  warnRemovedProps
21
- } from "./chunk-GYEUZSQP.mjs";
20
+ } from "./chunk-WLDTBKRA.mjs";
22
21
  import {
23
22
  ListRow
24
- } from "./chunk-AYWEWI47.mjs";
23
+ } from "./chunk-DYTRG4C7.mjs";
25
24
  import {
26
25
  AlertTriangleIcon,
27
26
  AppleIcon,
@@ -32,6 +31,7 @@ import {
32
31
  Callout,
33
32
  CardIcon,
34
33
  CdnIcon,
34
+ ChainCatalogProvider,
35
35
  CheckIcon,
36
36
  ChevronDownIcon,
37
37
  ChevronLeftIcon,
@@ -55,6 +55,7 @@ import {
55
55
  UnplugIcon,
56
56
  WalletIcon,
57
57
  applyTheme,
58
+ catalogKeyForChain,
58
59
  chainIdsByValue,
59
60
  checkBackendUrl,
60
61
  createDepositService,
@@ -66,6 +67,7 @@ import {
66
67
  formatTokenAmount,
67
68
  formatUserError,
68
69
  getAssetId,
70
+ getPublicClient,
69
71
  isDisplayStablecoinSymbol,
70
72
  isNativeAsset,
71
73
  isRecognizedToken,
@@ -74,10 +76,16 @@ import {
74
76
  resolveAppFeeBps,
75
77
  rpcUrlFor,
76
78
  tokenFormatter,
79
+ useCatalogChain,
80
+ useChainCatalog,
81
+ useChainName,
82
+ useDepositChainIds,
83
+ useExplorerTxUrl,
84
+ useIsDepositChain,
77
85
  useLatestRef,
78
86
  useRpcUrls,
79
87
  useStableRpcUrls
80
- } from "./chunk-WUQZYQRK.mjs";
88
+ } from "./chunk-ITAYM7SB.mjs";
81
89
  import {
82
90
  POLYMARKET_COLLATERAL_OFFRAMP_ADDRESS,
83
91
  POLYMARKET_ICON_URL,
@@ -88,20 +96,21 @@ import {
88
96
  executePolymarketSafeTransfer,
89
97
  fetchPolymarketProxyWallet,
90
98
  readPolymarketBalances
91
- } from "./chunk-ILT2PITN.mjs";
99
+ } from "./chunk-MZ53PDIX.mjs";
92
100
  import {
101
+ CHAIN_BY_ID,
93
102
  HYPERCORE_CHAIN_ID,
94
103
  HYPERCORE_MIN_DEPOSIT_USD,
104
+ HYPERCORE_SPOT_CAIP2,
95
105
  NATIVE_TOKEN_ADDRESS,
96
106
  SOLANA_TOKENS,
97
- SOURCE_CHAINS,
98
107
  cdnIconUrl,
99
108
  findTokenDecimals,
109
+ getBundledTargetTokens,
100
110
  getChainBadge,
101
111
  getChainIcon,
102
112
  getChainId,
103
113
  getChainName,
104
- getExplorerTxUrl,
105
114
  getExplorerUrl,
106
115
  getNativeSymbol,
107
116
  getSupportedChainIds,
@@ -111,12 +120,16 @@ import {
111
120
  getTokenDecimalsByAddress,
112
121
  getTokenSymbol,
113
122
  isHyperCoreCaip2,
123
+ isHyperCoreDestination,
114
124
  isNativeSol,
115
125
  isSolanaCaip2,
116
126
  isStablecoinSymbol,
117
127
  isVirtualDestination,
118
- parseEvmChainId
119
- } from "./chunk-A223BLVC.mjs";
128
+ parseEvmChainId,
129
+ publishShortlistTokens,
130
+ targetChainToCaip2,
131
+ targetChainToChainId
132
+ } from "./chunk-53IFZGSF.mjs";
120
133
 
121
134
  // src/DepositModal.tsx
122
135
  import {
@@ -207,11 +220,14 @@ SegmentedToggle.displayName = "SegmentedToggle";
207
220
  import { jsx as jsx2 } from "react/jsx-runtime";
208
221
  function ChainIcon({ chainId, className, loading }) {
209
222
  const badge = getChainBadge(chainId);
223
+ const catalogChain = useCatalogChain(catalogKeyForChain(chainId));
224
+ const name = catalogChain?.name ?? getChainName(chainId);
225
+ const initial = (catalogChain?.name ?? badge.shortLabel).charAt(0);
210
226
  return /* @__PURE__ */ jsx2(
211
227
  CdnIcon,
212
228
  {
213
- src: getChainIcon(chainId),
214
- alt: getChainName(chainId),
229
+ src: catalogChain?.iconUrl ?? getChainIcon(chainId),
230
+ alt: name,
215
231
  className,
216
232
  loading,
217
233
  fallback: /* @__PURE__ */ jsx2(
@@ -219,8 +235,8 @@ function ChainIcon({ chainId, className, loading }) {
219
235
  {
220
236
  className: "rs-chain-badge-fallback",
221
237
  style: { backgroundColor: badge.bg, color: badge.color },
222
- "aria-label": getChainName(chainId),
223
- children: badge.shortLabel.charAt(0)
238
+ "aria-label": name,
239
+ children: initial
224
240
  }
225
241
  )
226
242
  }
@@ -262,18 +278,17 @@ var DAPP_IMPORT_CATALOG = [
262
278
  label: "Polymarket",
263
279
  iconUrl: cdnIconUrl("dapps", "polymarket")
264
280
  },
281
+ {
282
+ id: "aave",
283
+ label: "Aave",
284
+ iconUrl: cdnIconUrl("dapps", "aave")
285
+ },
265
286
  {
266
287
  id: "hyperliquid",
267
288
  label: "Hyperliquid",
268
289
  iconUrl: cdnIconUrl("dapps", "hyperliquid"),
269
290
  comingSoon: true
270
291
  },
271
- {
272
- id: "aave",
273
- label: "Aave",
274
- iconUrl: cdnIconUrl("dapps", "aave"),
275
- comingSoon: true
276
- },
277
292
  {
278
293
  id: "morpho",
279
294
  label: "Morpho",
@@ -680,6 +695,9 @@ function AssetSelectStep({
680
695
  const [selectedAssetId, setSelectedAssetId] = useState2(null);
681
696
  const [loading, setLoading] = useState2(true);
682
697
  const [error, setError] = useState2(null);
698
+ const isDepositChain = useIsDepositChain();
699
+ const { catalog } = useChainCatalog();
700
+ const chainName = useChainName();
683
701
  const defaultAssetId = useMemo(() => {
684
702
  if (!defaultSourceChain || !defaultSourceToken) return null;
685
703
  return getAssetId({
@@ -714,10 +732,13 @@ function AssetSelectStep({
714
732
  (asset) => asset.token.toLowerCase() === NATIVE_TOKEN_ADDRESS
715
733
  );
716
734
  if (!hasNative) {
735
+ const connectedChainId = publicClient.chain?.id;
717
736
  const nativeAssets = await fetchNativeAssets(
718
737
  address,
719
738
  publicClient,
720
- portfolioAssets
739
+ portfolioAssets,
740
+ isDepositChain,
741
+ connectedChainId != null ? catalog?.byChainId.get(connectedChainId) : void 0
721
742
  );
722
743
  if (!active) return;
723
744
  if (nativeAssets.length > 0) {
@@ -739,9 +760,17 @@ function AssetSelectStep({
739
760
  return () => {
740
761
  active = false;
741
762
  };
742
- }, [address, publicClient, service, onTotalBalanceComputedRef]);
763
+ }, [
764
+ address,
765
+ publicClient,
766
+ service,
767
+ onTotalBalanceComputedRef,
768
+ isDepositChain,
769
+ catalog
770
+ ]);
743
771
  const rows = useMemo(() => {
744
772
  return assets.filter((a) => {
773
+ if (!isDepositChain(a.chainId)) return false;
745
774
  try {
746
775
  if (BigInt(a.balance ?? "0") <= BigInt(0)) return false;
747
776
  } catch {
@@ -761,7 +790,7 @@ function AssetSelectStep({
761
790
  if (balB < balA) return -1;
762
791
  return 0;
763
792
  });
764
- }, [assets]);
793
+ }, [assets, isDepositChain]);
765
794
  useEffect2(() => {
766
795
  if (!defaultAssetId || selectedAssetId) return;
767
796
  if (rows.some((asset) => asset.id === defaultAssetId)) {
@@ -835,7 +864,7 @@ function AssetSelectStep({
835
864
  fallback: asset.symbol.slice(0, 4)
836
865
  }
837
866
  ) }),
838
- chainIcon ? /* @__PURE__ */ jsx6("span", { className: "rs-asset-chain-badge", children: /* @__PURE__ */ jsx6(CdnIcon, { src: chainIcon, alt: getChainName(asset.chainId) }) }) : /* @__PURE__ */ jsx6(
867
+ chainIcon ? /* @__PURE__ */ jsx6("span", { className: "rs-asset-chain-badge", children: /* @__PURE__ */ jsx6(CdnIcon, { src: chainIcon, alt: chainName(asset.chainId) }) }) : /* @__PURE__ */ jsx6(
839
868
  "span",
840
869
  {
841
870
  className: "rs-asset-chain-badge",
@@ -852,7 +881,7 @@ function AssetSelectStep({
852
881
  /* @__PURE__ */ jsx6("span", { className: "rs-asset-name", children: asset.symbol }),
853
882
  /* @__PURE__ */ jsxs5("span", { className: "rs-asset-chain", children: [
854
883
  "on ",
855
- getChainName(asset.chainId)
884
+ chainName(asset.chainId)
856
885
  ] })
857
886
  ] }),
858
887
  /* @__PURE__ */ jsxs5("div", { className: "rs-asset-balance-small", children: [
@@ -881,11 +910,11 @@ function AssetSelectStep({
881
910
  /* @__PURE__ */ jsx6(PoweredBy, {})
882
911
  ] });
883
912
  }
884
- async function fetchNativeAssets(address, publicClient, existing) {
913
+ async function fetchNativeAssets(address, publicClient, existing, isDepositChain, catalogChain) {
885
914
  const existingIds = new Set(existing.map((asset) => asset.id));
886
915
  const connectedChainId = publicClient.chain?.id;
887
916
  if (!connectedChainId) return [];
888
- if (!SOURCE_CHAINS.some((chain) => chain.id === connectedChainId)) return [];
917
+ if (!isDepositChain(connectedChainId)) return [];
889
918
  const id = getAssetId({
890
919
  chainId: connectedChainId,
891
920
  token: NATIVE_TOKEN_ADDRESS
@@ -893,7 +922,8 @@ async function fetchNativeAssets(address, publicClient, existing) {
893
922
  if (existingIds.has(id)) return [];
894
923
  try {
895
924
  const balance = await publicClient.getBalance({ address });
896
- const nativeSymbol = getNativeSymbol(connectedChainId);
925
+ const nativeSymbol = catalogChain?.nativeToken.symbol ?? getNativeSymbol(connectedChainId);
926
+ const nativeDecimals = catalogChain?.nativeToken.decimals ?? 18;
897
927
  return [
898
928
  {
899
929
  id,
@@ -901,7 +931,7 @@ async function fetchNativeAssets(address, publicClient, existing) {
901
931
  token: NATIVE_TOKEN_ADDRESS,
902
932
  symbol: nativeSymbol,
903
933
  name: nativeSymbol,
904
- decimals: 18,
934
+ decimals: nativeDecimals,
905
935
  balance: balance.toString()
906
936
  }
907
937
  ];
@@ -1036,6 +1066,7 @@ function AmountStep({
1036
1066
  publicClient,
1037
1067
  address,
1038
1068
  balanceAddress,
1069
+ declaredBalance,
1039
1070
  asset,
1040
1071
  defaultAmount,
1041
1072
  switchChain,
@@ -1057,7 +1088,8 @@ function AmountStep({
1057
1088
  const chainMismatch = Boolean(
1058
1089
  walletClient?.chain?.id && walletClient.chain.id !== asset.chainId
1059
1090
  );
1060
- const targetSymbol = getTargetTokenSymbol(targetToken, targetChain);
1091
+ const targetChainId = targetChainToChainId(targetChain);
1092
+ const targetSymbol = getTargetTokenSymbol(targetToken, targetChainId);
1061
1093
  const isSourceStablecoin = isStablecoinSymbol(asset.symbol);
1062
1094
  const tokenPriceUsd = useMemo2(() => {
1063
1095
  if (tokenPriceUsdOverride !== void 0 && tokenPriceUsdOverride > 0)
@@ -1078,6 +1110,10 @@ function AmountStep({
1078
1110
  const hasPricing = tokenPriceUsd !== null;
1079
1111
  useEffect3(() => {
1080
1112
  let active = true;
1113
+ if (declaredBalance !== void 0) {
1114
+ setBalance(declaredBalance);
1115
+ return;
1116
+ }
1081
1117
  async function fetchBalance() {
1082
1118
  const balanceTarget = balanceAddress ?? address;
1083
1119
  if (!balanceTarget || !publicClient) return;
@@ -1097,7 +1133,7 @@ function AmountStep({
1097
1133
  return () => {
1098
1134
  active = false;
1099
1135
  };
1100
- }, [address, balanceAddress, publicClient, asset]);
1136
+ }, [address, balanceAddress, declaredBalance, publicClient, asset]);
1101
1137
  useEffect3(() => {
1102
1138
  if (chainMismatch && switchChain && !hasAttemptedSwitch.current) {
1103
1139
  hasAttemptedSwitch.current = true;
@@ -1175,7 +1211,7 @@ function AmountStep({
1175
1211
  return null;
1176
1212
  }
1177
1213
  }, [numericAmount, isSourceStablecoin, hasPricing, tokenPriceUsd, asset.decimals]);
1178
- const minDepositUsd = targetChain === HYPERCORE_CHAIN_ID ? Math.max(HYPERCORE_MIN_DEPOSIT_USD, uiConfig?.minDepositUsd ?? 0) : uiConfig?.minDepositUsd ?? null;
1214
+ const minDepositUsd = isHyperCoreDestination(targetChain) ? Math.max(HYPERCORE_MIN_DEPOSIT_USD, uiConfig?.minDepositUsd ?? 0) : uiConfig?.minDepositUsd ?? null;
1179
1215
  const maxDepositUsd = uiConfig?.maxDepositUsd ?? null;
1180
1216
  const isBelowMin = minDepositUsd !== null && numericAmount > 0 && amountUsd < minDepositUsd;
1181
1217
  const isAboveMax = maxDepositUsd !== null && amountUsd > maxDepositUsd;
@@ -1241,8 +1277,9 @@ function AmountStep({
1241
1277
  };
1242
1278
  const continueLabel = exceedsBalance ? "Insufficient balance" : isAboveMax ? "Continue with max allowed deposit" : isBelowMin ? "Continue with minimum deposit" : "Continue";
1243
1279
  const continueDisabled = chainMismatch || exceedsBalance || numericAmount === 0 && !isBelowMin || balance === null;
1244
- const sourceChainName = getChainName(asset.chainId);
1245
- const targetChainName = getChainName(targetChain);
1280
+ const chainName = useChainName();
1281
+ const sourceChainName = chainName(asset.chainId);
1282
+ const targetChainName = chainName(targetChainId);
1246
1283
  return /* @__PURE__ */ jsxs7("div", { className: "rs-screen", children: [
1247
1284
  /* @__PURE__ */ jsxs7("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
1248
1285
  /* @__PURE__ */ jsx8(BodyHeader, { icon: /* @__PURE__ */ jsx8(WalletIcon, {}), title: "Wallet deposit" }),
@@ -1315,7 +1352,6 @@ function AmountStep({
1315
1352
  /* @__PURE__ */ jsx8("span", { className: "rs-amount-detail-value", children: currencyFormatter.format(balanceAfterUsd) })
1316
1353
  ] })
1317
1354
  ] }),
1318
- targetChain === HYPERCORE_CHAIN_ID && /* @__PURE__ */ jsx8(Callout, { variant: "warning", children: "First deposit to a new HyperCore account includes a ~1 USDC activation fee." }),
1319
1355
  error && /* @__PURE__ */ jsx8(Callout, { variant: "error", children: error }),
1320
1356
  /* @__PURE__ */ jsx8(
1321
1357
  Button,
@@ -1390,11 +1426,12 @@ function ConfirmStep({
1390
1426
  recipient
1391
1427
  ]);
1392
1428
  const quote = setupReady && quoteResult?.requestKey === quoteRequestKey ? quoteResult.quote : null;
1393
- const targetSymbol = sameRoute ? asset.symbol : getTargetTokenSymbol(targetToken, targetChain);
1429
+ const targetChainId = targetChainToChainId(targetChain);
1430
+ const targetSymbol = sameRoute ? asset.symbol : getTargetTokenSymbol(targetToken, targetChainId);
1394
1431
  const sourceChainName = getChainName(asset.chainId);
1395
- const targetChainName = getChainName(targetChain);
1432
+ const targetChainName = getChainName(targetChainId);
1396
1433
  const sourceChainIcon = getChainIcon(asset.chainId);
1397
- const targetChainIcon = getChainIcon(targetChain);
1434
+ const targetChainIcon = getChainIcon(targetChainId);
1398
1435
  const formattedSendAmount = amount && Number.isFinite(Number(amount)) ? formatTokenAmount(Number(amount), asset.symbol) ?? "0" : "0";
1399
1436
  const mustHaveQuote = !appFeesResolved || resolveAppFeeBps(
1400
1437
  appFees,
@@ -1617,7 +1654,6 @@ function ConfirmStep({
1617
1654
  ) })
1618
1655
  ] })
1619
1656
  ] }),
1620
- targetChain === HYPERCORE_CHAIN_ID && /* @__PURE__ */ jsx9(Callout, { variant: "warning", children: "First deposit to a new HyperCore account includes a ~1 USDC activation fee." }),
1621
1657
  error && /* @__PURE__ */ jsx9(Callout, { variant: "error", children: error }),
1622
1658
  /* @__PURE__ */ jsx9(
1623
1659
  Button,
@@ -1843,8 +1879,9 @@ function DepositNotification({
1843
1879
  status,
1844
1880
  txHash
1845
1881
  ]);
1846
- const sourceExplorerUrl = sourceChain === "unknown" ? void 0 : getExplorerTxUrl(sourceChain, txHash);
1847
- const destExplorerUrl = destinationTxHash ? getExplorerTxUrl(targetChain, destinationTxHash) : null;
1882
+ const explorerTxUrl = useExplorerTxUrl();
1883
+ const sourceExplorerUrl = sourceChain === "unknown" ? void 0 : explorerTxUrl(sourceChain, txHash);
1884
+ const destExplorerUrl = destinationTxHash ? explorerTxUrl(targetChainToChainId(targetChain), destinationTxHash) : null;
1848
1885
  const title = status === "complete" ? "Deposit completed" : status === "failed" ? "Deposit failed" : "Deposit received and processing\u2026";
1849
1886
  const subtitle = status === "complete" ? "Your deposit has been credited to your account." : status === "failed" ? "Your deposit could not be processed." : "Your deposit will be credited to your account shortly.";
1850
1887
  const statusIcon = status === "complete" ? /* @__PURE__ */ jsx10("div", { className: "rs-deposit-notification-badge rs-deposit-notification-badge--complete", children: /* @__PURE__ */ jsx10(CheckIcon, {}) }) : status === "failed" ? /* @__PURE__ */ jsx10("div", { className: "rs-deposit-notification-badge rs-deposit-notification-badge--failed", children: /* @__PURE__ */ jsx10(CloseIcon, {}) }) : /* @__PURE__ */ jsx10("div", { className: "rs-deposit-notification-badge rs-deposit-notification-badge--processing", children: /* @__PURE__ */ jsxs9(
@@ -2045,21 +2082,25 @@ function getDepositEventDetails(event) {
2045
2082
  function isSameRoute(sourceChain, sourceToken, targetChain, targetToken) {
2046
2083
  return sourceChain === targetChain && sourceToken.toLowerCase() === targetToken.toLowerCase();
2047
2084
  }
2048
- function chainLabel(chainId) {
2049
- return getChainName(chainId).replace(/\s+(One|Mainnet|Smart Chain)$/i, "");
2085
+ function chainLabel(chainId, catalogChain) {
2086
+ const name = catalogChain?.name ?? getChainName(chainId);
2087
+ return name.replace(/\s+(One|Mainnet|Smart Chain|Chain)$/i, "");
2050
2088
  }
2051
- function computeTokensForChain(chainId, topTokens) {
2089
+ function computeTokensForChain(chainId, topTokens, catalogChain) {
2052
2090
  const fromBackend = topTokens?.[String(chainId)]?.map((t) => t.symbol);
2053
- const all = fromBackend ?? (chainId === "solana" ? SOLANA_TOKENS.map((t) => t.symbol) : (
2054
- // HyperCore accepts USDC + USDT0 as origin tokens (native Hyperliquid L1
2055
- // spot transfers); it has no EVM source-chain matrix entry.
2056
- chainId === "hypercore" ? ["USDC", "USDT0"] : getTargetTokenSymbolsForChain(chainId)
2057
- ));
2058
- return all;
2059
- }
2060
- function resolveSourceTokenAddress(symbol, chainId, topTokens) {
2091
+ if (fromBackend) return fromBackend;
2092
+ if (chainId === "solana") return SOLANA_TOKENS.map((t) => t.symbol);
2093
+ if (chainId === "hypercore") return ["USDC", "USDT0"];
2094
+ const bundled = getBundledTargetTokens(chainId).map((t) => t.symbol);
2095
+ if (bundled.length > 0) return bundled;
2096
+ return Array.isArray(catalogChain?.supportedTokens) ? catalogChain.supportedTokens.map((t) => t.symbol) : [];
2097
+ }
2098
+ function resolveSourceTokenAddress(symbol, chainId, topTokens, catalogChain) {
2061
2099
  const top = topTokens?.[String(chainId)]?.find((t) => t.symbol === symbol);
2062
- return top?.address ?? getTokenAddress(symbol, chainId);
2100
+ if (top?.address) return top.address;
2101
+ const fromRegistry = getTokenAddress(symbol, chainId);
2102
+ if (fromRegistry) return fromRegistry;
2103
+ return Array.isArray(catalogChain?.supportedTokens) ? catalogChain.supportedTokens.find((t) => t.symbol === symbol)?.address : void 0;
2063
2104
  }
2064
2105
  function TokenGlyph({ symbol }) {
2065
2106
  return /* @__PURE__ */ jsx11(
@@ -2093,25 +2134,38 @@ function DepositAddressStep({
2093
2134
  const [topTokens, setTopTokens] = useState6(null);
2094
2135
  useEffect6(() => {
2095
2136
  let active = true;
2137
+ setTopTokens(null);
2096
2138
  service.getTopTokens().then((t) => {
2097
- if (active) setTopTokens(t);
2139
+ if (!active) return;
2140
+ setTopTokens(t);
2141
+ if (t) publishShortlistTokens(t);
2098
2142
  });
2099
2143
  return () => {
2100
2144
  active = false;
2101
2145
  };
2102
2146
  }, [service]);
2103
2147
  const BASE_CHAIN_ID2 = 8453;
2104
- const evmChainIds = useMemo3(() => getSupportedChainIds(), []);
2148
+ const evmChainIds = useDepositChainIds();
2149
+ const { catalog } = useChainCatalog();
2150
+ const catalogFor = useCallback2(
2151
+ (chain) => {
2152
+ if (!catalog) return void 0;
2153
+ const key = catalogKeyForChain(chain);
2154
+ return typeof key === "number" ? catalog.byChainId.get(key) : catalog.byCaip2.get(key);
2155
+ },
2156
+ [catalog]
2157
+ );
2105
2158
  const chainOptions = useMemo3(() => {
2159
+ const acceptsDeposits = (chain) => catalogFor(chain)?.deposit !== false;
2106
2160
  const options = [...evmChainIds];
2107
2161
  const extras = [];
2108
- if (hasSolana) extras.push("solana");
2109
- extras.push("hypercore");
2162
+ if (hasSolana && acceptsDeposits("solana")) extras.push("solana");
2163
+ if (acceptsDeposits("hypercore")) extras.push("hypercore");
2110
2164
  options.splice(1, 0, ...extras);
2111
2165
  return options.filter(
2112
- (chain) => topTokens?.[String(chain)]?.length !== 0
2166
+ (chain) => topTokens?.[String(chain)]?.length !== 0 && computeTokensForChain(chain, topTokens, catalogFor(chain)).length > 0
2113
2167
  );
2114
- }, [evmChainIds, hasSolana, topTokens]);
2168
+ }, [evmChainIds, hasSolana, topTokens, catalogFor]);
2115
2169
  const preferredChainId = (options) => options.includes(BASE_CHAIN_ID2) ? BASE_CHAIN_ID2 : options[0] ?? BASE_CHAIN_ID2;
2116
2170
  const [sourceChainId, setSourceChainId] = useState6(() => preferredChainId(chainOptions));
2117
2171
  useEffect6(() => {
@@ -2122,8 +2176,8 @@ function DepositAddressStep({
2122
2176
  const isSolana = sourceChainId === "solana";
2123
2177
  const isHyperCore = sourceChainId === "hypercore";
2124
2178
  const tokensForChain = useMemo3(
2125
- () => computeTokensForChain(sourceChainId, topTokens),
2126
- [sourceChainId, topTokens]
2179
+ () => computeTokensForChain(sourceChainId, topTokens, catalogFor(sourceChainId)),
2180
+ [sourceChainId, topTokens, catalogFor]
2127
2181
  );
2128
2182
  const defaultToken = pickFallbackToken(tokensForChain, "USDC");
2129
2183
  const [sourceTokenSymbol, setSourceTokenSymbol] = useState6(defaultToken);
@@ -2154,7 +2208,8 @@ function DepositAddressStep({
2154
2208
  const sourceTokenAddress = resolveSourceTokenAddress(
2155
2209
  sourceTokenSymbol,
2156
2210
  sourceChainId,
2157
- topTokens
2211
+ topTokens,
2212
+ catalogFor(sourceChainId)
2158
2213
  );
2159
2214
  if (!sourceTokenAddress) {
2160
2215
  setLiquidityHelper({ kind: "idle" });
@@ -2165,7 +2220,7 @@ function DepositAddressStep({
2165
2220
  service.checkLiquidity({
2166
2221
  sourceChainId,
2167
2222
  sourceToken: sourceTokenAddress,
2168
- destinationChainId: targetChain,
2223
+ destinationChainId: targetChainToCaip2(targetChain),
2169
2224
  destinationToken: targetToken,
2170
2225
  amount: "1"
2171
2226
  }).then((result) => {
@@ -2239,14 +2294,18 @@ function DepositAddressStep({
2239
2294
  }, [displayAddress, onCopyAddress]);
2240
2295
  const handleSelectChain = useCallback2(
2241
2296
  (nextChain) => {
2242
- const nextTokens = computeTokensForChain(nextChain, topTokens);
2297
+ const nextTokens = computeTokensForChain(
2298
+ nextChain,
2299
+ topTokens,
2300
+ catalogFor(nextChain)
2301
+ );
2243
2302
  setSourceChainId(nextChain);
2244
2303
  setSourceTokenSymbol(pickFallbackToken(nextTokens, sourceTokenSymbol));
2245
2304
  setChainDropdownOpen(false);
2246
2305
  setTokenDropdownOpen(false);
2247
2306
  setCopied(false);
2248
2307
  },
2249
- [sourceTokenSymbol, topTokens]
2308
+ [sourceTokenSymbol, topTokens, catalogFor]
2250
2309
  );
2251
2310
  const onDepositSubmittedRef = useRef5(onDepositSubmitted);
2252
2311
  onDepositSubmittedRef.current = onDepositSubmitted;
@@ -2375,7 +2434,7 @@ function DepositAddressStep({
2375
2434
  const handleNotificationDismiss = useCallback2((id) => {
2376
2435
  setNotifications((prev) => prev.filter((n) => n.id !== id));
2377
2436
  }, []);
2378
- const qrIconSrc = getChainIcon(sourceChainId);
2437
+ const qrIconSrc = catalogFor(sourceChainId)?.iconUrl ?? getChainIcon(sourceChainId);
2379
2438
  return /* @__PURE__ */ jsxs10("div", { className: "rs-screen rs-step--with-notifications", children: [
2380
2439
  /* @__PURE__ */ jsxs10("div", { className: "rs-screen-body", children: [
2381
2440
  /* @__PURE__ */ jsx11(BodyHeader, { icon: /* @__PURE__ */ jsx11(TransferCryptoIcon, {}), title: "Transfer crypto" }),
@@ -2396,11 +2455,11 @@ function DepositAddressStep({
2396
2455
  /* @__PURE__ */ jsx11(
2397
2456
  CdnIcon,
2398
2457
  {
2399
- src: getChainIcon(sourceChainId),
2458
+ src: catalogFor(sourceChainId)?.iconUrl ?? getChainIcon(sourceChainId),
2400
2459
  className: "rs-deposit-address-dropdown-icon"
2401
2460
  }
2402
2461
  ),
2403
- /* @__PURE__ */ jsx11("span", { children: chainLabel(sourceChainId) }),
2462
+ /* @__PURE__ */ jsx11("span", { children: chainLabel(sourceChainId, catalogFor(sourceChainId)) }),
2404
2463
  /* @__PURE__ */ jsx11(ChevronDownIcon, { className: "rs-deposit-address-dropdown-chevron" })
2405
2464
  ]
2406
2465
  }
@@ -2415,11 +2474,11 @@ function DepositAddressStep({
2415
2474
  /* @__PURE__ */ jsx11(
2416
2475
  CdnIcon,
2417
2476
  {
2418
- src: getChainIcon(chainId),
2477
+ src: catalogFor(chainId)?.iconUrl ?? getChainIcon(chainId),
2419
2478
  className: "rs-deposit-address-dropdown-icon"
2420
2479
  }
2421
2480
  ),
2422
- /* @__PURE__ */ jsx11("span", { children: chainLabel(chainId) })
2481
+ /* @__PURE__ */ jsx11("span", { children: chainLabel(chainId, catalogFor(chainId)) })
2423
2482
  ]
2424
2483
  },
2425
2484
  String(chainId)
@@ -2430,7 +2489,7 @@ function DepositAddressStep({
2430
2489
  /* @__PURE__ */ jsx11("span", { children: "Supported token" }),
2431
2490
  /* @__PURE__ */ jsxs10("span", { className: "rs-deposit-address-min", children: [
2432
2491
  "Min.$",
2433
- (targetChain === HYPERCORE_CHAIN_ID || isHyperCore ? Math.max(HYPERCORE_MIN_DEPOSIT_USD, uiConfig?.minDepositUsd ?? 0) : uiConfig?.minDepositUsd ?? 0.1).toFixed(2),
2492
+ (isHyperCoreDestination(targetChain) || isHyperCore ? Math.max(HYPERCORE_MIN_DEPOSIT_USD, uiConfig?.minDepositUsd ?? 0) : uiConfig?.minDepositUsd ?? 0.1).toFixed(2),
2434
2493
  /* @__PURE__ */ jsx11(Tooltip, { content: "Minimum deposit amount required for the selected chain.", children: /* @__PURE__ */ jsx11(
2435
2494
  InfoIcon,
2436
2495
  {
@@ -2505,7 +2564,6 @@ function DepositAddressStep({
2505
2564
  ]
2506
2565
  }
2507
2566
  ),
2508
- targetChain === HYPERCORE_CHAIN_ID && /* @__PURE__ */ jsx11(Callout, { variant: "warning", children: "HyperCore's first deposit to a new account includes a ~1 USDC activation fee \u2014 send at least 1 USDC or it will fail." }),
2509
2567
  /* @__PURE__ */ jsxs10(
2510
2568
  "div",
2511
2569
  {
@@ -2564,7 +2622,7 @@ function DepositAddressStep({
2564
2622
  /* @__PURE__ */ jsx11("strong", { children: "< 1 min" })
2565
2623
  ] })
2566
2624
  ] }),
2567
- /* @__PURE__ */ jsxs10("div", { className: "rs-price-impact-row", children: [
2625
+ liquidityHelper.kind !== "idle" && /* @__PURE__ */ jsxs10("div", { className: "rs-price-impact-row", children: [
2568
2626
  /* @__PURE__ */ jsx11("span", { className: "rs-price-impact-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx11(PlusCircleIcon, {}) }),
2569
2627
  /* @__PURE__ */ jsxs10("span", { className: "rs-price-impact-label", children: [
2570
2628
  "Max deposit:",
@@ -3906,7 +3964,7 @@ function SolanaAmountStep({
3906
3964
  return null;
3907
3965
  }
3908
3966
  }, [numericAmount, isSourceStablecoin, hasPricing, tokenPriceUsd, token.decimals]);
3909
- const minDepositUsd = targetChain === HYPERCORE_CHAIN_ID ? Math.max(HYPERCORE_MIN_DEPOSIT_USD, uiConfig?.minDepositUsd ?? 0) : uiConfig?.minDepositUsd ?? null;
3967
+ const minDepositUsd = isHyperCoreDestination(targetChain) ? Math.max(HYPERCORE_MIN_DEPOSIT_USD, uiConfig?.minDepositUsd ?? 0) : uiConfig?.minDepositUsd ?? null;
3910
3968
  const maxDepositUsd = uiConfig?.maxDepositUsd ?? null;
3911
3969
  const isBelowMin = minDepositUsd !== null && numericAmount > 0 && numericAmount < minDepositUsd;
3912
3970
  const isAboveMax = maxDepositUsd !== null && numericAmount > maxDepositUsd;
@@ -4048,7 +4106,6 @@ function SolanaAmountStep({
4048
4106
  /* @__PURE__ */ jsx20("span", { className: "rs-amount-detail-value", children: currencyFormatter.format(balanceAfterUsd) })
4049
4107
  ] })
4050
4108
  ] }),
4051
- targetChain === HYPERCORE_CHAIN_ID && /* @__PURE__ */ jsx20(Callout, { variant: "warning", children: "First deposit to a new HyperCore account includes a ~1 USDC activation fee." }),
4052
4109
  error && /* @__PURE__ */ jsx20(Callout, { variant: "error", children: error }),
4053
4110
  /* @__PURE__ */ jsx20(
4054
4111
  Button,
@@ -4191,11 +4248,12 @@ function SolanaConfirmStep({
4191
4248
  const rpcUrls = useRpcUrls();
4192
4249
  const [isSubmitting, setIsSubmitting] = useState11(false);
4193
4250
  const [error, setError] = useState11(null);
4194
- const targetSymbol = getTargetTokenSymbol(targetToken, targetChain);
4251
+ const targetChainId = targetChainToChainId(targetChain);
4252
+ const targetSymbol = getTargetTokenSymbol(targetToken, targetChainId);
4195
4253
  const sourceChainName = getChainName("solana");
4196
- const targetChainName = getChainName(targetChain);
4254
+ const targetChainName = getChainName(targetChainId);
4197
4255
  const sourceChainIcon = getChainIcon("solana");
4198
- const targetChainIcon = getChainIcon(targetChain);
4256
+ const targetChainIcon = getChainIcon(targetChainId);
4199
4257
  const feeSponsored = uiConfig?.feeSponsored ?? false;
4200
4258
  const feeTooltip = uiConfig?.feeTooltip ?? (feeSponsored ? "Network fees are sponsored for this deposit." : "Network fees apply.");
4201
4259
  const formattedAmount = sourceAmount && Number.isFinite(Number(sourceAmount)) ? formatTokenAmount(Number(sourceAmount), token.symbol) ?? "0" : "0";
@@ -4385,6 +4443,7 @@ import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
4385
4443
  function DappImportAssetSelectStep({
4386
4444
  sourceLabel,
4387
4445
  assets,
4446
+ incompleteSummary,
4388
4447
  onSelect
4389
4448
  }) {
4390
4449
  return /* @__PURE__ */ jsxs19("div", { className: "rs-screen", children: [
@@ -4397,6 +4456,7 @@ function DappImportAssetSelectStep({
4397
4456
  subtitle: "Pick the balance to import"
4398
4457
  }
4399
4458
  ),
4459
+ incompleteSummary && /* @__PURE__ */ jsx22("div", { className: "rs-asset-notice", role: "status", children: incompleteSummary }),
4400
4460
  /* @__PURE__ */ jsx22("div", { className: "rs-asset-list", children: assets.map((asset) => {
4401
4461
  const tokenAmount = asset.balance ? tokenFormatter.format(
4402
4462
  Number(asset.balance) / 10 ** asset.decimals
@@ -4435,7 +4495,8 @@ function DappImportAssetSelectStep({
4435
4495
  /* @__PURE__ */ jsx22("span", { className: "rs-asset-name", children: asset.symbol }),
4436
4496
  /* @__PURE__ */ jsxs19("span", { className: "rs-asset-chain", children: [
4437
4497
  "on ",
4438
- asset.sourceLabel
4498
+ asset.sourceLabel,
4499
+ asset.qualifier ? ` \xB7 ${asset.qualifier}` : ""
4439
4500
  ] })
4440
4501
  ] }),
4441
4502
  /* @__PURE__ */ jsxs19("div", { className: "rs-asset-balance-small", children: [
@@ -4649,6 +4710,188 @@ function composeFiatMethods(regional, fallbackMethods) {
4649
4710
  };
4650
4711
  }
4651
4712
 
4713
+ // src/core/dapp-imports/balance-source.ts
4714
+ function dappImportBalanceSource(asset) {
4715
+ if (!isDappImportAsset(asset)) return {};
4716
+ if (asset.balanceAddress) return { balanceAddress: asset.balanceAddress };
4717
+ if (asset.balance === void 0) return {};
4718
+ try {
4719
+ return { declaredBalance: BigInt(asset.balance) };
4720
+ } catch {
4721
+ return {};
4722
+ }
4723
+ }
4724
+
4725
+ // src/core/dapp-imports/aave/index.ts
4726
+ var PROVIDER_ID = "aave";
4727
+ var SOURCE_LABEL = "Aave";
4728
+ var POLICY_REFUSED = [
4729
+ "below_deposit_floor",
4730
+ "deposit_not_whitelisted"
4731
+ ];
4732
+ var aaveProvider = {
4733
+ id: PROVIDER_ID,
4734
+ sourceLabel: SOURCE_LABEL,
4735
+ async fetchAvailability({ eoa, backend, signal }) {
4736
+ if (!backend) {
4737
+ throw new Error("Aave positions require a backend connection");
4738
+ }
4739
+ const response = await backend.getPositions(eoa);
4740
+ if (signal?.aborted) return null;
4741
+ const assets = toImportableAssets(response.positions);
4742
+ const failures = response.failures ?? [];
4743
+ if (assets.length === 0) {
4744
+ if (failures.length > 0) {
4745
+ throw new Error(
4746
+ `Could not read Aave positions: ${failures.map((failure) => failure.reason).join("; ")}`
4747
+ );
4748
+ }
4749
+ return null;
4750
+ }
4751
+ const availability = {
4752
+ providerId: PROVIDER_ID,
4753
+ // Deliberately the sum over importable assets rather than
4754
+ // `response.totalUsd`: the latter counts positions this flow filters out,
4755
+ // so using it would show a balance the user then cannot find.
4756
+ totalUsd: assets.reduce((sum, asset) => sum + (asset.balanceUsd ?? 0), 0),
4757
+ assets,
4758
+ // Some markets read, some did not. Erroring would discard positions the
4759
+ // user can migrate right now — and with ~29 markets on a keyless API, one
4760
+ // failing is the expected case, so erroring would be the normal outcome.
4761
+ // The list therefore stands, marked as a floor. The upstream reason names
4762
+ // an internal market, so it is summarised rather than surfaced.
4763
+ ...failures.length > 0 ? {
4764
+ incomplete: {
4765
+ summary: failures.length === 1 ? "One Aave market couldn't be loaded, so a position may be missing." : `${failures.length} Aave markets couldn't be loaded, so positions may be missing.`
4766
+ }
4767
+ } : {}
4768
+ };
4769
+ return availability;
4770
+ },
4771
+ async executeTransfer({ walletClient, recipient, asset, amount, backend }) {
4772
+ if (!backend) {
4773
+ throw new Error("Aave withdrawals require a backend connection");
4774
+ }
4775
+ const metadata = asset.providerMetadata;
4776
+ const account = walletClient.account;
4777
+ const chain = walletClient.chain;
4778
+ if (!account || !chain) {
4779
+ throw new Error("Wallet not connected");
4780
+ }
4781
+ if (chain.id !== metadata.chainId) {
4782
+ throw new Error(
4783
+ `Switch to ${metadata.marketName} chain (${metadata.chainId}) to sign`
4784
+ );
4785
+ }
4786
+ const prepared = await backend.prepareUnwind({
4787
+ address: account.address,
4788
+ // The backend resolves the recipient from this account rather than
4789
+ // trusting a supplied address. `amount` is always explicit — expressing
4790
+ // "everything" is the backend's call, since only it knows whether sweeping
4791
+ // accrued interest could push the delivered amount past a whitelist
4792
+ // ceiling and get the proceeds rejected after the withdraw succeeded.
4793
+ account: recipient,
4794
+ market: metadata.market,
4795
+ chainId: metadata.chainId,
4796
+ asset: metadata.asset,
4797
+ amount: amount.toString()
4798
+ });
4799
+ if (prepared.recipient.toLowerCase() !== recipient.toLowerCase()) {
4800
+ throw new Error(
4801
+ "Aave withdrawal would send funds to an unexpected address"
4802
+ );
4803
+ }
4804
+ if (prepared.transaction.chainId !== metadata.chainId) {
4805
+ throw new Error("Aave withdrawal was prepared for a different chain");
4806
+ }
4807
+ const txHash = await walletClient.sendTransaction({
4808
+ account,
4809
+ chain,
4810
+ to: prepared.transaction.to,
4811
+ data: prepared.transaction.data,
4812
+ value: BigInt(prepared.transaction.value)
4813
+ });
4814
+ return {
4815
+ txHash,
4816
+ // Aave pays out the underlying straight to the deposit address — no
4817
+ // unwrap, no swap, so what arrives is what was supplied.
4818
+ sourceToken: metadata.asset,
4819
+ sourceSymbol: asset.symbol,
4820
+ sourceDecimals: asset.decimals
4821
+ };
4822
+ }
4823
+ };
4824
+ function toImportableAssets(positions) {
4825
+ const assets = [];
4826
+ for (const position of positions) {
4827
+ const chainId = parseEvmChainId(position.chain);
4828
+ if (chainId === null) continue;
4829
+ if (!CHAIN_BY_ID[chainId]) continue;
4830
+ if (BigInt(position.maxWithdrawable) <= 0n) continue;
4831
+ if (position.constraints.some((c) => POLICY_REFUSED.includes(c))) continue;
4832
+ assets.push(buildAsset(position, chainId));
4833
+ }
4834
+ return qualifyAmbiguousMarkets(assets);
4835
+ }
4836
+ function buildAsset(position, chainId) {
4837
+ const { asset, market } = position;
4838
+ const token = asset.address.toLowerCase();
4839
+ const metadata = {
4840
+ market: market.address,
4841
+ marketName: market.name,
4842
+ chainId,
4843
+ asset: asset.address
4844
+ };
4845
+ return {
4846
+ // Market-keyed, so one chain holding the same token in two markets yields
4847
+ // two distinct rows rather than one that silently shadows the other.
4848
+ id: `aave:${chainId}:${market.address.toLowerCase()}:${token}`,
4849
+ chainId,
4850
+ token,
4851
+ symbol: asset.symbol,
4852
+ // The market name, not a token description: it is what tells four Aave v3
4853
+ // markets on Ethereum apart.
4854
+ name: market.name,
4855
+ decimals: asset.decimals,
4856
+ // `maxWithdrawable`, NOT the supplied balance. The amount selector lets the
4857
+ // user pick up to this, and seeding it with the supplied balance would let
4858
+ // them choose above the cap and sign a withdraw the pool rejects.
4859
+ balance: position.maxWithdrawable,
4860
+ balanceUsd: withdrawableUsd(position),
4861
+ source: PROVIDER_ID,
4862
+ sourceLabel: SOURCE_LABEL,
4863
+ reviewLabel: `You withdraw ${asset.symbol} from Aave`,
4864
+ // Aave sends the underlying itself to the deposit address, so the token the
4865
+ // orchestrator sees land is the same one and on the same chain.
4866
+ depositToken: token,
4867
+ depositChainId: chainId,
4868
+ providerMetadata: metadata
4869
+ };
4870
+ }
4871
+ function qualifyAmbiguousMarkets(assets) {
4872
+ const counts = /* @__PURE__ */ new Map();
4873
+ for (const asset of assets) {
4874
+ const key = `${asset.chainId}:${asset.token}`;
4875
+ counts.set(key, (counts.get(key) ?? 0) + 1);
4876
+ }
4877
+ return assets.map(
4878
+ (asset) => (counts.get(`${asset.chainId}:${asset.token}`) ?? 0) > 1 ? {
4879
+ ...asset,
4880
+ qualifier: asset.providerMetadata.marketName
4881
+ } : asset
4882
+ );
4883
+ }
4884
+ function withdrawableUsd(position) {
4885
+ const amount = BigInt(position.amount);
4886
+ const withdrawable = BigInt(position.maxWithdrawable);
4887
+ if (amount === 0n) return 0;
4888
+ if (withdrawable === amount) return position.usdValue;
4889
+ const SCALE = 1000000n;
4890
+ const ratio = Number(withdrawable * SCALE / amount) / Number(SCALE);
4891
+ const usd = position.usdValue * ratio;
4892
+ return Number.isFinite(usd) ? usd : 0;
4893
+ }
4894
+
4652
4895
  // src/core/dapp-imports/polymarket/index.ts
4653
4896
  import { formatUnits as formatUnits6 } from "viem";
4654
4897
 
@@ -4819,11 +5062,10 @@ function buildPusdUnwrapCalls(recipient, amount) {
4819
5062
  }
4820
5063
 
4821
5064
  // src/core/dapp-imports/polymarket/index.ts
4822
- var PROVIDER_ID = "polymarket";
5065
+ var PROVIDER_ID2 = "polymarket";
4823
5066
  var polymarketProvider = {
4824
- id: PROVIDER_ID,
5067
+ id: PROVIDER_ID2,
4825
5068
  sourceLabel: "Polymarket",
4826
- chainId: POLYMARKET_POLYGON_CHAIN_ID,
4827
5069
  async fetchAvailability({ eoa, getPublicClient: getPublicClient2, signal }) {
4828
5070
  const proxyWallet = await fetchPolymarketProxyWallet(eoa, signal);
4829
5071
  if (!proxyWallet) return null;
@@ -4846,17 +5088,17 @@ var polymarketProvider = {
4846
5088
  const assets = [];
4847
5089
  if (balances.pusd > 0n) {
4848
5090
  assets.push(
4849
- buildAsset({ tokenKind: "pusd", proxyWallet, walletKind, balance: balances.pusd })
5091
+ buildAsset2({ tokenKind: "pusd", proxyWallet, walletKind, balance: balances.pusd })
4850
5092
  );
4851
5093
  }
4852
5094
  if (balances.usdce > 0n) {
4853
5095
  assets.push(
4854
- buildAsset({ tokenKind: "usdce", proxyWallet, walletKind, balance: balances.usdce })
5096
+ buildAsset2({ tokenKind: "usdce", proxyWallet, walletKind, balance: balances.usdce })
4855
5097
  );
4856
5098
  }
4857
5099
  const totalUsd = assets.reduce((sum, a) => sum + (a.balanceUsd ?? 0), 0);
4858
5100
  const availability = {
4859
- providerId: PROVIDER_ID,
5101
+ providerId: PROVIDER_ID2,
4860
5102
  totalUsd,
4861
5103
  assets
4862
5104
  };
@@ -4904,7 +5146,7 @@ var polymarketProvider = {
4904
5146
  };
4905
5147
  }
4906
5148
  };
4907
- function buildAsset(params) {
5149
+ function buildAsset2(params) {
4908
5150
  const { tokenKind, proxyWallet, walletKind, balance } = params;
4909
5151
  const isPusd = tokenKind === "pusd";
4910
5152
  const tokenAddress = isPusd ? POLYMARKET_PUSD_ADDRESS : POLYMARKET_USDCE_ADDRESS;
@@ -4921,8 +5163,11 @@ function buildAsset(params) {
4921
5163
  decimals: 6,
4922
5164
  balance: balance.toString(),
4923
5165
  balanceUsd: Number.isFinite(balanceUsd) ? balanceUsd : 0,
4924
- source: PROVIDER_ID,
5166
+ source: PROVIDER_ID2,
4925
5167
  sourceLabel: "Polymarket",
5168
+ // The proxy wallet really does hold this ERC-20, so the amount step reads it
5169
+ // live rather than trusting the figure from the availability fetch.
5170
+ balanceAddress: proxyWallet,
4926
5171
  reviewLabel: isPusd ? "You send pUSD from Polymarket" : "You send USDC.e from Polymarket",
4927
5172
  // pUSD unwraps to USDC.e via the offramp; USDC.e is what actually
4928
5173
  // arrives at the smart account, so it's also what the orchestrator
@@ -4934,7 +5179,10 @@ function buildAsset(params) {
4934
5179
  }
4935
5180
 
4936
5181
  // src/core/dapp-imports/registry.ts
4937
- var DAPP_IMPORT_PROVIDERS = [polymarketProvider];
5182
+ var DAPP_IMPORT_PROVIDERS = [
5183
+ polymarketProvider,
5184
+ aaveProvider
5185
+ ];
4938
5186
  function getEnabledProviders(config) {
4939
5187
  if (!config) return [];
4940
5188
  return DAPP_IMPORT_PROVIDERS.filter(
@@ -6353,7 +6601,8 @@ function DepositFlow({
6353
6601
  selectedWalletId
6354
6602
  ]);
6355
6603
  const setupChainId = typeof targetChain === "number" && !isVirtualDestination(targetChain) ? targetChain : typeof defaultSourceChain === "number" ? defaultSourceChain : base.id;
6356
- const targetSymbol = getTargetTokenSymbol(targetToken, targetChain);
6604
+ const targetChainId = targetChainToChainId(targetChain);
6605
+ const targetSymbol = getTargetTokenSymbol(targetToken, targetChainId);
6357
6606
  const isTargetStablecoin = isStablecoinSymbol(targetSymbol);
6358
6607
  const targetMarketPriceRef = useRef8(null);
6359
6608
  useEffect11(() => {
@@ -6363,7 +6612,7 @@ function DepositFlow({
6363
6612
  }
6364
6613
  let cancelled = false;
6365
6614
  fetchTokenPriceUsd(service, {
6366
- chainId: targetChain,
6615
+ chainId: targetChainId,
6367
6616
  address: targetToken,
6368
6617
  symbol: targetSymbol
6369
6618
  }).then((price) => {
@@ -6636,8 +6885,8 @@ function DepositFlow({
6636
6885
  pred_balance: totalBalanceUsd
6637
6886
  });
6638
6887
  } else if (effectiveStep.type === "deposit-address") {
6639
- const chainName = getChainName(targetChain);
6640
- const tokenSymbol = getTargetTokenSymbol(targetToken, targetChain);
6888
+ const chainName = getChainName(targetChainId);
6889
+ const tokenSymbol = getTargetTokenSymbol(targetToken, targetChainId);
6641
6890
  onEventRef.current?.({
6642
6891
  type: "deposit_modal_transfer_crypto_open",
6643
6892
  default_chain: chainName,
@@ -6645,7 +6894,7 @@ function DepositFlow({
6645
6894
  pred_balance: totalBalanceUsd
6646
6895
  });
6647
6896
  } else if (effectiveStep.type === "amount" && stepSendToken) {
6648
- const receiveSymbol = getTargetTokenSymbol(targetToken, targetChain);
6897
+ const receiveSymbol = getTargetTokenSymbol(targetToken, targetChainId);
6649
6898
  onEventRef.current?.({
6650
6899
  type: "deposit_modal_connected_wallet_enter_value_open",
6651
6900
  send_token: stepSendToken,
@@ -6768,6 +7017,9 @@ function DepositFlow({
6768
7017
  return null;
6769
7018
  }
6770
7019
  },
7020
+ // Providers whose positions live behind the Rhinestone API rather than
7021
+ // an RPC (Aave) read them through here.
7022
+ backend: service,
6771
7023
  signal: controller.signal
6772
7024
  }).then((availability) => {
6773
7025
  if (controller.signal.aborted) return;
@@ -6792,7 +7044,8 @@ function DepositFlow({
6792
7044
  enabledDappImportProviders,
6793
7045
  dappImportAttemptNonce,
6794
7046
  storeApi,
6795
- rpcUrls
7047
+ rpcUrls,
7048
+ service
6796
7049
  ]);
6797
7050
  useLayoutEffect2(() => {
6798
7051
  if (!initialAssetMigrationProvider) return;
@@ -7374,7 +7627,7 @@ function DepositFlow({
7374
7627
  );
7375
7628
  const handleSolanaAmountContinue = useCallback7(
7376
7629
  (token, sourceAmount, inputAmountUsd) => {
7377
- const targetSym = getTargetTokenSymbol(targetToken, targetChain);
7630
+ const targetSym = getTargetTokenSymbol(targetToken, targetChainId);
7378
7631
  const isTargetStable = isStablecoinSymbol(targetSym);
7379
7632
  const targetTokenPriceUsd = isTargetStable ? 1 : targetMarketPriceRef.current;
7380
7633
  logFlow("solana:amount:continue", {
@@ -7452,7 +7705,7 @@ function DepositFlow({
7452
7705
  (amount, targetAmount, balance) => {
7453
7706
  const entry = storeApi.getState().setup;
7454
7707
  if (entry.status !== "ready") return;
7455
- const targetSym = getTargetTokenSymbol(targetToken, targetChain);
7708
+ const targetSym = getTargetTokenSymbol(targetToken, targetChainId);
7456
7709
  const isTargetStable = isStablecoinSymbol(targetSym);
7457
7710
  const targetTokenPriceUsd = isTargetStable ? 1 : targetMarketPriceRef.current;
7458
7711
  storeApi.dispatch({
@@ -7728,8 +7981,8 @@ function DepositFlow({
7728
7981
  onDepositComplete: handleDepositComplete,
7729
7982
  onDepositFailed: handleDepositFailed,
7730
7983
  onCopyAddress: () => {
7731
- const chainName = getChainName(targetChain);
7732
- const tokenSymbol = getTargetTokenSymbol(targetToken, targetChain);
7984
+ const chainName = getChainName(targetChainId);
7985
+ const tokenSymbol = getTargetTokenSymbol(targetToken, targetChainId);
7733
7986
  onEvent?.({
7734
7987
  type: "deposit_modal_transfer_crypto_cta_click",
7735
7988
  default_chain: chainName,
@@ -7915,8 +8168,8 @@ function DepositFlow({
7915
8168
  defaultAmount: effectiveStep.inputAmountUsd,
7916
8169
  uiConfig,
7917
8170
  targetChain,
7918
- targetChainName: getChainName(targetChain),
7919
- targetTokenSymbol: getTargetTokenSymbol(targetToken, targetChain),
8171
+ targetChainName: getChainName(targetChainId),
8172
+ targetTokenSymbol: getTargetTokenSymbol(targetToken, targetChainId),
7920
8173
  appBalanceUsd,
7921
8174
  onContinue: handleSolanaAmountContinue,
7922
8175
  debug
@@ -8096,6 +8349,7 @@ function DepositFlow({
8096
8349
  {
8097
8350
  sourceLabel: activeDappImportAvailability.assets[0]?.sourceLabel ?? activeDappImportProvider.sourceLabel,
8098
8351
  assets: activeDappImportAvailability.assets,
8352
+ incompleteSummary: activeDappImportAvailability.incomplete?.summary,
8099
8353
  onSelect: handleDappImportAssetSelected
8100
8354
  }
8101
8355
  ),
@@ -8105,7 +8359,7 @@ function DepositFlow({
8105
8359
  walletClient: signerContext.walletClient,
8106
8360
  publicClient: getReadClientForChain(effectiveStep.asset.chainId),
8107
8361
  address: ownerAddress,
8108
- balanceAddress: isDappImportAsset(effectiveStep.asset) ? effectiveStep.asset.providerMetadata.proxyWallet : void 0,
8362
+ ...dappImportBalanceSource(effectiveStep.asset),
8109
8363
  asset: effectiveStep.asset,
8110
8364
  defaultAmount: effectiveStep.inputAmountUsd ?? defaultAmount,
8111
8365
  switchChain: signerContext.switchChain,
@@ -8116,7 +8370,7 @@ function DepositFlow({
8116
8370
  service,
8117
8371
  onContinue: handleAmountContinue,
8118
8372
  onCtaClick: (ctaName) => {
8119
- const receiveSymbol = getTargetTokenSymbol(targetToken, targetChain);
8373
+ const receiveSymbol = getTargetTokenSymbol(targetToken, targetChainId);
8120
8374
  onEvent?.({
8121
8375
  type: "deposit_modal_connected_wallet_enter_value_cta_click",
8122
8376
  send_token: effectiveStep.asset.symbol,
@@ -8152,8 +8406,11 @@ function DepositFlow({
8152
8406
  const result = await activeDappImportProvider.executeTransfer(
8153
8407
  {
8154
8408
  walletClient: signerContext.walletClient,
8409
+ // The asset's chain: a provider's assets can span chains
8410
+ // (Aave positions exist on every deposit-enabled chain), so
8411
+ // there is no single provider-level chain to read from.
8155
8412
  publicClient: getReadClientForChain(
8156
- activeDappImportProvider.chainId
8413
+ effectiveStep.asset.chainId
8157
8414
  ),
8158
8415
  recipient: effectiveStep.smartAccount,
8159
8416
  asset: effectiveStep.asset,
@@ -8492,7 +8749,7 @@ DepositHistoryPanel.displayName = "DepositHistoryPanel";
8492
8749
  // src/DepositModal.tsx
8493
8750
  import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
8494
8751
  var ReownDepositInner = lazy2(
8495
- () => import("./DepositModalReown-JUJI7UHE.mjs").then((m) => ({ default: m.DepositModalReown }))
8752
+ () => import("./DepositModalReown-6RVLEM3B.mjs").then((m) => ({ default: m.DepositModalReown }))
8496
8753
  );
8497
8754
  function sortByCreatedAtDesc(items) {
8498
8755
  return [...items].sort((a, b) => {
@@ -8586,7 +8843,7 @@ function DepositModalInner({
8586
8843
  const cursorRef = useRef9(null);
8587
8844
  const historyStaleRef = useRef9(false);
8588
8845
  const historyLoadedRef = useRef9(false);
8589
- const targetChain = targetChainProp === "solana" ? "solana" : getChainId(targetChainProp);
8846
+ const targetChain = targetChainProp === "solana" || targetChainProp === HYPERCORE_SPOT_CAIP2 ? targetChainProp : getChainId(targetChainProp);
8590
8847
  const sourceChain = sourceChainProp ? getChainId(sourceChainProp) : void 0;
8591
8848
  const rpcUrls = useStableRpcUrls(rpcUrlsProp);
8592
8849
  const service = useMemo9(
@@ -8741,7 +8998,7 @@ function DepositModalInner({
8741
8998
  const canGoBack = backHandler !== void 0;
8742
8999
  const hideHeaderChrome = swappedImmersive;
8743
9000
  const modalClassName = `rs-modal${hideHeaderChrome ? " rs-modal--swapped-iframe" : ""}`;
8744
- return /* @__PURE__ */ jsx27(RpcUrlsProvider, { value: rpcUrls, children: /* @__PURE__ */ jsx27(DepositStoreProvider, { store, children: /* @__PURE__ */ jsx27(
9001
+ return /* @__PURE__ */ jsx27(RpcUrlsProvider, { value: rpcUrls, children: /* @__PURE__ */ jsx27(ChainCatalogProvider, { service, rpcUrls, children: /* @__PURE__ */ jsx27(DepositStoreProvider, { store, children: /* @__PURE__ */ jsx27(
8745
9002
  Modal,
8746
9003
  {
8747
9004
  isOpen,
@@ -8840,7 +9097,7 @@ function DepositModalInner({
8840
9097
  )
8841
9098
  ] })
8842
9099
  }
8843
- ) }) });
9100
+ ) }) }) });
8844
9101
  }
8845
9102
 
8846
9103
  export {