@unifold/connect-react 0.1.64 → 0.1.66

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.
package/dist/index.mjs CHANGED
@@ -1326,6 +1326,17 @@ var ArrowUpDown = createLucideIcon("ArrowUpDown", [
1326
1326
  ["path", { d: "M7 4v16", key: "1glfcx" }]
1327
1327
  ]);
1328
1328
 
1329
+ // ../../node_modules/.pnpm/lucide-react@0.454.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/bitcoin.js
1330
+ var Bitcoin = createLucideIcon("Bitcoin", [
1331
+ [
1332
+ "path",
1333
+ {
1334
+ d: "M11.767 19.089c4.924.868 6.14-6.025 1.216-6.894m-1.216 6.894L5.86 18.047m5.908 1.042-.347 1.97m1.563-8.864c4.924.869 6.14-6.025 1.215-6.893m-1.215 6.893-3.94-.694m5.155-6.2L8.29 4.26m5.908 1.042.348-1.97M7.48 20.364l3.126-17.727",
1335
+ key: "yr8idg"
1336
+ }
1337
+ ]
1338
+ ]);
1339
+
1329
1340
  // ../../node_modules/.pnpm/lucide-react@0.454.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/check.js
1330
1341
  var Check = createLucideIcon("Check", [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]]);
1331
1342
 
@@ -7004,6 +7015,29 @@ async function getDepositQuote(request, publishableKey) {
7004
7015
  const json = await response.json();
7005
7016
  return json.data;
7006
7017
  }
7018
+ async function buildHypercoreTransaction(request, publishableKey) {
7019
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
7020
+ validatePublishableKey(pk);
7021
+ const response = await fetch(
7022
+ `${API_BASE_URL}/v1/public/transactions/hypercore/build`,
7023
+ {
7024
+ method: "POST",
7025
+ headers: {
7026
+ accept: "application/json",
7027
+ "x-publishable-key": pk,
7028
+ "Content-Type": "application/json"
7029
+ },
7030
+ body: JSON.stringify(request)
7031
+ }
7032
+ );
7033
+ if (!response.ok) {
7034
+ const error = await response.json().catch(() => ({ message: response.statusText }));
7035
+ throw new Error(
7036
+ `Failed to build HyperCore transaction: ${error.message || response.statusText}`
7037
+ );
7038
+ }
7039
+ return response.json();
7040
+ }
7007
7041
  async function getCashAppLimits(currency = "usd", publishableKey) {
7008
7042
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
7009
7043
  validatePublishableKey(pk);
@@ -7069,6 +7103,29 @@ async function getCashAppSessionStatus(externalId, publishableKey) {
7069
7103
  }
7070
7104
  return response.json();
7071
7105
  }
7106
+ async function sendHypercoreTransaction(request, publishableKey) {
7107
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
7108
+ validatePublishableKey(pk);
7109
+ const response = await fetch(
7110
+ `${API_BASE_URL}/v1/public/transactions/hypercore/send`,
7111
+ {
7112
+ method: "POST",
7113
+ headers: {
7114
+ accept: "application/json",
7115
+ "x-publishable-key": pk,
7116
+ "Content-Type": "application/json"
7117
+ },
7118
+ body: JSON.stringify(request)
7119
+ }
7120
+ );
7121
+ if (!response.ok) {
7122
+ const error = await response.json().catch(() => ({ message: response.statusText }));
7123
+ throw new Error(
7124
+ `Failed to send HyperCore transaction: ${error.message || response.statusText}`
7125
+ );
7126
+ }
7127
+ return response.json();
7128
+ }
7072
7129
  var DepositEventType = /* @__PURE__ */ ((DepositEventType2) => {
7073
7130
  DepositEventType2["ONRAMP_SESSION_CREATED"] = "onramp_session.created";
7074
7131
  return DepositEventType2;
@@ -13596,6 +13653,22 @@ function clearStoredWalletState() {
13596
13653
  } catch {
13597
13654
  }
13598
13655
  }
13656
+ var LAST_OPENED_WALLET_KEY = "unifold_last_opened_wallet";
13657
+ function getLastOpenedWallet() {
13658
+ if (typeof window === "undefined") return void 0;
13659
+ try {
13660
+ return localStorage.getItem(LAST_OPENED_WALLET_KEY) ?? void 0;
13661
+ } catch {
13662
+ return void 0;
13663
+ }
13664
+ }
13665
+ function setLastOpenedWallet(walletId) {
13666
+ if (typeof window === "undefined") return;
13667
+ try {
13668
+ localStorage.setItem(LAST_OPENED_WALLET_KEY, walletId);
13669
+ } catch {
13670
+ }
13671
+ }
13599
13672
  var MOBILE_VIEWPORT_MEDIA_QUERY = "(max-width: 768px)";
13600
13673
  function isMobileViewport() {
13601
13674
  if (typeof window === "undefined") return false;
@@ -14401,7 +14474,7 @@ function DepositHeader({
14401
14474
  setShowBalanceSkeleton(false);
14402
14475
  return;
14403
14476
  }
14404
- const supportedChainTypes = ["ethereum", "solana", "bitcoin"];
14477
+ const supportedChainTypes = ["ethereum", "solana", "bitcoin", "n1"];
14405
14478
  if (!supportedChainTypes.includes(
14406
14479
  balanceChainType
14407
14480
  )) {
@@ -24419,7 +24492,7 @@ function useHypercoreActivation(params) {
24419
24492
  publishableKey,
24420
24493
  enabled = true
24421
24494
  } = params;
24422
- const isHypercore2 = destinationChainId === HYPERCORE_CHAIN_ID;
24495
+ const isHypercore2 = String(destinationChainId) === HYPERCORE_CHAIN_ID;
24423
24496
  const recipient = recipientAddress?.trim() ?? "";
24424
24497
  const source = sourceAddress?.trim() ?? "";
24425
24498
  const hasAddresses = !!recipient && !!source;
@@ -25565,6 +25638,46 @@ function TransferCryptoDoubleInput({
25565
25638
  }
25566
25639
  ) });
25567
25640
  }
25641
+ function isHypercoreChain(chainId) {
25642
+ return chainId === HYPERCORE_CHAIN_ID;
25643
+ }
25644
+ async function sendHypercoreEvmTransfer(params) {
25645
+ const {
25646
+ provider,
25647
+ fromAddress,
25648
+ recipientAddress,
25649
+ sourceTokenAddress,
25650
+ amount,
25651
+ publishableKey
25652
+ } = params;
25653
+ const currentChainHex = await provider.request({
25654
+ method: "eth_chainId",
25655
+ params: []
25656
+ });
25657
+ const activeChainId = String(parseInt(currentChainHex, 16));
25658
+ const buildResult = await buildHypercoreTransaction(
25659
+ {
25660
+ signature_chain_id: activeChainId,
25661
+ recipient_address: recipientAddress,
25662
+ token_address: sourceTokenAddress,
25663
+ amount
25664
+ },
25665
+ publishableKey
25666
+ );
25667
+ const signature = await provider.request({
25668
+ method: "eth_signTypedData_v4",
25669
+ params: [fromAddress, JSON.stringify(buildResult.typed_data)]
25670
+ });
25671
+ await sendHypercoreTransaction(
25672
+ {
25673
+ action_payload: buildResult.action_payload,
25674
+ signature,
25675
+ nonce: buildResult.nonce
25676
+ },
25677
+ publishableKey
25678
+ );
25679
+ return { signature };
25680
+ }
25568
25681
  function useDepositQuote(params) {
25569
25682
  const {
25570
25683
  publishableKey,
@@ -25972,7 +26085,8 @@ function EnterAmountView({
25972
26085
  onClose,
25973
26086
  quickSelectMode,
25974
26087
  checkoutAmountUsd,
25975
- checkoutReceivedUsd
26088
+ checkoutReceivedUsd,
26089
+ footer
25976
26090
  }) {
25977
26091
  const { colors: colors2, fonts, components } = useTheme();
25978
26092
  const isCheckout = !!checkoutAmountUsd;
@@ -26228,6 +26342,7 @@ function EnterAmountView({
26228
26342
  )
26229
26343
  ] })
26230
26344
  ] }),
26345
+ footer && /* @__PURE__ */ jsx51("div", { className: "uf-shrink-0 uf-pt-2", children: footer }),
26231
26346
  /* @__PURE__ */ jsx51("div", { className: "uf-shrink-0 uf-pt-2", children: /* @__PURE__ */ jsx51(
26232
26347
  "button",
26233
26348
  {
@@ -26677,7 +26792,7 @@ var WALLET_ICONS3 = {
26677
26792
  };
26678
26793
  var FALLBACK_WALLET_DEFINITIONS = [
26679
26794
  { id: "phantom", name: "Phantom", networks: ["ethereum", "solana"], installUrl: "https://phantom.app/", supportsMobileBrowse: true },
26680
- { id: "coinbase", name: "Coinbase Wallet", networks: ["ethereum", "solana"], installUrl: "https://www.coinbase.com/wallet", supportsMobileBrowse: true },
26795
+ { id: "coinbase", name: "Coinbase Wallet", networks: ["ethereum"], installUrl: "https://www.coinbase.com/wallet", supportsMobileBrowse: true },
26681
26796
  { id: "trust", name: "Trust Wallet", networks: ["ethereum", "solana"], installUrl: "https://trustwallet.com/", supportsMobileBrowse: true },
26682
26797
  { id: "metamask", name: "MetaMask", networks: ["ethereum"], installUrl: "https://metamask.io/download/", supportsMobileBrowse: true },
26683
26798
  { id: "rainbow", name: "Rainbow", networks: ["ethereum"], installUrl: "https://rainbow.me/", supportsMobileBrowse: true },
@@ -26737,7 +26852,7 @@ function getLegacyEvmProviders() {
26737
26852
  okxEthereum: win.okxwallet
26738
26853
  };
26739
26854
  }
26740
- function detectAvailableWallets(definitions, filterChainType) {
26855
+ function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
26741
26856
  const solProviders = getSolanaProviders();
26742
26857
  const legacyEvm = getLegacyEvmProviders();
26743
26858
  const eip6963List = getEip6963Providers();
@@ -26763,7 +26878,7 @@ function detectAvailableWallets(definitions, filterChainType) {
26763
26878
  return false;
26764
26879
  }
26765
26880
  });
26766
- return definitions.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
26881
+ const sorted = definitions.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
26767
26882
  let isInstalled = false;
26768
26883
  const detectedNetworks = [];
26769
26884
  switch (wallet.id) {
@@ -26786,8 +26901,6 @@ function detectAvailableWallets(definitions, filterChainType) {
26786
26901
  isInstalled = true;
26787
26902
  detectedNetworks.push("ethereum");
26788
26903
  }
26789
- if (solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana) detectedNetworks.push("solana");
26790
- if (isInstalled && wallet.networks.includes("solana") && !detectedNetworks.includes("solana")) detectedNetworks.push("solana");
26791
26904
  break;
26792
26905
  case "trust":
26793
26906
  if (hasEip6963("trust") || legacyEvm.trustEthereum || legacyEvm.ethereum?.isTrust || win?.trustwallet) {
@@ -26824,11 +26937,17 @@ function detectAvailableWallets(definitions, filterChainType) {
26824
26937
  }
26825
26938
  return { ...wallet, isInstalled, detectedNetworks };
26826
26939
  }).sort((a, b) => {
26940
+ if (recentWalletId) {
26941
+ const aRecent = a.id === recentWalletId ? 1 : 0;
26942
+ const bRecent = b.id === recentWalletId ? 1 : 0;
26943
+ if (aRecent !== bRecent) return bRecent - aRecent;
26944
+ }
26827
26945
  if (a.isInstalled && !b.isInstalled) return -1;
26828
26946
  if (!a.isInstalled && b.isInstalled) return 1;
26829
26947
  if (a.isInstalled && b.isInstalled) return b.networks.length - a.networks.length;
26830
26948
  return 0;
26831
26949
  });
26950
+ return sorted;
26832
26951
  }
26833
26952
  function WalletConnect({
26834
26953
  walletInfo: initialWalletInfo,
@@ -26903,9 +27022,15 @@ function WalletConnect({
26903
27022
  })) : FALLBACK_WALLET_DEFINITIONS,
26904
27023
  [backendWallets]
26905
27024
  );
27025
+ const [recentWalletId, setRecentWalletIdState] = React302.useState(getLastOpenedWallet);
27026
+ React302.useEffect(() => {
27027
+ if (view === "select_wallet") {
27028
+ setRecentWalletIdState(getLastOpenedWallet());
27029
+ }
27030
+ }, [view]);
26906
27031
  const availableWallets = React302.useMemo(
26907
- () => detectAvailableWallets(walletDefinitions),
26908
- [walletDefinitions, eip6963ProviderCount]
27032
+ () => detectAvailableWallets(walletDefinitions, recentWalletId),
27033
+ [walletDefinitions, eip6963ProviderCount, recentWalletId]
26909
27034
  );
26910
27035
  const [isMobile, setIsMobile] = React302.useState(false);
26911
27036
  React302.useEffect(() => {
@@ -26965,7 +27090,7 @@ function WalletConnect({
26965
27090
  const chainType = activeDepositWallet?.chain_type ?? "ethereum";
26966
27091
  const recipientAddress = activeDepositWallet?.address ?? "";
26967
27092
  const isCheckoutMode = !!checkoutAmountUsd;
26968
- const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
27093
+ const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
26969
27094
  const transitionTo = React302.useCallback((nextView) => {
26970
27095
  if (nextView === viewRef.current) return;
26971
27096
  setIsTransitioning(true);
@@ -26989,6 +27114,8 @@ function WalletConnect({
26989
27114
  );
26990
27115
  if (res.deeplink) {
26991
27116
  setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
27117
+ setLastOpenedWallet(wallet.id);
27118
+ setRecentWalletIdState(wallet.id);
26992
27119
  setAwaitingMobileDeposit(true);
26993
27120
  transitionTo("mobile_redirect");
26994
27121
  window.location.href = res.deeplink;
@@ -27049,6 +27176,8 @@ function WalletConnect({
27049
27176
  const handleConnectWallet = async (wallet, network) => {
27050
27177
  setConnectingNetwork(network);
27051
27178
  transitionTo("connecting");
27179
+ setLastOpenedWallet(wallet.id);
27180
+ setRecentWalletIdState(wallet.id);
27052
27181
  setWalletError(null);
27053
27182
  setIsWalletConnecting(true);
27054
27183
  try {
@@ -27153,6 +27282,13 @@ function WalletConnect({
27153
27282
  }
27154
27283
  };
27155
27284
  const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
27285
+ const { needsActivation: hypercoreNeedsActivation, activationFee: hypercoreActivationFee, sponsored: hypercoreActivationSponsored } = useHypercoreActivation({
27286
+ recipientAddress,
27287
+ sourceAddress: activeWalletInfo?.address,
27288
+ destinationChainId: selectedToken?.chain_id,
27289
+ publishableKey,
27290
+ enabled: !!activeWalletInfo && !!recipientAddress
27291
+ });
27156
27292
  const effectiveDestinationAmount = React302.useMemo(() => {
27157
27293
  if (!checkoutRemainingBaseUnits || checkoutRemainingBaseUnits === "0") return "0";
27158
27294
  if (!checkoutAmountUsd) return checkoutRemainingBaseUnits;
@@ -27257,7 +27393,7 @@ function WalletConnect({
27257
27393
  let cancelled = false;
27258
27394
  setIsLoading(true);
27259
27395
  setError(null);
27260
- const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" ? "ethereum" : activeDepositWallet.chain_type;
27396
+ const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" ? "ethereum" : activeDepositWallet.chain_type;
27261
27397
  getAddressBalances(activeWalletInfo.address, sct, publishableKey).then((response) => {
27262
27398
  if (cancelled) return;
27263
27399
  const nonZero = response.balances.filter((b) => b.amount !== "0");
@@ -27423,9 +27559,16 @@ function WalletConnect({
27423
27559
  const [integerPart = "0", decimalPart = ""] = amountStr.trim().split(".");
27424
27560
  return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
27425
27561
  };
27426
- const sendEthereumTransaction = async (token, amountStr) => {
27427
- if (!recipientAddress || !/^0x[a-fA-F0-9]{40}$/.test(recipientAddress)) throw new Error(`Invalid recipient address.`);
27428
- const walletIdMap = { "phantom-ethereum": "phantom", coinbase: "coinbase", trust: "trust", okx: "okx", rainbow: "rainbow", rabby: "rabby", metamask: "metamask" };
27562
+ const resolveEvmProvider = () => {
27563
+ const walletIdMap = {
27564
+ "phantom-ethereum": "phantom",
27565
+ coinbase: "coinbase",
27566
+ trust: "trust",
27567
+ okx: "okx",
27568
+ rainbow: "rainbow",
27569
+ rabby: "rabby",
27570
+ metamask: "metamask"
27571
+ };
27429
27572
  const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
27430
27573
  const eip6963Match = findProviderByWalletId(lookupId);
27431
27574
  let provider = eip6963Match?.provider;
@@ -27434,6 +27577,11 @@ function WalletConnect({
27434
27577
  else if (walletInfo.type === "coinbase") provider = window.coinbaseWalletExtension || window.ethereum;
27435
27578
  else provider = window.ethereum;
27436
27579
  }
27580
+ return provider;
27581
+ };
27582
+ const sendEthereumTransaction = async (token, amountStr) => {
27583
+ if (!recipientAddress || !/^0x[a-fA-F0-9]{40}$/.test(recipientAddress)) throw new Error(`Invalid recipient address.`);
27584
+ const provider = resolveEvmProvider();
27437
27585
  if (!provider) throw new Error("Ethereum wallet not found");
27438
27586
  const currentChainIdHex = await provider.request({ method: "eth_chainId", params: [] });
27439
27587
  if (parseInt(currentChainIdHex, 16).toString() !== token.chain_id) {
@@ -27498,6 +27646,19 @@ function WalletConnect({
27498
27646
  const resp = await sendSolanaTransaction({ chain_id: "mainnet", signed_transaction: btoa(bs) }, publishableKey);
27499
27647
  return resp.signature;
27500
27648
  };
27649
+ const sendHypercoreDeposit = async (token, amountStr) => {
27650
+ const provider = resolveEvmProvider();
27651
+ if (!provider) throw new Error("Ethereum wallet not found");
27652
+ const { signature } = await sendHypercoreEvmTransfer({
27653
+ provider,
27654
+ fromAddress: walletInfo.address,
27655
+ recipientAddress,
27656
+ sourceTokenAddress: token.token_address,
27657
+ amount: amountStr,
27658
+ publishableKey
27659
+ });
27660
+ return signature;
27661
+ };
27501
27662
  const handleConfirm = async () => {
27502
27663
  if (!hasWallet || !selectedBalance || !amountUsd || tokenAmount === 0 || !recipientAddress) return;
27503
27664
  const token = getTokenFromBalance(selectedBalance);
@@ -27517,7 +27678,33 @@ function WalletConnect({
27517
27678
  setIsConfirming(true);
27518
27679
  setError(null);
27519
27680
  try {
27520
- const txHash = token.chain_type === "solana" ? await sendSolanaTransaction2(token, tokenAmount.toString()) : await sendEthereumTransaction(token, tokenAmount.toString());
27681
+ const isHypercoreToken = String(token.chain_id) === HYPERCORE_CHAIN_ID;
27682
+ let txHash;
27683
+ if (token.chain_type === "solana") {
27684
+ txHash = await sendSolanaTransaction2(token, tokenAmount.toString());
27685
+ } else if (isHypercoreToken) {
27686
+ let sendAmount = tokenAmount;
27687
+ try {
27688
+ const activation = await checkHypercoreActivation(
27689
+ { source_address: walletInfo.address, recipient_address: recipientAddress },
27690
+ publishableKey
27691
+ );
27692
+ if (!activation.user_exists) {
27693
+ const fee = activation.activation_fee;
27694
+ if (!Number.isFinite(tokenAmount) || tokenAmount <= fee) {
27695
+ throw new Error(
27696
+ `Insufficient amount. A ${fee} USDC activation fee is required for the first transfer to this address.`
27697
+ );
27698
+ }
27699
+ sendAmount = tokenAmount - fee;
27700
+ }
27701
+ } catch (e) {
27702
+ if (e instanceof Error && e.message.includes("activation fee")) throw e;
27703
+ }
27704
+ txHash = await sendHypercoreDeposit(token, sendAmount.toString());
27705
+ } else {
27706
+ txHash = await sendEthereumTransaction(token, tokenAmount.toString());
27707
+ }
27521
27708
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
27522
27709
  setHasSignedTransaction(true);
27523
27710
  handleIveDeposited();
@@ -27556,7 +27743,10 @@ function WalletConnect({
27556
27743
  children: [
27557
27744
  /* @__PURE__ */ jsxs48("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
27558
27745
  WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ jsx54(WalletIconWithNetwork, { WalletIcon: WALLET_ICONS3[wallet.id], networks: wallet.networks, size: 40, className: "uf-rounded-lg" }) : /* @__PURE__ */ jsx54("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
27559
- /* @__PURE__ */ jsx54("div", { className: "uf-text-sm uf-font-medium", style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: wallet.name })
27746
+ /* @__PURE__ */ jsxs48("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
27747
+ /* @__PURE__ */ jsx54("div", { className: "uf-text-sm uf-font-medium", style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: wallet.name }),
27748
+ wallet.id === recentWalletId && /* @__PURE__ */ jsx54("span", { className: "uf-text-xs uf-px-2 uf-py-0.5 uf-rounded-full", style: { backgroundColor: colors2.primary + "20", color: colors2.primary, fontFamily: fonts.medium }, children: "Last used" })
27749
+ ] })
27560
27750
  ] }),
27561
27751
  isPending ? /* @__PURE__ */ jsx54(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin", style: { color: colors2.primary } }) : wallet.isInstalled ? /* @__PURE__ */ jsx54("span", { className: "uf-text-xs uf-px-2 uf-py-1 uf-rounded-full", style: { backgroundColor: colors2.primary + "20", color: colors2.primary, fontFamily: fonts.medium }, children: "Detected" }) : /* @__PURE__ */ jsxs48("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
27562
27752
  /* @__PURE__ */ jsx54("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: showOpenInApp ? "Open" : "Install" }),
@@ -27735,7 +27925,7 @@ function WalletConnect({
27735
27925
  }
27736
27926
  if (view === "enter_amount" && selectedToken && selectedBalance) {
27737
27927
  return /* @__PURE__ */ jsx54(AccentColorOverride, { accentColor: walletAccent, accentForeground: walletAccentForeground, children: /* @__PURE__ */ jsx54("div", { style: viewTransitionStyle, children: /* @__PURE__ */ jsx54(EnterAmountView, { walletInfo, selectedBalance, selectedToken, amountUsd, formattedTokenAmount, tokenChainDetails, inputUsdNum, maxUsdAmount, isValidAmount, error, onAmountChange: setAmountUsd, onMaxClick: handleMaxClick, onReview: handleReview, onBack: handleBack, onClose: onClose ?? (() => {
27738
- }), quickSelectMode: amountQuickSelect, checkoutAmountUsd, checkoutReceivedUsd }) }) });
27928
+ }), quickSelectMode: amountQuickSelect, checkoutAmountUsd, checkoutReceivedUsd, footer: hypercoreNeedsActivation && !hypercoreActivationSponsored ? /* @__PURE__ */ jsx54(HypercoreActivationWarning, { activationFee: hypercoreActivationFee }) : void 0 }) }) });
27739
27929
  }
27740
27930
  if (view === "review" && selectedToken) {
27741
27931
  return /* @__PURE__ */ jsx54(AccentColorOverride, { accentColor: walletAccent, accentForeground: walletAccentForeground, children: /* @__PURE__ */ jsx54("div", { style: viewTransitionStyle, children: /* @__PURE__ */ jsx54(ReviewView, { walletInfo, recipientAddress, assetCdnUrl, selectedToken, amountUsd, formattedTokenAmount, tokenChainDetails, loadingTokenDetails, showTransactionDetails, isConfirming, error, onToggleDetails: () => setShowTransactionDetails(!showTransactionDetails), onConfirm: handleConfirm, onBack: handleBack, onClose: onClose ?? (() => {
@@ -27771,6 +27961,9 @@ function SkeletonButton({
27771
27961
  ] });
27772
27962
  }
27773
27963
  var t7 = i18n2.depositModal;
27964
+ function depositTabForScreen(screen) {
27965
+ return screen === "card" || screen === "cashapp" ? "cash" : "crypto";
27966
+ }
27774
27967
  function DepositModal({
27775
27968
  open,
27776
27969
  onOpenChange,
@@ -27806,6 +27999,7 @@ function DepositModal({
27806
27999
  theme = "dark",
27807
28000
  hideOverlay = false,
27808
28001
  initialScreen = "main",
28002
+ displayMode = "stacked",
27809
28003
  transferCryptoTitle = t7.transferCrypto.title,
27810
28004
  depositWithCardTitle = t7.depositWithCard.title,
27811
28005
  payWithExchangeTitle = t7.payWithExchange.title,
@@ -27840,6 +28034,9 @@ function DepositModal({
27840
28034
  effectiveInitialScreen
27841
28035
  );
27842
28036
  const [coinbaseSkipToHoldings, setCoinbaseSkipToHoldings] = useState32(false);
28037
+ const [depositTab, setDepositTab] = useState32(
28038
+ () => depositTabForScreen(effectiveInitialScreen)
28039
+ );
27843
28040
  const resetViewTimeoutRef = useRef92(null);
27844
28041
  const [cardView, setCardView] = useState32(
27845
28042
  "amount"
@@ -28137,6 +28334,7 @@ function DepositModal({
28137
28334
  resetViewTimeoutRef.current = null;
28138
28335
  }
28139
28336
  setView(effectiveInitialScreen);
28337
+ setDepositTab(depositTabForScreen(effectiveInitialScreen));
28140
28338
  setCardView("amount");
28141
28339
  setExchangeView("providers");
28142
28340
  setBrowserWalletInfo(null);
@@ -28165,6 +28363,7 @@ function DepositModal({
28165
28363
  } else if (view === "cashapp" && cashAppView !== "amount") {
28166
28364
  setCashAppView("amount");
28167
28365
  } else {
28366
+ setDepositTab(depositTabForScreen(view));
28168
28367
  setView("main");
28169
28368
  setCardView("amount");
28170
28369
  setExchangeView("providers");
@@ -28244,6 +28443,184 @@ function DepositModal({
28244
28443
  className: "uf-flex uf-justify-center uf-shrink-0"
28245
28444
  }
28246
28445
  ) });
28446
+ const transferCryptoMenuButton = showTransferCrypto ? /* @__PURE__ */ jsx55(
28447
+ TransferCryptoButton,
28448
+ {
28449
+ onClick: () => setView("transfer"),
28450
+ title: transferCryptoTitle,
28451
+ subtitle: t7.transferCrypto.subtitle,
28452
+ featuredTokens: projectConfig?.transfer_crypto.networks
28453
+ },
28454
+ "transfer"
28455
+ ) : null;
28456
+ const connectWalletMenuButton = showConnectWallet ? /* @__PURE__ */ jsx55(
28457
+ BrowserWalletButton,
28458
+ {
28459
+ onClick: handleBrowserWalletClick,
28460
+ onConnectClick: handleWalletConnectClick,
28461
+ onDisconnect: handleWalletDisconnect,
28462
+ chainType: browserWalletChainType,
28463
+ publishableKey,
28464
+ featuredWallets: projectConfig?.connect_wallet?.wallets
28465
+ },
28466
+ "wallet"
28467
+ ) : null;
28468
+ const depositWithCardMenuButton = showFiatOnramp ? /* @__PURE__ */ jsx55(
28469
+ DepositWithCardButton,
28470
+ {
28471
+ onClick: () => setView("card"),
28472
+ title: depositWithCardTitle,
28473
+ subtitle: t7.depositWithCard.subtitle,
28474
+ paymentNetworks: projectConfig?.payment_networks.networks
28475
+ },
28476
+ "card"
28477
+ ) : null;
28478
+ const payWithExchangeMenuButton = showPayWithExchange ? /* @__PURE__ */ jsx55(
28479
+ PayWithExchangeButton,
28480
+ {
28481
+ onClick: () => setView("exchange"),
28482
+ title: payWithExchangeTitle,
28483
+ subtitle: t7.payWithExchange.subtitle,
28484
+ exchanges,
28485
+ loading: exchangesLoading
28486
+ },
28487
+ "exchange"
28488
+ ) : null;
28489
+ const connectExchangeMenuButton = showConnectExchange && connectedExchange ? /* @__PURE__ */ jsx55(
28490
+ ConnectExchangeButton,
28491
+ {
28492
+ onClick: () => {
28493
+ setCoinbaseSkipToHoldings(true);
28494
+ setView("coinbase_connect");
28495
+ },
28496
+ onDisconnect: handleExchangeDisconnect,
28497
+ title: i18n2.connectExchange.title,
28498
+ subtitle: i18n2.connectExchange.subtitle,
28499
+ exchanges: integrationExchanges,
28500
+ connectedExchange
28501
+ },
28502
+ "connect-exchange"
28503
+ ) : showConnectExchange && !connectedExchange ? /* @__PURE__ */ jsx55(
28504
+ ConnectExchangeButton,
28505
+ {
28506
+ onClick: () => {
28507
+ setCoinbaseSkipToHoldings(false);
28508
+ setView("coinbase_connect");
28509
+ },
28510
+ title: i18n2.connectExchange.title,
28511
+ subtitle: i18n2.connectExchange.subtitle,
28512
+ exchanges: integrationExchanges
28513
+ },
28514
+ "connect-exchange"
28515
+ ) : null;
28516
+ const cashAppMenuButton = showCashApp ? /* @__PURE__ */ jsx55(
28517
+ CashAppButton,
28518
+ {
28519
+ onClick: () => setView("cashapp"),
28520
+ title: "Pay with Cash App",
28521
+ subtitle: "Deposit via Cash App",
28522
+ iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
28523
+ },
28524
+ "cashapp"
28525
+ ) : null;
28526
+ const depositTrackerMenuButton = showDepositTracker ? /* @__PURE__ */ jsx55(
28527
+ DepositTrackerButton,
28528
+ {
28529
+ onClick: () => {
28530
+ setAllExecutions(depositExecutions);
28531
+ setView("tracker");
28532
+ },
28533
+ title: depositTrackerTitle,
28534
+ subtitle: depositTrackerSubTitle,
28535
+ badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
28536
+ },
28537
+ "tracker"
28538
+ ) : null;
28539
+ const cryptoMenuButtons = [
28540
+ transferCryptoMenuButton,
28541
+ connectWalletMenuButton,
28542
+ payWithExchangeMenuButton,
28543
+ connectExchangeMenuButton
28544
+ ].filter(Boolean);
28545
+ const cashMenuButtons = [
28546
+ depositWithCardMenuButton,
28547
+ cashAppMenuButton
28548
+ ].filter(Boolean);
28549
+ const depositTabs = [
28550
+ { id: "crypto", label: "Use Crypto", icon: Bitcoin, buttons: cryptoMenuButtons },
28551
+ { id: "cash", label: "Use Cash", icon: DollarSign, buttons: cashMenuButtons }
28552
+ ].filter((tab) => tab.buttons.length > 0);
28553
+ const activeDepositTab = depositTabs.find((tab) => tab.id === depositTab) ?? depositTabs[0];
28554
+ const renderMainMenuBody = () => {
28555
+ if (depositPrerequisiteBody) {
28556
+ return /* @__PURE__ */ jsx55("div", { className: "uf-space-y-3", children: depositPrerequisiteBody });
28557
+ }
28558
+ if (displayMode === "tabs" && activeDepositTab) {
28559
+ return /* @__PURE__ */ jsxs49("div", { children: [
28560
+ depositTabs.length > 1 && /* @__PURE__ */ jsx55(
28561
+ "div",
28562
+ {
28563
+ className: "uf-flex uf-gap-1 uf-p-1 uf-rounded-xl uf-mb-3",
28564
+ style: {
28565
+ // Frosted-glass track: a translucent fill plus a backdrop blur so
28566
+ // the control reads as a soft surface rather than a solid bar.
28567
+ backgroundColor: `color-mix(in srgb, ${colors2.card} 55%, transparent)`,
28568
+ backdropFilter: "blur(12px)",
28569
+ WebkitBackdropFilter: "blur(12px)"
28570
+ },
28571
+ role: "tablist",
28572
+ children: depositTabs.map((tab) => {
28573
+ const active = activeDepositTab.id === tab.id;
28574
+ const TabIcon = tab.icon;
28575
+ return /* @__PURE__ */ jsxs49(
28576
+ "button",
28577
+ {
28578
+ type: "button",
28579
+ role: "tab",
28580
+ "aria-selected": active,
28581
+ onClick: () => setDepositTab(tab.id),
28582
+ className: "uf-flex-1 uf-py-2 uf-px-3 uf-rounded-lg uf-text-sm uf-transition-all uf-flex uf-items-center uf-justify-center uf-gap-1.5",
28583
+ style: {
28584
+ backgroundColor: active ? `color-mix(in srgb, ${colors2.primary} 22%, transparent)` : "transparent",
28585
+ backdropFilter: active ? "blur(8px)" : void 0,
28586
+ WebkitBackdropFilter: active ? "blur(8px)" : void 0,
28587
+ boxShadow: active ? `0 1px 8px color-mix(in srgb, ${colors2.primary} 25%, transparent)` : void 0,
28588
+ color: active ? colors2.foreground : colors2.foregroundMuted,
28589
+ fontFamily: fonts.medium
28590
+ },
28591
+ children: [
28592
+ /* @__PURE__ */ jsx55(
28593
+ "span",
28594
+ {
28595
+ className: "uf-inline-flex uf-items-center uf-justify-center uf-rounded-full uf-w-5 uf-h-5 uf-flex-shrink-0",
28596
+ style: {
28597
+ backgroundColor: active ? colors2.foreground : colors2.foregroundMuted
28598
+ },
28599
+ children: /* @__PURE__ */ jsx55(TabIcon, { size: 12, style: { color: active ? colors2.background : colors2.background }, strokeWidth: 2.5 })
28600
+ }
28601
+ ),
28602
+ tab.label
28603
+ ]
28604
+ },
28605
+ tab.id
28606
+ );
28607
+ })
28608
+ }
28609
+ ),
28610
+ /* @__PURE__ */ jsx55("div", { className: "uf-space-y-3", children: activeDepositTab.buttons }),
28611
+ depositTrackerMenuButton && /* @__PURE__ */ jsx55("div", { className: "uf-mt-3", children: depositTrackerMenuButton })
28612
+ ] });
28613
+ }
28614
+ return /* @__PURE__ */ jsxs49("div", { className: "uf-space-y-3", children: [
28615
+ transferCryptoMenuButton,
28616
+ connectWalletMenuButton,
28617
+ depositWithCardMenuButton,
28618
+ payWithExchangeMenuButton,
28619
+ connectExchangeMenuButton,
28620
+ cashAppMenuButton,
28621
+ depositTrackerMenuButton
28622
+ ] });
28623
+ };
28247
28624
  return /* @__PURE__ */ jsx55(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ jsx55(
28248
28625
  Dialog2,
28249
28626
  {
@@ -28270,7 +28647,7 @@ function DepositModal({
28270
28647
  onClose: handleClose,
28271
28648
  showBalance: showBalanceHeader,
28272
28649
  balanceAddress: recipientAddress,
28273
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
28650
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
28274
28651
  balanceChainId: destinationChainId,
28275
28652
  balanceTokenAddress: destinationTokenAddress,
28276
28653
  projectName: projectConfig?.project_name,
@@ -28278,94 +28655,7 @@ function DepositModal({
28278
28655
  }
28279
28656
  ),
28280
28657
  /* @__PURE__ */ jsxs49("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
28281
- /* @__PURE__ */ jsx55("div", { className: "uf-space-y-3", children: depositPrerequisiteBody ?? /* @__PURE__ */ jsxs49(Fragment11, { children: [
28282
- showTransferCrypto && /* @__PURE__ */ jsx55(
28283
- TransferCryptoButton,
28284
- {
28285
- onClick: () => setView("transfer"),
28286
- title: transferCryptoTitle,
28287
- subtitle: t7.transferCrypto.subtitle,
28288
- featuredTokens: projectConfig?.transfer_crypto.networks
28289
- }
28290
- ),
28291
- showConnectWallet && /* @__PURE__ */ jsx55(
28292
- BrowserWalletButton,
28293
- {
28294
- onClick: handleBrowserWalletClick,
28295
- onConnectClick: handleWalletConnectClick,
28296
- onDisconnect: handleWalletDisconnect,
28297
- chainType: browserWalletChainType,
28298
- publishableKey,
28299
- featuredWallets: projectConfig?.connect_wallet?.wallets
28300
- }
28301
- ),
28302
- showFiatOnramp && /* @__PURE__ */ jsx55(
28303
- DepositWithCardButton,
28304
- {
28305
- onClick: () => setView("card"),
28306
- title: depositWithCardTitle,
28307
- subtitle: t7.depositWithCard.subtitle,
28308
- paymentNetworks: projectConfig?.payment_networks.networks
28309
- }
28310
- ),
28311
- showPayWithExchange && /* @__PURE__ */ jsx55(
28312
- PayWithExchangeButton,
28313
- {
28314
- onClick: () => setView("exchange"),
28315
- title: payWithExchangeTitle,
28316
- subtitle: t7.payWithExchange.subtitle,
28317
- exchanges,
28318
- loading: exchangesLoading
28319
- }
28320
- ),
28321
- showConnectExchange && connectedExchange && /* @__PURE__ */ jsx55(
28322
- ConnectExchangeButton,
28323
- {
28324
- onClick: () => {
28325
- setCoinbaseSkipToHoldings(true);
28326
- setView("coinbase_connect");
28327
- },
28328
- onDisconnect: handleExchangeDisconnect,
28329
- title: i18n2.connectExchange.title,
28330
- subtitle: i18n2.connectExchange.subtitle,
28331
- exchanges: integrationExchanges,
28332
- connectedExchange
28333
- }
28334
- ),
28335
- showConnectExchange && !connectedExchange && /* @__PURE__ */ jsx55(
28336
- ConnectExchangeButton,
28337
- {
28338
- onClick: () => {
28339
- setCoinbaseSkipToHoldings(false);
28340
- setView("coinbase_connect");
28341
- },
28342
- title: i18n2.connectExchange.title,
28343
- subtitle: i18n2.connectExchange.subtitle,
28344
- exchanges: integrationExchanges
28345
- }
28346
- ),
28347
- showCashApp && /* @__PURE__ */ jsx55(
28348
- CashAppButton,
28349
- {
28350
- onClick: () => setView("cashapp"),
28351
- title: "Pay with Cash App",
28352
- subtitle: "Deposit via Cash App",
28353
- iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
28354
- }
28355
- ),
28356
- showDepositTracker && /* @__PURE__ */ jsx55(
28357
- DepositTrackerButton,
28358
- {
28359
- onClick: () => {
28360
- setAllExecutions(depositExecutions);
28361
- setView("tracker");
28362
- },
28363
- title: depositTrackerTitle,
28364
- subtitle: depositTrackerSubTitle,
28365
- badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
28366
- }
28367
- )
28368
- ] }) }),
28658
+ renderMainMenuBody(),
28369
28659
  depositPoweredByFooter
28370
28660
  ] })
28371
28661
  ] }) : view === "transfer" ? /* @__PURE__ */ jsxs49(Fragment11, { children: [
@@ -28378,7 +28668,7 @@ function DepositModal({
28378
28668
  onClose: handleClose,
28379
28669
  showBalance: showBalanceHeader,
28380
28670
  balanceAddress: recipientAddress,
28381
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
28671
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
28382
28672
  balanceChainId: destinationChainId,
28383
28673
  balanceTokenAddress: destinationTokenAddress,
28384
28674
  projectName: projectConfig?.project_name,
@@ -28466,7 +28756,7 @@ function DepositModal({
28466
28756
  badge: cardView === "quotes" ? { count: quotesCount } : void 0,
28467
28757
  showBalance: showBalanceHeader,
28468
28758
  balanceAddress: recipientAddress,
28469
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
28759
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
28470
28760
  balanceChainId: destinationChainId,
28471
28761
  balanceTokenAddress: destinationTokenAddress,
28472
28762
  projectName: projectConfig?.project_name,
@@ -29762,9 +30052,6 @@ function useVerifyRecipientAddress(params) {
29762
30052
  refetchOnWindowFocus: false
29763
30053
  });
29764
30054
  }
29765
- function isHypercoreChain(chainId) {
29766
- return chainId === HYPERCORE_CHAIN_ID;
29767
- }
29768
30055
  function useGetDepositAddress(params) {
29769
30056
  const {
29770
30057
  userId,
@@ -30691,8 +30978,6 @@ function WithdrawConfirmingView({
30691
30978
  className: "uf-text-sm uf-text-center",
30692
30979
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
30693
30980
  children: [
30694
- txInfo.amount,
30695
- " ",
30696
30981
  txInfo.sourceTokenSymbol,
30697
30982
  " to",
30698
30983
  " ",
@@ -31336,6 +31621,7 @@ function UnifoldProvider2({
31336
31621
  hideDepositTracker: config?.hideDepositTracker,
31337
31622
  showBalanceHeader: config?.showBalanceHeader,
31338
31623
  transferInputVariant: config?.transferInputVariant,
31624
+ displayMode: config?.displayMode,
31339
31625
  enableTransferCrypto: config?.enableTransferCrypto,
31340
31626
  enableConnectWallet: config?.enableConnectWallet,
31341
31627
  enablePayWithExchange: config?.enablePayWithExchange,
@@ -31441,6 +31727,7 @@ lucide-react/dist/esm/createLucideIcon.js:
31441
31727
  lucide-react/dist/esm/icons/arrow-left-right.js:
31442
31728
  lucide-react/dist/esm/icons/arrow-left.js:
31443
31729
  lucide-react/dist/esm/icons/arrow-up-down.js:
31730
+ lucide-react/dist/esm/icons/bitcoin.js:
31444
31731
  lucide-react/dist/esm/icons/check.js:
31445
31732
  lucide-react/dist/esm/icons/chevron-down.js:
31446
31733
  lucide-react/dist/esm/icons/chevron-right.js: