@unifold/ui-react 0.1.64 → 0.1.65

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
@@ -97,6 +97,22 @@ function clearStoredWalletState() {
97
97
  } catch {
98
98
  }
99
99
  }
100
+ var LAST_OPENED_WALLET_KEY = "unifold_last_opened_wallet";
101
+ function getLastOpenedWallet() {
102
+ if (typeof window === "undefined") return void 0;
103
+ try {
104
+ return localStorage.getItem(LAST_OPENED_WALLET_KEY) ?? void 0;
105
+ } catch {
106
+ return void 0;
107
+ }
108
+ }
109
+ function setLastOpenedWallet(walletId) {
110
+ if (typeof window === "undefined") return;
111
+ try {
112
+ localStorage.setItem(LAST_OPENED_WALLET_KEY, walletId);
113
+ } catch {
114
+ }
115
+ }
100
116
  var MOBILE_VIEWPORT_MEDIA_QUERY = "(max-width: 768px)";
101
117
  function isMobileViewport() {
102
118
  if (typeof window === "undefined") return false;
@@ -959,7 +975,7 @@ function DepositHeader({
959
975
  setShowBalanceSkeleton(false);
960
976
  return;
961
977
  }
962
- const supportedChainTypes = ["ethereum", "solana", "bitcoin"];
978
+ const supportedChainTypes = ["ethereum", "solana", "bitcoin", "n1"];
963
979
  if (!supportedChainTypes.includes(
964
980
  balanceChainType
965
981
  )) {
@@ -11365,7 +11381,7 @@ function useHypercoreActivation(params) {
11365
11381
  publishableKey,
11366
11382
  enabled = true
11367
11383
  } = params;
11368
- const isHypercore2 = destinationChainId === HYPERCORE_CHAIN_ID;
11384
+ const isHypercore2 = String(destinationChainId) === HYPERCORE_CHAIN_ID;
11369
11385
  const recipient = recipientAddress?.trim() ?? "";
11370
11386
  const source = sourceAddress?.trim() ?? "";
11371
11387
  const hasAddresses = !!recipient && !!source;
@@ -12556,9 +12572,56 @@ import {
12556
12572
  ExecutionStatus as ExecutionStatus5,
12557
12573
  buildSolanaTransaction,
12558
12574
  sendSolanaTransaction as sendSolanaTransactionToBackend,
12559
- getWalletMobileDeepLink
12575
+ getWalletMobileDeepLink,
12576
+ checkHypercoreActivation as checkHypercoreActivation2
12560
12577
  } from "@unifold/core";
12561
12578
 
12579
+ // src/lib/send-hypercore.ts
12580
+ import {
12581
+ buildHypercoreTransaction as buildHypercoreTransactionFromBackend,
12582
+ sendHypercoreTransaction as sendHypercoreTransactionToBackend
12583
+ } from "@unifold/core";
12584
+ function isHypercoreChain(chainId) {
12585
+ return chainId === HYPERCORE_CHAIN_ID;
12586
+ }
12587
+ async function sendHypercoreEvmTransfer(params) {
12588
+ const {
12589
+ provider,
12590
+ fromAddress,
12591
+ recipientAddress,
12592
+ sourceTokenAddress,
12593
+ amount,
12594
+ publishableKey
12595
+ } = params;
12596
+ const currentChainHex = await provider.request({
12597
+ method: "eth_chainId",
12598
+ params: []
12599
+ });
12600
+ const activeChainId = String(parseInt(currentChainHex, 16));
12601
+ const buildResult = await buildHypercoreTransactionFromBackend(
12602
+ {
12603
+ signature_chain_id: activeChainId,
12604
+ recipient_address: recipientAddress,
12605
+ token_address: sourceTokenAddress,
12606
+ amount
12607
+ },
12608
+ publishableKey
12609
+ );
12610
+ const signature = await provider.request({
12611
+ method: "eth_signTypedData_v4",
12612
+ params: [fromAddress, JSON.stringify(buildResult.typed_data)]
12613
+ });
12614
+ await sendHypercoreTransactionToBackend(
12615
+ {
12616
+ action_payload: buildResult.action_payload,
12617
+ signature,
12618
+ nonce: buildResult.nonce
12619
+ },
12620
+ publishableKey
12621
+ );
12622
+ return { signature };
12623
+ }
12624
+
12562
12625
  // src/hooks/use-deposit-quote.ts
12563
12626
  import { useQuery as useQuery12 } from "@tanstack/react-query";
12564
12627
  import {
@@ -12991,7 +13054,8 @@ function EnterAmountView({
12991
13054
  onClose,
12992
13055
  quickSelectMode,
12993
13056
  checkoutAmountUsd,
12994
- checkoutReceivedUsd
13057
+ checkoutReceivedUsd,
13058
+ footer
12995
13059
  }) {
12996
13060
  const { colors: colors2, fonts, components } = useTheme();
12997
13061
  const isCheckout = !!checkoutAmountUsd;
@@ -13247,6 +13311,7 @@ function EnterAmountView({
13247
13311
  )
13248
13312
  ] })
13249
13313
  ] }),
13314
+ footer && /* @__PURE__ */ jsx51("div", { className: "uf-shrink-0 uf-pt-2", children: footer }),
13250
13315
  /* @__PURE__ */ jsx51("div", { className: "uf-shrink-0 uf-pt-2", children: /* @__PURE__ */ jsx51(
13251
13316
  "button",
13252
13317
  {
@@ -13708,7 +13773,7 @@ var WALLET_ICONS3 = {
13708
13773
  };
13709
13774
  var FALLBACK_WALLET_DEFINITIONS = [
13710
13775
  { id: "phantom", name: "Phantom", networks: ["ethereum", "solana"], installUrl: "https://phantom.app/", supportsMobileBrowse: true },
13711
- { id: "coinbase", name: "Coinbase Wallet", networks: ["ethereum", "solana"], installUrl: "https://www.coinbase.com/wallet", supportsMobileBrowse: true },
13776
+ { id: "coinbase", name: "Coinbase Wallet", networks: ["ethereum"], installUrl: "https://www.coinbase.com/wallet", supportsMobileBrowse: true },
13712
13777
  { id: "trust", name: "Trust Wallet", networks: ["ethereum", "solana"], installUrl: "https://trustwallet.com/", supportsMobileBrowse: true },
13713
13778
  { id: "metamask", name: "MetaMask", networks: ["ethereum"], installUrl: "https://metamask.io/download/", supportsMobileBrowse: true },
13714
13779
  { id: "rainbow", name: "Rainbow", networks: ["ethereum"], installUrl: "https://rainbow.me/", supportsMobileBrowse: true },
@@ -13768,7 +13833,7 @@ function getLegacyEvmProviders() {
13768
13833
  okxEthereum: win.okxwallet
13769
13834
  };
13770
13835
  }
13771
- function detectAvailableWallets(definitions, filterChainType) {
13836
+ function detectAvailableWallets(definitions, recentWalletId, filterChainType) {
13772
13837
  const solProviders = getSolanaProviders();
13773
13838
  const legacyEvm = getLegacyEvmProviders();
13774
13839
  const eip6963List = getEip6963Providers();
@@ -13794,7 +13859,7 @@ function detectAvailableWallets(definitions, filterChainType) {
13794
13859
  return false;
13795
13860
  }
13796
13861
  });
13797
- return definitions.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
13862
+ const sorted = definitions.filter((w) => !filterChainType || w.networks.includes(filterChainType)).map((wallet) => {
13798
13863
  let isInstalled = false;
13799
13864
  const detectedNetworks = [];
13800
13865
  switch (wallet.id) {
@@ -13817,8 +13882,6 @@ function detectAvailableWallets(definitions, filterChainType) {
13817
13882
  isInstalled = true;
13818
13883
  detectedNetworks.push("ethereum");
13819
13884
  }
13820
- if (solProviders.coinbaseSolana || win?.coinbaseWalletExtension?.solana) detectedNetworks.push("solana");
13821
- if (isInstalled && wallet.networks.includes("solana") && !detectedNetworks.includes("solana")) detectedNetworks.push("solana");
13822
13885
  break;
13823
13886
  case "trust":
13824
13887
  if (hasEip6963("trust") || legacyEvm.trustEthereum || legacyEvm.ethereum?.isTrust || win?.trustwallet) {
@@ -13855,11 +13918,17 @@ function detectAvailableWallets(definitions, filterChainType) {
13855
13918
  }
13856
13919
  return { ...wallet, isInstalled, detectedNetworks };
13857
13920
  }).sort((a, b) => {
13921
+ if (recentWalletId) {
13922
+ const aRecent = a.id === recentWalletId ? 1 : 0;
13923
+ const bRecent = b.id === recentWalletId ? 1 : 0;
13924
+ if (aRecent !== bRecent) return bRecent - aRecent;
13925
+ }
13858
13926
  if (a.isInstalled && !b.isInstalled) return -1;
13859
13927
  if (!a.isInstalled && b.isInstalled) return 1;
13860
13928
  if (a.isInstalled && b.isInstalled) return b.networks.length - a.networks.length;
13861
13929
  return 0;
13862
13930
  });
13931
+ return sorted;
13863
13932
  }
13864
13933
  function WalletConnect({
13865
13934
  walletInfo: initialWalletInfo,
@@ -13934,9 +14003,15 @@ function WalletConnect({
13934
14003
  })) : FALLBACK_WALLET_DEFINITIONS,
13935
14004
  [backendWallets]
13936
14005
  );
14006
+ const [recentWalletId, setRecentWalletIdState] = React30.useState(getLastOpenedWallet);
14007
+ React30.useEffect(() => {
14008
+ if (view === "select_wallet") {
14009
+ setRecentWalletIdState(getLastOpenedWallet());
14010
+ }
14011
+ }, [view]);
13937
14012
  const availableWallets = React30.useMemo(
13938
- () => detectAvailableWallets(walletDefinitions),
13939
- [walletDefinitions, eip6963ProviderCount]
14013
+ () => detectAvailableWallets(walletDefinitions, recentWalletId),
14014
+ [walletDefinitions, eip6963ProviderCount, recentWalletId]
13940
14015
  );
13941
14016
  const [isMobile, setIsMobile] = React30.useState(false);
13942
14017
  React30.useEffect(() => {
@@ -13996,7 +14071,7 @@ function WalletConnect({
13996
14071
  const chainType = activeDepositWallet?.chain_type ?? "ethereum";
13997
14072
  const recipientAddress = activeDepositWallet?.address ?? "";
13998
14073
  const isCheckoutMode = !!checkoutAmountUsd;
13999
- const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
14074
+ const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
14000
14075
  const transitionTo = React30.useCallback((nextView) => {
14001
14076
  if (nextView === viewRef.current) return;
14002
14077
  setIsTransitioning(true);
@@ -14020,6 +14095,8 @@ function WalletConnect({
14020
14095
  );
14021
14096
  if (res.deeplink) {
14022
14097
  setMobileRedirect({ walletId: wallet.id, walletName: wallet.name, deeplink: res.deeplink });
14098
+ setLastOpenedWallet(wallet.id);
14099
+ setRecentWalletIdState(wallet.id);
14023
14100
  setAwaitingMobileDeposit(true);
14024
14101
  transitionTo("mobile_redirect");
14025
14102
  window.location.href = res.deeplink;
@@ -14080,6 +14157,8 @@ function WalletConnect({
14080
14157
  const handleConnectWallet = async (wallet, network) => {
14081
14158
  setConnectingNetwork(network);
14082
14159
  transitionTo("connecting");
14160
+ setLastOpenedWallet(wallet.id);
14161
+ setRecentWalletIdState(wallet.id);
14083
14162
  setWalletError(null);
14084
14163
  setIsWalletConnecting(true);
14085
14164
  try {
@@ -14184,6 +14263,13 @@ function WalletConnect({
14184
14263
  }
14185
14264
  };
14186
14265
  const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
14266
+ const { needsActivation: hypercoreNeedsActivation, activationFee: hypercoreActivationFee, sponsored: hypercoreActivationSponsored } = useHypercoreActivation({
14267
+ recipientAddress,
14268
+ sourceAddress: activeWalletInfo?.address,
14269
+ destinationChainId: selectedToken?.chain_id,
14270
+ publishableKey,
14271
+ enabled: !!activeWalletInfo && !!recipientAddress
14272
+ });
14187
14273
  const effectiveDestinationAmount = React30.useMemo(() => {
14188
14274
  if (!checkoutRemainingBaseUnits || checkoutRemainingBaseUnits === "0") return "0";
14189
14275
  if (!checkoutAmountUsd) return checkoutRemainingBaseUnits;
@@ -14288,7 +14374,7 @@ function WalletConnect({
14288
14374
  let cancelled = false;
14289
14375
  setIsLoading(true);
14290
14376
  setError(null);
14291
- const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" ? "ethereum" : activeDepositWallet.chain_type;
14377
+ const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" ? "ethereum" : activeDepositWallet.chain_type;
14292
14378
  getAddressBalances2(activeWalletInfo.address, sct, publishableKey).then((response) => {
14293
14379
  if (cancelled) return;
14294
14380
  const nonZero = response.balances.filter((b) => b.amount !== "0");
@@ -14454,9 +14540,16 @@ function WalletConnect({
14454
14540
  const [integerPart = "0", decimalPart = ""] = amountStr.trim().split(".");
14455
14541
  return (integerPart + decimalPart.padEnd(decimals, "0").slice(0, decimals)).replace(/^0+/, "") || "0";
14456
14542
  };
14457
- const sendEthereumTransaction = async (token, amountStr) => {
14458
- if (!recipientAddress || !/^0x[a-fA-F0-9]{40}$/.test(recipientAddress)) throw new Error(`Invalid recipient address.`);
14459
- const walletIdMap = { "phantom-ethereum": "phantom", coinbase: "coinbase", trust: "trust", okx: "okx", rainbow: "rainbow", rabby: "rabby", metamask: "metamask" };
14543
+ const resolveEvmProvider = () => {
14544
+ const walletIdMap = {
14545
+ "phantom-ethereum": "phantom",
14546
+ coinbase: "coinbase",
14547
+ trust: "trust",
14548
+ okx: "okx",
14549
+ rainbow: "rainbow",
14550
+ rabby: "rabby",
14551
+ metamask: "metamask"
14552
+ };
14460
14553
  const lookupId = walletIdMap[walletInfo.type] || walletInfo.type;
14461
14554
  const eip6963Match = findProviderByWalletId(lookupId);
14462
14555
  let provider = eip6963Match?.provider;
@@ -14465,6 +14558,11 @@ function WalletConnect({
14465
14558
  else if (walletInfo.type === "coinbase") provider = window.coinbaseWalletExtension || window.ethereum;
14466
14559
  else provider = window.ethereum;
14467
14560
  }
14561
+ return provider;
14562
+ };
14563
+ const sendEthereumTransaction = async (token, amountStr) => {
14564
+ if (!recipientAddress || !/^0x[a-fA-F0-9]{40}$/.test(recipientAddress)) throw new Error(`Invalid recipient address.`);
14565
+ const provider = resolveEvmProvider();
14468
14566
  if (!provider) throw new Error("Ethereum wallet not found");
14469
14567
  const currentChainIdHex = await provider.request({ method: "eth_chainId", params: [] });
14470
14568
  if (parseInt(currentChainIdHex, 16).toString() !== token.chain_id) {
@@ -14529,6 +14627,19 @@ function WalletConnect({
14529
14627
  const resp = await sendSolanaTransactionToBackend({ chain_id: "mainnet", signed_transaction: btoa(bs) }, publishableKey);
14530
14628
  return resp.signature;
14531
14629
  };
14630
+ const sendHypercoreDeposit = async (token, amountStr) => {
14631
+ const provider = resolveEvmProvider();
14632
+ if (!provider) throw new Error("Ethereum wallet not found");
14633
+ const { signature } = await sendHypercoreEvmTransfer({
14634
+ provider,
14635
+ fromAddress: walletInfo.address,
14636
+ recipientAddress,
14637
+ sourceTokenAddress: token.token_address,
14638
+ amount: amountStr,
14639
+ publishableKey
14640
+ });
14641
+ return signature;
14642
+ };
14532
14643
  const handleConfirm = async () => {
14533
14644
  if (!hasWallet || !selectedBalance || !amountUsd || tokenAmount === 0 || !recipientAddress) return;
14534
14645
  const token = getTokenFromBalance(selectedBalance);
@@ -14548,7 +14659,33 @@ function WalletConnect({
14548
14659
  setIsConfirming(true);
14549
14660
  setError(null);
14550
14661
  try {
14551
- const txHash = token.chain_type === "solana" ? await sendSolanaTransaction(token, tokenAmount.toString()) : await sendEthereumTransaction(token, tokenAmount.toString());
14662
+ const isHypercoreToken = String(token.chain_id) === HYPERCORE_CHAIN_ID;
14663
+ let txHash;
14664
+ if (token.chain_type === "solana") {
14665
+ txHash = await sendSolanaTransaction(token, tokenAmount.toString());
14666
+ } else if (isHypercoreToken) {
14667
+ let sendAmount = tokenAmount;
14668
+ try {
14669
+ const activation = await checkHypercoreActivation2(
14670
+ { source_address: walletInfo.address, recipient_address: recipientAddress },
14671
+ publishableKey
14672
+ );
14673
+ if (!activation.user_exists) {
14674
+ const fee = activation.activation_fee;
14675
+ if (!Number.isFinite(tokenAmount) || tokenAmount <= fee) {
14676
+ throw new Error(
14677
+ `Insufficient amount. A ${fee} USDC activation fee is required for the first transfer to this address.`
14678
+ );
14679
+ }
14680
+ sendAmount = tokenAmount - fee;
14681
+ }
14682
+ } catch (e) {
14683
+ if (e instanceof Error && e.message.includes("activation fee")) throw e;
14684
+ }
14685
+ txHash = await sendHypercoreDeposit(token, sendAmount.toString());
14686
+ } else {
14687
+ txHash = await sendEthereumTransaction(token, tokenAmount.toString());
14688
+ }
14552
14689
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
14553
14690
  setHasSignedTransaction(true);
14554
14691
  handleIveDeposited();
@@ -14766,7 +14903,7 @@ function WalletConnect({
14766
14903
  }
14767
14904
  if (view === "enter_amount" && selectedToken && selectedBalance) {
14768
14905
  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 ?? (() => {
14769
- }), quickSelectMode: amountQuickSelect, checkoutAmountUsd, checkoutReceivedUsd }) }) });
14906
+ }), quickSelectMode: amountQuickSelect, checkoutAmountUsd, checkoutReceivedUsd, footer: hypercoreNeedsActivation && !hypercoreActivationSponsored ? /* @__PURE__ */ jsx54(HypercoreActivationWarning, { activationFee: hypercoreActivationFee }) : void 0 }) }) });
14770
14907
  }
14771
14908
  if (view === "review" && selectedToken) {
14772
14909
  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 ?? (() => {
@@ -14805,6 +14942,9 @@ function SkeletonButton({
14805
14942
  ] });
14806
14943
  }
14807
14944
  var t7 = i18n.depositModal;
14945
+ function depositTabForScreen(screen) {
14946
+ return screen === "card" || screen === "cashapp" ? "cash" : "crypto";
14947
+ }
14808
14948
  function DepositModal({
14809
14949
  open,
14810
14950
  onOpenChange,
@@ -14840,6 +14980,7 @@ function DepositModal({
14840
14980
  theme = "dark",
14841
14981
  hideOverlay = false,
14842
14982
  initialScreen = "main",
14983
+ displayMode = "stacked",
14843
14984
  transferCryptoTitle = t7.transferCrypto.title,
14844
14985
  depositWithCardTitle = t7.depositWithCard.title,
14845
14986
  payWithExchangeTitle = t7.payWithExchange.title,
@@ -14874,6 +15015,9 @@ function DepositModal({
14874
15015
  effectiveInitialScreen
14875
15016
  );
14876
15017
  const [coinbaseSkipToHoldings, setCoinbaseSkipToHoldings] = useState32(false);
15018
+ const [depositTab, setDepositTab] = useState32(
15019
+ () => depositTabForScreen(effectiveInitialScreen)
15020
+ );
14877
15021
  const resetViewTimeoutRef = useRef9(null);
14878
15022
  const [cardView, setCardView] = useState32(
14879
15023
  "amount"
@@ -15171,6 +15315,7 @@ function DepositModal({
15171
15315
  resetViewTimeoutRef.current = null;
15172
15316
  }
15173
15317
  setView(effectiveInitialScreen);
15318
+ setDepositTab(depositTabForScreen(effectiveInitialScreen));
15174
15319
  setCardView("amount");
15175
15320
  setExchangeView("providers");
15176
15321
  setBrowserWalletInfo(null);
@@ -15199,6 +15344,7 @@ function DepositModal({
15199
15344
  } else if (view === "cashapp" && cashAppView !== "amount") {
15200
15345
  setCashAppView("amount");
15201
15346
  } else {
15347
+ setDepositTab(depositTabForScreen(view));
15202
15348
  setView("main");
15203
15349
  setCardView("amount");
15204
15350
  setExchangeView("providers");
@@ -15278,6 +15424,174 @@ function DepositModal({
15278
15424
  className: "uf-flex uf-justify-center uf-shrink-0"
15279
15425
  }
15280
15426
  ) });
15427
+ const transferCryptoMenuButton = showTransferCrypto ? /* @__PURE__ */ jsx55(
15428
+ TransferCryptoButton,
15429
+ {
15430
+ onClick: () => setView("transfer"),
15431
+ title: transferCryptoTitle,
15432
+ subtitle: t7.transferCrypto.subtitle,
15433
+ featuredTokens: projectConfig?.transfer_crypto.networks
15434
+ },
15435
+ "transfer"
15436
+ ) : null;
15437
+ const connectWalletMenuButton = showConnectWallet ? /* @__PURE__ */ jsx55(
15438
+ BrowserWalletButton,
15439
+ {
15440
+ onClick: handleBrowserWalletClick,
15441
+ onConnectClick: handleWalletConnectClick,
15442
+ onDisconnect: handleWalletDisconnect,
15443
+ chainType: browserWalletChainType,
15444
+ publishableKey,
15445
+ featuredWallets: projectConfig?.connect_wallet?.wallets
15446
+ },
15447
+ "wallet"
15448
+ ) : null;
15449
+ const depositWithCardMenuButton = showFiatOnramp ? /* @__PURE__ */ jsx55(
15450
+ DepositWithCardButton,
15451
+ {
15452
+ onClick: () => setView("card"),
15453
+ title: depositWithCardTitle,
15454
+ subtitle: t7.depositWithCard.subtitle,
15455
+ paymentNetworks: projectConfig?.payment_networks.networks
15456
+ },
15457
+ "card"
15458
+ ) : null;
15459
+ const payWithExchangeMenuButton = showPayWithExchange ? /* @__PURE__ */ jsx55(
15460
+ PayWithExchangeButton,
15461
+ {
15462
+ onClick: () => setView("exchange"),
15463
+ title: payWithExchangeTitle,
15464
+ subtitle: t7.payWithExchange.subtitle,
15465
+ exchanges,
15466
+ loading: exchangesLoading
15467
+ },
15468
+ "exchange"
15469
+ ) : null;
15470
+ const connectExchangeMenuButton = showConnectExchange && connectedExchange ? /* @__PURE__ */ jsx55(
15471
+ ConnectExchangeButton,
15472
+ {
15473
+ onClick: () => {
15474
+ setCoinbaseSkipToHoldings(true);
15475
+ setView("coinbase_connect");
15476
+ },
15477
+ onDisconnect: handleExchangeDisconnect,
15478
+ title: i18n.connectExchange.title,
15479
+ subtitle: i18n.connectExchange.subtitle,
15480
+ exchanges: integrationExchanges,
15481
+ connectedExchange
15482
+ },
15483
+ "connect-exchange"
15484
+ ) : showConnectExchange && !connectedExchange ? /* @__PURE__ */ jsx55(
15485
+ ConnectExchangeButton,
15486
+ {
15487
+ onClick: () => {
15488
+ setCoinbaseSkipToHoldings(false);
15489
+ setView("coinbase_connect");
15490
+ },
15491
+ title: i18n.connectExchange.title,
15492
+ subtitle: i18n.connectExchange.subtitle,
15493
+ exchanges: integrationExchanges
15494
+ },
15495
+ "connect-exchange"
15496
+ ) : null;
15497
+ const cashAppMenuButton = showCashApp ? /* @__PURE__ */ jsx55(
15498
+ CashAppButton,
15499
+ {
15500
+ onClick: () => setView("cashapp"),
15501
+ title: "Pay with Cash App",
15502
+ subtitle: "Deposit via Cash App",
15503
+ iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
15504
+ },
15505
+ "cashapp"
15506
+ ) : null;
15507
+ const depositTrackerMenuButton = showDepositTracker ? /* @__PURE__ */ jsx55(
15508
+ DepositTrackerButton,
15509
+ {
15510
+ onClick: () => {
15511
+ setAllExecutions(depositExecutions);
15512
+ setView("tracker");
15513
+ },
15514
+ title: depositTrackerTitle,
15515
+ subtitle: depositTrackerSubTitle,
15516
+ badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
15517
+ },
15518
+ "tracker"
15519
+ ) : null;
15520
+ const cryptoMenuButtons = [
15521
+ transferCryptoMenuButton,
15522
+ connectWalletMenuButton,
15523
+ payWithExchangeMenuButton,
15524
+ connectExchangeMenuButton
15525
+ ].filter(Boolean);
15526
+ const cashMenuButtons = [
15527
+ depositWithCardMenuButton,
15528
+ cashAppMenuButton
15529
+ ].filter(Boolean);
15530
+ const depositTabs = [
15531
+ { id: "crypto", label: "Use Crypto", buttons: cryptoMenuButtons },
15532
+ { id: "cash", label: "Use Cash", buttons: cashMenuButtons }
15533
+ ].filter((tab) => tab.buttons.length > 0);
15534
+ const activeDepositTab = depositTabs.find((tab) => tab.id === depositTab) ?? depositTabs[0];
15535
+ const renderMainMenuBody = () => {
15536
+ if (depositPrerequisiteBody) {
15537
+ return /* @__PURE__ */ jsx55("div", { className: "uf-space-y-3", children: depositPrerequisiteBody });
15538
+ }
15539
+ if (displayMode === "tabs" && activeDepositTab) {
15540
+ return /* @__PURE__ */ jsxs49("div", { children: [
15541
+ depositTabs.length > 1 && /* @__PURE__ */ jsx55(
15542
+ "div",
15543
+ {
15544
+ className: "uf-flex uf-gap-1 uf-p-1 uf-rounded-xl uf-mb-3",
15545
+ style: {
15546
+ // Frosted-glass track: a translucent fill plus a backdrop blur so
15547
+ // the control reads as a soft surface rather than a solid bar.
15548
+ backgroundColor: `color-mix(in srgb, ${colors2.card} 55%, transparent)`,
15549
+ backdropFilter: "blur(12px)",
15550
+ WebkitBackdropFilter: "blur(12px)"
15551
+ },
15552
+ role: "tablist",
15553
+ children: depositTabs.map((tab) => {
15554
+ const active = activeDepositTab.id === tab.id;
15555
+ return /* @__PURE__ */ jsx55(
15556
+ "button",
15557
+ {
15558
+ type: "button",
15559
+ role: "tab",
15560
+ "aria-selected": active,
15561
+ onClick: () => setDepositTab(tab.id),
15562
+ className: "uf-flex-1 uf-py-2 uf-px-3 uf-rounded-lg uf-text-sm uf-transition-all",
15563
+ style: {
15564
+ // Active tab is a soft, blurred glass pill — a faint accent
15565
+ // tint with its own backdrop blur and a subtle border/shadow,
15566
+ // so it looks frosted instead of like a hard solid button.
15567
+ backgroundColor: active ? `color-mix(in srgb, ${colors2.primary} 22%, transparent)` : "transparent",
15568
+ backdropFilter: active ? "blur(8px)" : void 0,
15569
+ WebkitBackdropFilter: active ? "blur(8px)" : void 0,
15570
+ boxShadow: active ? `0 1px 8px color-mix(in srgb, ${colors2.primary} 25%, transparent)` : void 0,
15571
+ color: active ? colors2.foreground : colors2.foregroundMuted,
15572
+ fontFamily: fonts.medium
15573
+ },
15574
+ children: tab.label
15575
+ },
15576
+ tab.id
15577
+ );
15578
+ })
15579
+ }
15580
+ ),
15581
+ /* @__PURE__ */ jsx55("div", { className: "uf-space-y-3", children: activeDepositTab.buttons }),
15582
+ depositTrackerMenuButton && /* @__PURE__ */ jsx55("div", { className: "uf-mt-3", children: depositTrackerMenuButton })
15583
+ ] });
15584
+ }
15585
+ return /* @__PURE__ */ jsxs49("div", { className: "uf-space-y-3", children: [
15586
+ transferCryptoMenuButton,
15587
+ connectWalletMenuButton,
15588
+ depositWithCardMenuButton,
15589
+ payWithExchangeMenuButton,
15590
+ connectExchangeMenuButton,
15591
+ cashAppMenuButton,
15592
+ depositTrackerMenuButton
15593
+ ] });
15594
+ };
15281
15595
  return /* @__PURE__ */ jsx55(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ jsx55(
15282
15596
  Dialog,
15283
15597
  {
@@ -15304,7 +15618,7 @@ function DepositModal({
15304
15618
  onClose: handleClose,
15305
15619
  showBalance: showBalanceHeader,
15306
15620
  balanceAddress: recipientAddress,
15307
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
15621
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
15308
15622
  balanceChainId: destinationChainId,
15309
15623
  balanceTokenAddress: destinationTokenAddress,
15310
15624
  projectName: projectConfig?.project_name,
@@ -15312,94 +15626,7 @@ function DepositModal({
15312
15626
  }
15313
15627
  ),
15314
15628
  /* @__PURE__ */ jsxs49("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
15315
- /* @__PURE__ */ jsx55("div", { className: "uf-space-y-3", children: depositPrerequisiteBody ?? /* @__PURE__ */ jsxs49(Fragment11, { children: [
15316
- showTransferCrypto && /* @__PURE__ */ jsx55(
15317
- TransferCryptoButton,
15318
- {
15319
- onClick: () => setView("transfer"),
15320
- title: transferCryptoTitle,
15321
- subtitle: t7.transferCrypto.subtitle,
15322
- featuredTokens: projectConfig?.transfer_crypto.networks
15323
- }
15324
- ),
15325
- showConnectWallet && /* @__PURE__ */ jsx55(
15326
- BrowserWalletButton,
15327
- {
15328
- onClick: handleBrowserWalletClick,
15329
- onConnectClick: handleWalletConnectClick,
15330
- onDisconnect: handleWalletDisconnect,
15331
- chainType: browserWalletChainType,
15332
- publishableKey,
15333
- featuredWallets: projectConfig?.connect_wallet?.wallets
15334
- }
15335
- ),
15336
- showFiatOnramp && /* @__PURE__ */ jsx55(
15337
- DepositWithCardButton,
15338
- {
15339
- onClick: () => setView("card"),
15340
- title: depositWithCardTitle,
15341
- subtitle: t7.depositWithCard.subtitle,
15342
- paymentNetworks: projectConfig?.payment_networks.networks
15343
- }
15344
- ),
15345
- showPayWithExchange && /* @__PURE__ */ jsx55(
15346
- PayWithExchangeButton,
15347
- {
15348
- onClick: () => setView("exchange"),
15349
- title: payWithExchangeTitle,
15350
- subtitle: t7.payWithExchange.subtitle,
15351
- exchanges,
15352
- loading: exchangesLoading
15353
- }
15354
- ),
15355
- showConnectExchange && connectedExchange && /* @__PURE__ */ jsx55(
15356
- ConnectExchangeButton,
15357
- {
15358
- onClick: () => {
15359
- setCoinbaseSkipToHoldings(true);
15360
- setView("coinbase_connect");
15361
- },
15362
- onDisconnect: handleExchangeDisconnect,
15363
- title: i18n.connectExchange.title,
15364
- subtitle: i18n.connectExchange.subtitle,
15365
- exchanges: integrationExchanges,
15366
- connectedExchange
15367
- }
15368
- ),
15369
- showConnectExchange && !connectedExchange && /* @__PURE__ */ jsx55(
15370
- ConnectExchangeButton,
15371
- {
15372
- onClick: () => {
15373
- setCoinbaseSkipToHoldings(false);
15374
- setView("coinbase_connect");
15375
- },
15376
- title: i18n.connectExchange.title,
15377
- subtitle: i18n.connectExchange.subtitle,
15378
- exchanges: integrationExchanges
15379
- }
15380
- ),
15381
- showCashApp && /* @__PURE__ */ jsx55(
15382
- CashAppButton,
15383
- {
15384
- onClick: () => setView("cashapp"),
15385
- title: "Pay with Cash App",
15386
- subtitle: "Deposit via Cash App",
15387
- iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0
15388
- }
15389
- ),
15390
- showDepositTracker && /* @__PURE__ */ jsx55(
15391
- DepositTrackerButton,
15392
- {
15393
- onClick: () => {
15394
- setAllExecutions(depositExecutions);
15395
- setView("tracker");
15396
- },
15397
- title: depositTrackerTitle,
15398
- subtitle: depositTrackerSubTitle,
15399
- badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
15400
- }
15401
- )
15402
- ] }) }),
15629
+ renderMainMenuBody(),
15403
15630
  depositPoweredByFooter
15404
15631
  ] })
15405
15632
  ] }) : view === "transfer" ? /* @__PURE__ */ jsxs49(Fragment11, { children: [
@@ -15412,7 +15639,7 @@ function DepositModal({
15412
15639
  onClose: handleClose,
15413
15640
  showBalance: showBalanceHeader,
15414
15641
  balanceAddress: recipientAddress,
15415
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
15642
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
15416
15643
  balanceChainId: destinationChainId,
15417
15644
  balanceTokenAddress: destinationTokenAddress,
15418
15645
  projectName: projectConfig?.project_name,
@@ -15500,7 +15727,7 @@ function DepositModal({
15500
15727
  badge: cardView === "quotes" ? { count: quotesCount } : void 0,
15501
15728
  showBalance: showBalanceHeader,
15502
15729
  balanceAddress: recipientAddress,
15503
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
15730
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
15504
15731
  balanceChainId: destinationChainId,
15505
15732
  balanceTokenAddress: destinationTokenAddress,
15506
15733
  projectName: projectConfig?.project_name,
@@ -16834,7 +17061,7 @@ import {
16834
17061
  Wallet as Wallet3
16835
17062
  } from "lucide-react";
16836
17063
  import {
16837
- checkHypercoreActivation as checkHypercoreActivation2
17064
+ checkHypercoreActivation as checkHypercoreActivation3
16838
17065
  } from "@unifold/core";
16839
17066
 
16840
17067
  // src/hooks/use-verify-recipient-address.ts
@@ -16882,9 +17109,7 @@ function useVerifyRecipientAddress(params) {
16882
17109
  // src/components/withdrawals/send-withdraw.ts
16883
17110
  import {
16884
17111
  buildSolanaTransaction as buildSolanaTransaction2,
16885
- sendSolanaTransaction as sendSolanaTransactionToBackend2,
16886
- buildHypercoreTransaction as buildHypercoreTransactionFromBackend,
16887
- sendHypercoreTransaction as sendHypercoreTransactionToBackend
17112
+ sendSolanaTransaction as sendSolanaTransactionToBackend2
16888
17113
  } from "@unifold/core";
16889
17114
  async function sendEvmWithdraw(params) {
16890
17115
  const {
@@ -16995,50 +17220,15 @@ async function sendSolanaWithdraw(params) {
16995
17220
  );
16996
17221
  return sendResponse.signature;
16997
17222
  }
16998
- var HYPERCORE_SPOT_USDC_ADDRESS = "0x6d1e7cde53ba9467b783cb7c530ce054";
16999
- function isHypercoreChain(chainId) {
17000
- return chainId === HYPERCORE_CHAIN_ID;
17001
- }
17002
17223
  async function sendHypercoreWithdraw(params) {
17003
- const {
17004
- provider,
17005
- fromAddress,
17006
- depositWalletAddress,
17007
- sourceTokenAddress,
17008
- amount,
17009
- tokenSymbol,
17010
- publishableKey
17011
- } = params;
17012
- const isSpot = sourceTokenAddress.toLowerCase() === HYPERCORE_SPOT_USDC_ADDRESS;
17013
- const currentChainHex = await provider.request({
17014
- method: "eth_chainId",
17015
- params: []
17016
- });
17017
- const activeChainId = String(parseInt(currentChainHex, 16));
17018
- const buildResult = await buildHypercoreTransactionFromBackend(
17019
- {
17020
- action_type: isSpot ? "spot_send" : "usd_send",
17021
- signature_chain_type: "ethereum",
17022
- signature_chain_id: activeChainId,
17023
- recipient_address: depositWalletAddress,
17024
- token_address: sourceTokenAddress,
17025
- token_symbol: tokenSymbol || void 0,
17026
- amount
17027
- },
17028
- publishableKey
17029
- );
17030
- const signature = await provider.request({
17031
- method: "eth_signTypedData_v4",
17032
- params: [fromAddress, JSON.stringify(buildResult.typed_data)]
17224
+ await sendHypercoreEvmTransfer({
17225
+ provider: params.provider,
17226
+ fromAddress: params.fromAddress,
17227
+ recipientAddress: params.depositWalletAddress,
17228
+ sourceTokenAddress: params.sourceTokenAddress,
17229
+ amount: params.amount,
17230
+ publishableKey: params.publishableKey
17033
17231
  });
17034
- await sendHypercoreTransactionToBackend(
17035
- {
17036
- action_payload: buildResult.action_payload,
17037
- signature,
17038
- nonce: buildResult.nonce
17039
- },
17040
- publishableKey
17041
- );
17042
17232
  }
17043
17233
  async function detectBrowserWallet(chainType, senderAddress) {
17044
17234
  const win = typeof window !== "undefined" ? window : null;
@@ -17474,7 +17664,7 @@ function WithdrawForm({
17474
17664
  let humanAmount = isMaxed ? balanceData.balanceHuman : toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
17475
17665
  if (isHypercoreChain(sourceChainId)) {
17476
17666
  try {
17477
- const check = await checkHypercoreActivation2(
17667
+ const check = await checkHypercoreActivation3(
17478
17668
  {
17479
17669
  source_address: senderAddress,
17480
17670
  recipient_address: depositWallet.address
@@ -18070,8 +18260,6 @@ function WithdrawConfirmingView({
18070
18260
  className: "uf-text-sm uf-text-center",
18071
18261
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18072
18262
  children: [
18073
- txInfo.amount,
18074
- " ",
18075
18263
  txInfo.sourceTokenSymbol,
18076
18264
  " to",
18077
18265
  " ",