@unifold/ui-react 0.1.43 → 0.1.44

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.d.mts CHANGED
@@ -567,46 +567,6 @@ declare function useAddressBalance(params: {
567
567
  enabled?: boolean;
568
568
  }): _tanstack_react_query.UseQueryResult<AddressBalanceResult | null, Error>;
569
569
 
570
- type DetectedWallet = {
571
- name: string;
572
- address: string;
573
- } & ({
574
- chainFamily: "evm";
575
- provider: EvmWalletProvider;
576
- } | {
577
- chainFamily: "solana";
578
- provider: SolanaWalletProvider;
579
- });
580
- declare function sendEvmWithdraw(params: {
581
- provider: EvmWalletProvider;
582
- fromAddress: string;
583
- depositWalletAddress: string;
584
- sourceTokenAddress: string;
585
- sourceChainId: string;
586
- amountBaseUnit: string;
587
- }): Promise<string>;
588
- declare function sendSolanaWithdraw(params: {
589
- provider: SolanaWalletProvider;
590
- fromAddress: string;
591
- depositWalletAddress: string;
592
- sourceTokenAddress: string;
593
- amountBaseUnit: string;
594
- publishableKey: string;
595
- }): Promise<string>;
596
- declare const HYPERCORE_CHAIN_ID = "1337";
597
- declare function isHypercoreChain(chainId: string): boolean;
598
- declare function sendHypercoreWithdraw(params: {
599
- provider: EvmWalletProvider;
600
- fromAddress: string;
601
- depositWalletAddress: string;
602
- sourceTokenAddress: string;
603
- amount: string;
604
- tokenSymbol: string;
605
- publishableKey: string;
606
- }): Promise<void>;
607
-
608
- declare function detectBrowserWallet(chainType: string, senderAddress?: string): Promise<DetectedWallet | null>;
609
-
610
570
  interface WithdrawFormProps {
611
571
  publishableKey: string;
612
572
  externalUserId: string;
@@ -621,13 +581,9 @@ interface WithdrawFormProps {
621
581
  estimatedProcessingTime: number | null;
622
582
  maxSlippagePercent: number | null;
623
583
  priceImpactPercent: number | null;
624
- /** Detected browser wallet with provider ref — used for SDK-native sends */
625
- detectedWallet: DetectedWallet | null;
584
+ senderAddress: string;
626
585
  sourceChainId: string;
627
586
  sourceTokenAddress: string;
628
- isWalletMatch: boolean;
629
- connectedWalletName: string | null;
630
- canWithdraw: boolean;
631
587
  onWithdraw?: (txInfo: WithdrawTransactionInfo) => void | Promise<void>;
632
588
  onWithdrawError?: (error: {
633
589
  message: string;
@@ -649,7 +605,7 @@ interface WithdrawFormProps {
649
605
  /** Optional element rendered on the left side of the footer row (e.g. tracker link) */
650
606
  footerLeft?: React.ReactNode;
651
607
  }
652
- declare function WithdrawForm({ publishableKey, externalUserId, sourceChainType, selectedToken, selectedChain, sourceTokenSymbol, recipientAddressProp, balanceData, isLoadingBalance, minimumWithdrawAmountUsd, estimatedProcessingTime, maxSlippagePercent, priceImpactPercent, detectedWallet, sourceChainId, sourceTokenAddress, isWalletMatch, connectedWalletName, canWithdraw, onWithdraw, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, footerLeft, }: WithdrawFormProps): react_jsx_runtime.JSX.Element;
608
+ declare function WithdrawForm({ publishableKey, externalUserId, sourceChainType, selectedToken, selectedChain, sourceTokenSymbol, recipientAddressProp, balanceData, isLoadingBalance, minimumWithdrawAmountUsd, estimatedProcessingTime, maxSlippagePercent, priceImpactPercent, senderAddress, sourceChainId, sourceTokenAddress, onWithdraw, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, footerLeft, }: WithdrawFormProps): react_jsx_runtime.JSX.Element;
653
609
 
654
610
  interface WithdrawExecutionItemProps {
655
611
  execution: AutoSwapResponse;
@@ -665,6 +621,46 @@ interface WithdrawConfirmingViewProps {
665
621
  }
666
622
  declare function WithdrawConfirmingView({ txInfo, executions, onClose, onViewTracker, }: WithdrawConfirmingViewProps): react_jsx_runtime.JSX.Element;
667
623
 
624
+ type DetectedWallet = {
625
+ name: string;
626
+ address: string;
627
+ } & ({
628
+ chainFamily: "evm";
629
+ provider: EvmWalletProvider;
630
+ } | {
631
+ chainFamily: "solana";
632
+ provider: SolanaWalletProvider;
633
+ });
634
+ declare function sendEvmWithdraw(params: {
635
+ provider: EvmWalletProvider;
636
+ fromAddress: string;
637
+ depositWalletAddress: string;
638
+ sourceTokenAddress: string;
639
+ sourceChainId: string;
640
+ amountBaseUnit: string;
641
+ }): Promise<string>;
642
+ declare function sendSolanaWithdraw(params: {
643
+ provider: SolanaWalletProvider;
644
+ fromAddress: string;
645
+ depositWalletAddress: string;
646
+ sourceTokenAddress: string;
647
+ amountBaseUnit: string;
648
+ publishableKey: string;
649
+ }): Promise<string>;
650
+ declare const HYPERCORE_CHAIN_ID = "1337";
651
+ declare function isHypercoreChain(chainId: string): boolean;
652
+ declare function sendHypercoreWithdraw(params: {
653
+ provider: EvmWalletProvider;
654
+ fromAddress: string;
655
+ depositWalletAddress: string;
656
+ sourceTokenAddress: string;
657
+ amount: string;
658
+ tokenSymbol: string;
659
+ publishableKey: string;
660
+ }): Promise<void>;
661
+
662
+ declare function detectBrowserWallet(chainType: string, senderAddress?: string): Promise<DetectedWallet | null>;
663
+
668
664
  interface CurrencyListItemProps {
669
665
  currency: FiatCurrency;
670
666
  isSelected: boolean;
package/dist/index.d.ts CHANGED
@@ -567,46 +567,6 @@ declare function useAddressBalance(params: {
567
567
  enabled?: boolean;
568
568
  }): _tanstack_react_query.UseQueryResult<AddressBalanceResult | null, Error>;
569
569
 
570
- type DetectedWallet = {
571
- name: string;
572
- address: string;
573
- } & ({
574
- chainFamily: "evm";
575
- provider: EvmWalletProvider;
576
- } | {
577
- chainFamily: "solana";
578
- provider: SolanaWalletProvider;
579
- });
580
- declare function sendEvmWithdraw(params: {
581
- provider: EvmWalletProvider;
582
- fromAddress: string;
583
- depositWalletAddress: string;
584
- sourceTokenAddress: string;
585
- sourceChainId: string;
586
- amountBaseUnit: string;
587
- }): Promise<string>;
588
- declare function sendSolanaWithdraw(params: {
589
- provider: SolanaWalletProvider;
590
- fromAddress: string;
591
- depositWalletAddress: string;
592
- sourceTokenAddress: string;
593
- amountBaseUnit: string;
594
- publishableKey: string;
595
- }): Promise<string>;
596
- declare const HYPERCORE_CHAIN_ID = "1337";
597
- declare function isHypercoreChain(chainId: string): boolean;
598
- declare function sendHypercoreWithdraw(params: {
599
- provider: EvmWalletProvider;
600
- fromAddress: string;
601
- depositWalletAddress: string;
602
- sourceTokenAddress: string;
603
- amount: string;
604
- tokenSymbol: string;
605
- publishableKey: string;
606
- }): Promise<void>;
607
-
608
- declare function detectBrowserWallet(chainType: string, senderAddress?: string): Promise<DetectedWallet | null>;
609
-
610
570
  interface WithdrawFormProps {
611
571
  publishableKey: string;
612
572
  externalUserId: string;
@@ -621,13 +581,9 @@ interface WithdrawFormProps {
621
581
  estimatedProcessingTime: number | null;
622
582
  maxSlippagePercent: number | null;
623
583
  priceImpactPercent: number | null;
624
- /** Detected browser wallet with provider ref — used for SDK-native sends */
625
- detectedWallet: DetectedWallet | null;
584
+ senderAddress: string;
626
585
  sourceChainId: string;
627
586
  sourceTokenAddress: string;
628
- isWalletMatch: boolean;
629
- connectedWalletName: string | null;
630
- canWithdraw: boolean;
631
587
  onWithdraw?: (txInfo: WithdrawTransactionInfo) => void | Promise<void>;
632
588
  onWithdrawError?: (error: {
633
589
  message: string;
@@ -649,7 +605,7 @@ interface WithdrawFormProps {
649
605
  /** Optional element rendered on the left side of the footer row (e.g. tracker link) */
650
606
  footerLeft?: React.ReactNode;
651
607
  }
652
- declare function WithdrawForm({ publishableKey, externalUserId, sourceChainType, selectedToken, selectedChain, sourceTokenSymbol, recipientAddressProp, balanceData, isLoadingBalance, minimumWithdrawAmountUsd, estimatedProcessingTime, maxSlippagePercent, priceImpactPercent, detectedWallet, sourceChainId, sourceTokenAddress, isWalletMatch, connectedWalletName, canWithdraw, onWithdraw, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, footerLeft, }: WithdrawFormProps): react_jsx_runtime.JSX.Element;
608
+ declare function WithdrawForm({ publishableKey, externalUserId, sourceChainType, selectedToken, selectedChain, sourceTokenSymbol, recipientAddressProp, balanceData, isLoadingBalance, minimumWithdrawAmountUsd, estimatedProcessingTime, maxSlippagePercent, priceImpactPercent, senderAddress, sourceChainId, sourceTokenAddress, onWithdraw, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, footerLeft, }: WithdrawFormProps): react_jsx_runtime.JSX.Element;
653
609
 
654
610
  interface WithdrawExecutionItemProps {
655
611
  execution: AutoSwapResponse;
@@ -665,6 +621,46 @@ interface WithdrawConfirmingViewProps {
665
621
  }
666
622
  declare function WithdrawConfirmingView({ txInfo, executions, onClose, onViewTracker, }: WithdrawConfirmingViewProps): react_jsx_runtime.JSX.Element;
667
623
 
624
+ type DetectedWallet = {
625
+ name: string;
626
+ address: string;
627
+ } & ({
628
+ chainFamily: "evm";
629
+ provider: EvmWalletProvider;
630
+ } | {
631
+ chainFamily: "solana";
632
+ provider: SolanaWalletProvider;
633
+ });
634
+ declare function sendEvmWithdraw(params: {
635
+ provider: EvmWalletProvider;
636
+ fromAddress: string;
637
+ depositWalletAddress: string;
638
+ sourceTokenAddress: string;
639
+ sourceChainId: string;
640
+ amountBaseUnit: string;
641
+ }): Promise<string>;
642
+ declare function sendSolanaWithdraw(params: {
643
+ provider: SolanaWalletProvider;
644
+ fromAddress: string;
645
+ depositWalletAddress: string;
646
+ sourceTokenAddress: string;
647
+ amountBaseUnit: string;
648
+ publishableKey: string;
649
+ }): Promise<string>;
650
+ declare const HYPERCORE_CHAIN_ID = "1337";
651
+ declare function isHypercoreChain(chainId: string): boolean;
652
+ declare function sendHypercoreWithdraw(params: {
653
+ provider: EvmWalletProvider;
654
+ fromAddress: string;
655
+ depositWalletAddress: string;
656
+ sourceTokenAddress: string;
657
+ amount: string;
658
+ tokenSymbol: string;
659
+ publishableKey: string;
660
+ }): Promise<void>;
661
+
662
+ declare function detectBrowserWallet(chainType: string, senderAddress?: string): Promise<DetectedWallet | null>;
663
+
668
664
  interface CurrencyListItemProps {
669
665
  currency: FiatCurrency;
670
666
  isSelected: boolean;
package/dist/index.js CHANGED
@@ -13589,6 +13589,7 @@ function WithdrawDoubleInput({
13589
13589
  // src/components/withdrawals/WithdrawForm.tsx
13590
13590
  var import_react21 = require("react");
13591
13591
  var import_lucide_react25 = require("lucide-react");
13592
+ var import_core33 = require("@unifold/core");
13592
13593
 
13593
13594
  // src/hooks/use-verify-recipient-address.ts
13594
13595
  var import_react_query15 = require("@tanstack/react-query");
@@ -13792,6 +13793,7 @@ async function sendHypercoreWithdraw(params) {
13792
13793
  async function detectBrowserWallet(chainType, senderAddress) {
13793
13794
  const win = typeof window !== "undefined" ? window : null;
13794
13795
  if (!win || !senderAddress) return null;
13796
+ if (getUserDisconnectedWallet()) return null;
13795
13797
  const anyWin = win;
13796
13798
  if (chainType === "solana") {
13797
13799
  const solProviders = [];
@@ -13825,28 +13827,44 @@ async function detectBrowserWallet(chainType, senderAddress) {
13825
13827
  evmProviders.push({ provider: p, name });
13826
13828
  }
13827
13829
  };
13828
- add(anyWin.phantom?.ethereum, "Phantom");
13829
- add(anyWin.coinbaseWalletExtension, "Coinbase");
13830
- add(anyWin.trustwallet?.ethereum, "Trust Wallet");
13831
- add(anyWin.okxwallet, "OKX Wallet");
13832
- if (anyWin.__eip6963Providers) {
13833
- for (const detail of anyWin.__eip6963Providers) {
13834
- const rdns = detail.info?.rdns || "";
13835
- let name = detail.info?.name || "Wallet";
13836
- if (rdns.includes("metamask")) name = "MetaMask";
13837
- else if (rdns.includes("rabby")) name = "Rabby";
13838
- else if (rdns.includes("rainbow")) name = "Rainbow";
13839
- add(detail.provider, name);
13840
- }
13830
+ if (!anyWin.__eip6963Providers) {
13831
+ anyWin.__eip6963Providers = [];
13841
13832
  }
13842
- if (win.ethereum) {
13843
- const eth = win.ethereum;
13844
- let name = "Wallet";
13845
- if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
13846
- else if (eth.isRabby) name = "Rabby";
13847
- else if (eth.isRainbow) name = "Rainbow";
13848
- else if (eth.isCoinbaseWallet) name = "Coinbase";
13849
- add(eth, name);
13833
+ const handleAnnouncement = (event) => {
13834
+ const { detail } = event;
13835
+ if (!detail?.info || !detail?.provider) return;
13836
+ const exists = anyWin.__eip6963Providers.some((p) => p.info.uuid === detail.info.uuid);
13837
+ if (!exists) anyWin.__eip6963Providers.push(detail);
13838
+ };
13839
+ win.addEventListener("eip6963:announceProvider", handleAnnouncement);
13840
+ win.dispatchEvent(new Event("eip6963:requestProvider"));
13841
+ win.removeEventListener("eip6963:announceProvider", handleAnnouncement);
13842
+ for (const detail of anyWin.__eip6963Providers) {
13843
+ const rdns = detail.info?.rdns || "";
13844
+ let name = detail.info?.name || "Wallet";
13845
+ if (rdns.includes("metamask")) name = "MetaMask";
13846
+ else if (rdns.includes("phantom")) name = "Phantom";
13847
+ else if (rdns.includes("coinbase")) name = "Coinbase";
13848
+ else if (rdns.includes("rabby")) name = "Rabby";
13849
+ else if (rdns.includes("rainbow")) name = "Rainbow";
13850
+ else if (rdns.includes("okx")) name = "OKX Wallet";
13851
+ else if (rdns.includes("trust")) name = "Trust Wallet";
13852
+ add(detail.provider, name);
13853
+ }
13854
+ if (evmProviders.length === 0) {
13855
+ add(anyWin.phantom?.ethereum, "Phantom");
13856
+ add(anyWin.coinbaseWalletExtension, "Coinbase");
13857
+ add(anyWin.trustwallet?.ethereum, "Trust Wallet");
13858
+ add(anyWin.okxwallet, "OKX Wallet");
13859
+ if (evmProviders.length === 0 && win.ethereum) {
13860
+ const eth = win.ethereum;
13861
+ let name = "Wallet";
13862
+ if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
13863
+ else if (eth.isRabby) name = "Rabby";
13864
+ else if (eth.isRainbow) name = "Rainbow";
13865
+ else if (eth.isCoinbaseWallet) name = "Coinbase";
13866
+ add(eth, name);
13867
+ }
13850
13868
  }
13851
13869
  for (const { provider, name } of evmProviders) {
13852
13870
  try {
@@ -13902,12 +13920,9 @@ function WithdrawForm({
13902
13920
  estimatedProcessingTime,
13903
13921
  maxSlippagePercent,
13904
13922
  priceImpactPercent,
13905
- detectedWallet,
13923
+ senderAddress,
13906
13924
  sourceChainId,
13907
13925
  sourceTokenAddress,
13908
- isWalletMatch,
13909
- connectedWalletName,
13910
- canWithdraw,
13911
13926
  onWithdraw,
13912
13927
  onWithdrawError,
13913
13928
  onDepositWalletCreation,
@@ -14042,12 +14057,43 @@ function WithdrawForm({
14042
14057
  destinationTokenAddress: selectedChain.token_address,
14043
14058
  recipientAddress: trimmedAddress
14044
14059
  });
14045
- const amountBaseUnit = computeBaseUnit(
14060
+ let amountBaseUnit = computeBaseUnit(
14046
14061
  balanceData.balanceBaseUnit,
14047
14062
  parseFloat(amount),
14048
14063
  inputUnit === "crypto" ? balanceCrypto : balanceUsdNum
14049
14064
  );
14050
- const humanAmount = toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
14065
+ let humanAmount = toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
14066
+ if (isHypercoreChain(sourceChainId)) {
14067
+ try {
14068
+ const check = await (0, import_core33.checkHypercoreActivation)(
14069
+ {
14070
+ source_address: senderAddress,
14071
+ recipient_address: depositWallet.address
14072
+ },
14073
+ publishableKey
14074
+ );
14075
+ if (!check.user_exists) {
14076
+ const fee = check.activation_fee;
14077
+ const maxSendable = balanceCrypto - fee;
14078
+ if (maxSendable <= 0) {
14079
+ throw new Error(
14080
+ `Insufficient balance. A ${fee} USDC activation fee is required for the first transfer to this address.`
14081
+ );
14082
+ }
14083
+ const requestedAmount = parseFloat(humanAmount);
14084
+ if (requestedAmount > maxSendable) {
14085
+ humanAmount = toSafeDecimalString(maxSendable, sourceDecimals);
14086
+ amountBaseUnit = computeBaseUnit(
14087
+ balanceData.balanceBaseUnit,
14088
+ maxSendable,
14089
+ balanceCrypto
14090
+ );
14091
+ }
14092
+ }
14093
+ } catch (e) {
14094
+ if (e instanceof Error && e.message.includes("activation fee")) throw e;
14095
+ }
14096
+ }
14051
14097
  const txInfo = {
14052
14098
  sourceChainType,
14053
14099
  sourceChainId,
@@ -14062,43 +14108,67 @@ function WithdrawForm({
14062
14108
  withdrawIntentAddress: depositWallet.address,
14063
14109
  recipientAddress: trimmedAddress
14064
14110
  };
14065
- if (detectedWallet) {
14066
- if (detectedWallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
14067
- await sendHypercoreWithdraw({
14068
- provider: detectedWallet.provider,
14069
- fromAddress: detectedWallet.address,
14070
- depositWalletAddress: depositWallet.address,
14071
- sourceTokenAddress,
14111
+ const wallet = await detectBrowserWallet(sourceChainType, senderAddress);
14112
+ console.log("browser wallet", wallet);
14113
+ if (wallet) {
14114
+ try {
14115
+ if (wallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
14116
+ await sendHypercoreWithdraw({
14117
+ provider: wallet.provider,
14118
+ fromAddress: wallet.address,
14119
+ depositWalletAddress: depositWallet.address,
14120
+ sourceTokenAddress,
14121
+ amount: humanAmount,
14122
+ tokenSymbol,
14123
+ publishableKey
14124
+ });
14125
+ } else if (wallet.chainFamily === "evm") {
14126
+ await sendEvmWithdraw({
14127
+ provider: wallet.provider,
14128
+ fromAddress: wallet.address,
14129
+ depositWalletAddress: depositWallet.address,
14130
+ sourceTokenAddress,
14131
+ sourceChainId,
14132
+ amountBaseUnit
14133
+ });
14134
+ } else if (wallet.chainFamily === "solana") {
14135
+ await sendSolanaWithdraw({
14136
+ provider: wallet.provider,
14137
+ fromAddress: wallet.address,
14138
+ depositWalletAddress: depositWallet.address,
14139
+ sourceTokenAddress,
14140
+ amountBaseUnit,
14141
+ publishableKey
14142
+ });
14143
+ }
14144
+ } catch (walletErr) {
14145
+ console.error("[Unifold] Browser wallet send failed:", walletErr, {
14146
+ wallet: `${wallet.name} (${wallet.chainFamily})`,
14147
+ sourceChainId,
14072
14148
  amount: humanAmount,
14073
- tokenSymbol,
14074
- publishableKey
14149
+ amountBaseUnit,
14150
+ depositWallet: depositWallet.address
14075
14151
  });
14076
- } else if (detectedWallet.chainFamily === "evm") {
14077
- await sendEvmWithdraw({
14078
- provider: detectedWallet.provider,
14079
- fromAddress: detectedWallet.address,
14080
- depositWalletAddress: depositWallet.address,
14081
- sourceTokenAddress,
14152
+ throw walletErr;
14153
+ }
14154
+ } else if (onWithdraw) {
14155
+ try {
14156
+ await onWithdraw(txInfo);
14157
+ } catch (callbackErr) {
14158
+ console.error("[Unifold] onWithdraw callback failed:", callbackErr, {
14082
14159
  sourceChainId,
14083
- amountBaseUnit
14084
- });
14085
- } else if (detectedWallet.chainFamily === "solana") {
14086
- await sendSolanaWithdraw({
14087
- provider: detectedWallet.provider,
14088
- fromAddress: detectedWallet.address,
14089
- depositWalletAddress: depositWallet.address,
14090
- sourceTokenAddress,
14160
+ amount: humanAmount,
14091
14161
  amountBaseUnit,
14092
- publishableKey
14162
+ depositWallet: depositWallet.address
14093
14163
  });
14164
+ throw callbackErr;
14094
14165
  }
14095
- } else if (onWithdraw) {
14096
- await onWithdraw(txInfo);
14097
14166
  } else {
14098
14167
  throw new Error("No withdrawal method available. Please connect a wallet.");
14099
14168
  }
14100
14169
  onWithdrawSubmitted?.(txInfo);
14101
14170
  } catch (err) {
14171
+ console.error("[Unifold] Withdrawal failed:", err);
14102
14172
  const raw = err instanceof Error ? err.message : "Withdrawal failed. Please try again.";
14103
14173
  setSubmitError(raw.length > 120 ? "Withdrawal failed. Please try again." : raw);
14104
14174
  onWithdrawError?.({
@@ -14109,7 +14179,7 @@ function WithdrawForm({
14109
14179
  } finally {
14110
14180
  setIsSubmitting(false);
14111
14181
  }
14112
- }, [selectedToken, selectedChain, isFormValid, cryptoAmountFromInput, sourceDecimals, trimmedAddress, publishableKey, onWithdraw, detectedWallet, sourceTokenAddress, sourceChainId, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, amount, inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
14182
+ }, [selectedToken, selectedChain, isFormValid, cryptoAmountFromInput, sourceDecimals, trimmedAddress, publishableKey, onWithdraw, sourceChainType, senderAddress, sourceTokenAddress, sourceChainId, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, amount, inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
14113
14183
  return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
14114
14184
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { children: [
14115
14185
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
@@ -14320,23 +14390,12 @@ function WithdrawForm({
14320
14390
  ] })
14321
14391
  ] })
14322
14392
  ] }),
14323
- !canWithdraw && !submitError && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
14324
- "div",
14325
- {
14326
- className: "uf-flex uf-items-start uf-gap-2.5 uf-p-3 uf-rounded-xl",
14327
- style: { backgroundColor: colors2.card, border: `1px solid ${colors2.border}` },
14328
- children: [
14329
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react25.Wallet, { className: "uf-w-4 uf-h-4 uf-flex-shrink-0 uf-mt-0.5", style: { color: colors2.warning } }),
14330
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No connected wallet detected. Please connect a wallet that matches your account to withdraw." })
14331
- ]
14332
- }
14333
- ),
14334
- isWalletMatch && connectedWalletName ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
14393
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
14335
14394
  "button",
14336
14395
  {
14337
14396
  type: "button",
14338
14397
  onClick: handleWithdraw,
14339
- disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
14398
+ disabled: !isFormValid || isSubmitting || !selectedToken || !selectedChain,
14340
14399
  className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed uf-flex uf-items-center uf-justify-center uf-gap-2",
14341
14400
  style: {
14342
14401
  backgroundColor: colors2.primary,
@@ -14350,29 +14409,9 @@ function WithdrawForm({
14350
14409
  "Processing..."
14351
14410
  ] }) : isOverBalance ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children: "Insufficient balance" }) : isBelowMinimum ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children: "Minimum amount not met" }) : submitError ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children: "Withdrawal failed. Try again" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
14352
14411
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react25.Wallet, { className: "uf-w-4 uf-h-4" }),
14353
- "Withdraw from ",
14354
- connectedWalletName
14412
+ t8.withdraw
14355
14413
  ] })
14356
14414
  }
14357
- ) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
14358
- "button",
14359
- {
14360
- type: "button",
14361
- onClick: handleWithdraw,
14362
- disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
14363
- className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
14364
- style: {
14365
- backgroundColor: colors2.primary,
14366
- color: colors2.primaryForeground,
14367
- fontFamily: fonts.medium,
14368
- borderRadius: components.button.borderRadius,
14369
- border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
14370
- },
14371
- children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
14372
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react25.Loader2, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
14373
- "Processing..."
14374
- ] }) : isOverBalance ? "Insufficient balance" : isBelowMinimum ? "Minimum amount not met" : submitError ? "Withdrawal failed. Try again" : t8.withdraw
14375
- }
14376
14415
  ),
14377
14416
  /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-text-xs uf-pt-1", children: [
14378
14417
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { children: footerLeft }),
@@ -14390,14 +14429,14 @@ function WithdrawForm({
14390
14429
 
14391
14430
  // src/components/withdrawals/WithdrawExecutionItem.tsx
14392
14431
  var import_lucide_react26 = require("lucide-react");
14393
- var import_core33 = require("@unifold/core");
14432
+ var import_core34 = require("@unifold/core");
14394
14433
  var import_jsx_runtime55 = require("react/jsx-runtime");
14395
14434
  function WithdrawExecutionItem({
14396
14435
  execution,
14397
14436
  onClick
14398
14437
  }) {
14399
14438
  const { colors: colors2, fonts, components } = useTheme();
14400
- const isPending = execution.status === import_core33.ExecutionStatus.PENDING || execution.status === import_core33.ExecutionStatus.WAITING || execution.status === import_core33.ExecutionStatus.DELAYED;
14439
+ const isPending = execution.status === import_core34.ExecutionStatus.PENDING || execution.status === import_core34.ExecutionStatus.WAITING || execution.status === import_core34.ExecutionStatus.DELAYED;
14401
14440
  const formatDateTime = (timestamp) => {
14402
14441
  try {
14403
14442
  const date = new Date(timestamp);
@@ -14444,7 +14483,7 @@ function WithdrawExecutionItem({
14444
14483
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
14445
14484
  "img",
14446
14485
  {
14447
- src: execution.destination_token_metadata?.icon_url || (0, import_core33.getIconUrl)("/icons/tokens/svg/usdc.svg"),
14486
+ src: execution.destination_token_metadata?.icon_url || (0, import_core34.getIconUrl)("/icons/tokens/svg/usdc.svg"),
14448
14487
  alt: "Token",
14449
14488
  width: 36,
14450
14489
  height: 36,
@@ -14703,7 +14742,7 @@ function WithdrawConfirmingView({
14703
14742
  }
14704
14743
 
14705
14744
  // src/components/withdrawals/WithdrawModal.tsx
14706
- var import_core34 = require("@unifold/core");
14745
+ var import_core35 = require("@unifold/core");
14707
14746
  var import_jsx_runtime57 = require("react/jsx-runtime");
14708
14747
  var t9 = i18n.withdrawModal;
14709
14748
  var getChainKey5 = (chainId, chainType) => `${chainType}:${chainId}`;
@@ -14764,22 +14803,6 @@ function WithdrawModal({
14764
14803
  });
14765
14804
  const [selectedToken, setSelectedToken] = (0, import_react23.useState)(null);
14766
14805
  const [selectedChain, setSelectedChain] = (0, import_react23.useState)(null);
14767
- const [detectedWallet, setDetectedWallet] = (0, import_react23.useState)(null);
14768
- const connectedWalletName = detectedWallet?.name ?? null;
14769
- const isWalletMatch = !!detectedWallet;
14770
- (0, import_react23.useEffect)(() => {
14771
- if (!senderAddress || !open) {
14772
- setDetectedWallet(null);
14773
- return;
14774
- }
14775
- let cancelled = false;
14776
- detectBrowserWallet(sourceChainType, senderAddress).then((wallet) => {
14777
- if (!cancelled) setDetectedWallet(wallet);
14778
- });
14779
- return () => {
14780
- cancelled = true;
14781
- };
14782
- }, [senderAddress, sourceChainType, open]);
14783
14806
  const [view, setView] = (0, import_react23.useState)("form");
14784
14807
  const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react23.useState)();
14785
14808
  const [selectedExecution, setSelectedExecution] = (0, import_react23.useState)(null);
@@ -14793,24 +14816,24 @@ function WithdrawModal({
14793
14816
  onWithdrawError
14794
14817
  });
14795
14818
  const { data: allWithdrawalsData } = useExecutions(externalUserId, publishableKey, {
14796
- actionType: import_core34.ActionType.Withdraw,
14819
+ actionType: import_core35.ActionType.Withdraw,
14797
14820
  enabled: open,
14798
14821
  refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
14799
14822
  });
14800
14823
  const allWithdrawals = allWithdrawalsData?.data ?? [];
14801
14824
  const handleDepositWalletCreation = (0, import_react23.useCallback)(async (params) => {
14802
- const { data: wallets } = await (0, import_core34.createDepositAddress)(
14825
+ const { data: wallets } = await (0, import_core35.createDepositAddress)(
14803
14826
  {
14804
14827
  external_user_id: externalUserId,
14805
14828
  destination_chain_type: params.destinationChainType,
14806
14829
  destination_chain_id: params.destinationChainId,
14807
14830
  destination_token_address: params.destinationTokenAddress,
14808
14831
  recipient_address: params.recipientAddress,
14809
- action_type: import_core34.ActionType.Withdraw
14832
+ action_type: import_core35.ActionType.Withdraw
14810
14833
  },
14811
14834
  publishableKey
14812
14835
  );
14813
- const depositWallet = (0, import_core34.getWalletByChainType)(wallets, sourceChainType);
14836
+ const depositWallet = (0, import_core35.getWalletByChainType)(wallets, sourceChainType);
14814
14837
  if (!depositWallet) {
14815
14838
  throw new Error(`No deposit wallet available for ${sourceChainType}`);
14816
14839
  }
@@ -14872,7 +14895,6 @@ function WithdrawModal({
14872
14895
  if (chain) setSelectedChain(chain);
14873
14896
  }, [selectedToken]);
14874
14897
  const isSourceSupported = sourceValidation?.isSupported ?? null;
14875
- const canWithdraw = !!onWithdraw || isWalletMatch;
14876
14898
  const isAnyLoading = tokensLoading || isCheckingSourceToken;
14877
14899
  const withdrawPoweredByFooter = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PoweredByUnifold, { color: colors2.foregroundMuted, className: "uf-flex uf-justify-center uf-shrink-0" }) });
14878
14900
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Dialog, { open: hideOverlay || open, onOpenChange: hideOverlay ? void 0 : handleClose, modal: !hideOverlay, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
@@ -14903,7 +14925,7 @@ function WithdrawModal({
14903
14925
  /* ---------- Tracker view: execution list ---------- */
14904
14926
  /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
14905
14927
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(DepositHeader, { title: "Withdrawal History", showBack: true, showClose: !hideOverlay, onBack: () => setView("form"), onClose: handleClose }),
14906
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-flex uf-flex-col uf-gap-2", style: { minHeight: 200 }, children: allWithdrawals.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uf-text-sm", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No withdrawals to track yet" }) }) : allWithdrawals.map((ex) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14928
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-flex uf-flex-col uf-gap-2", children: allWithdrawals.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uf-text-sm", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No withdrawals to track yet" }) }) : allWithdrawals.map((ex) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
14907
14929
  WithdrawExecutionItem,
14908
14930
  {
14909
14931
  execution: ex,
@@ -14913,7 +14935,7 @@ function WithdrawModal({
14913
14935
  }
14914
14936
  },
14915
14937
  ex.id
14916
- )) }),
14938
+ )) }) }),
14917
14939
  withdrawPoweredByFooter
14918
14940
  ] })
14919
14941
  ) : (
@@ -14953,12 +14975,9 @@ function WithdrawModal({
14953
14975
  estimatedProcessingTime: sourceValidation?.estimatedProcessingTime ?? null,
14954
14976
  maxSlippagePercent: sourceValidation?.maxSlippagePercent ?? null,
14955
14977
  priceImpactPercent: sourceValidation?.priceImpactPercent ?? null,
14956
- detectedWallet,
14978
+ senderAddress,
14957
14979
  sourceChainId,
14958
14980
  sourceTokenAddress,
14959
- isWalletMatch,
14960
- connectedWalletName,
14961
- canWithdraw,
14962
14981
  onWithdraw,
14963
14982
  onWithdrawError,
14964
14983
  onDepositWalletCreation: handleDepositWalletCreation,
package/dist/index.mjs CHANGED
@@ -13592,6 +13592,9 @@ import {
13592
13592
  ShieldCheck as ShieldCheck3,
13593
13593
  Wallet as Wallet3
13594
13594
  } from "lucide-react";
13595
+ import {
13596
+ checkHypercoreActivation
13597
+ } from "@unifold/core";
13595
13598
 
13596
13599
  // src/hooks/use-verify-recipient-address.ts
13597
13600
  import { useQuery as useQuery15 } from "@tanstack/react-query";
@@ -13800,6 +13803,7 @@ async function sendHypercoreWithdraw(params) {
13800
13803
  async function detectBrowserWallet(chainType, senderAddress) {
13801
13804
  const win = typeof window !== "undefined" ? window : null;
13802
13805
  if (!win || !senderAddress) return null;
13806
+ if (getUserDisconnectedWallet()) return null;
13803
13807
  const anyWin = win;
13804
13808
  if (chainType === "solana") {
13805
13809
  const solProviders = [];
@@ -13833,28 +13837,44 @@ async function detectBrowserWallet(chainType, senderAddress) {
13833
13837
  evmProviders.push({ provider: p, name });
13834
13838
  }
13835
13839
  };
13836
- add(anyWin.phantom?.ethereum, "Phantom");
13837
- add(anyWin.coinbaseWalletExtension, "Coinbase");
13838
- add(anyWin.trustwallet?.ethereum, "Trust Wallet");
13839
- add(anyWin.okxwallet, "OKX Wallet");
13840
- if (anyWin.__eip6963Providers) {
13841
- for (const detail of anyWin.__eip6963Providers) {
13842
- const rdns = detail.info?.rdns || "";
13843
- let name = detail.info?.name || "Wallet";
13844
- if (rdns.includes("metamask")) name = "MetaMask";
13845
- else if (rdns.includes("rabby")) name = "Rabby";
13846
- else if (rdns.includes("rainbow")) name = "Rainbow";
13847
- add(detail.provider, name);
13848
- }
13840
+ if (!anyWin.__eip6963Providers) {
13841
+ anyWin.__eip6963Providers = [];
13849
13842
  }
13850
- if (win.ethereum) {
13851
- const eth = win.ethereum;
13852
- let name = "Wallet";
13853
- if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
13854
- else if (eth.isRabby) name = "Rabby";
13855
- else if (eth.isRainbow) name = "Rainbow";
13856
- else if (eth.isCoinbaseWallet) name = "Coinbase";
13857
- add(eth, name);
13843
+ const handleAnnouncement = (event) => {
13844
+ const { detail } = event;
13845
+ if (!detail?.info || !detail?.provider) return;
13846
+ const exists = anyWin.__eip6963Providers.some((p) => p.info.uuid === detail.info.uuid);
13847
+ if (!exists) anyWin.__eip6963Providers.push(detail);
13848
+ };
13849
+ win.addEventListener("eip6963:announceProvider", handleAnnouncement);
13850
+ win.dispatchEvent(new Event("eip6963:requestProvider"));
13851
+ win.removeEventListener("eip6963:announceProvider", handleAnnouncement);
13852
+ for (const detail of anyWin.__eip6963Providers) {
13853
+ const rdns = detail.info?.rdns || "";
13854
+ let name = detail.info?.name || "Wallet";
13855
+ if (rdns.includes("metamask")) name = "MetaMask";
13856
+ else if (rdns.includes("phantom")) name = "Phantom";
13857
+ else if (rdns.includes("coinbase")) name = "Coinbase";
13858
+ else if (rdns.includes("rabby")) name = "Rabby";
13859
+ else if (rdns.includes("rainbow")) name = "Rainbow";
13860
+ else if (rdns.includes("okx")) name = "OKX Wallet";
13861
+ else if (rdns.includes("trust")) name = "Trust Wallet";
13862
+ add(detail.provider, name);
13863
+ }
13864
+ if (evmProviders.length === 0) {
13865
+ add(anyWin.phantom?.ethereum, "Phantom");
13866
+ add(anyWin.coinbaseWalletExtension, "Coinbase");
13867
+ add(anyWin.trustwallet?.ethereum, "Trust Wallet");
13868
+ add(anyWin.okxwallet, "OKX Wallet");
13869
+ if (evmProviders.length === 0 && win.ethereum) {
13870
+ const eth = win.ethereum;
13871
+ let name = "Wallet";
13872
+ if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
13873
+ else if (eth.isRabby) name = "Rabby";
13874
+ else if (eth.isRainbow) name = "Rainbow";
13875
+ else if (eth.isCoinbaseWallet) name = "Coinbase";
13876
+ add(eth, name);
13877
+ }
13858
13878
  }
13859
13879
  for (const { provider, name } of evmProviders) {
13860
13880
  try {
@@ -13910,12 +13930,9 @@ function WithdrawForm({
13910
13930
  estimatedProcessingTime,
13911
13931
  maxSlippagePercent,
13912
13932
  priceImpactPercent,
13913
- detectedWallet,
13933
+ senderAddress,
13914
13934
  sourceChainId,
13915
13935
  sourceTokenAddress,
13916
- isWalletMatch,
13917
- connectedWalletName,
13918
- canWithdraw,
13919
13936
  onWithdraw,
13920
13937
  onWithdrawError,
13921
13938
  onDepositWalletCreation,
@@ -14050,12 +14067,43 @@ function WithdrawForm({
14050
14067
  destinationTokenAddress: selectedChain.token_address,
14051
14068
  recipientAddress: trimmedAddress
14052
14069
  });
14053
- const amountBaseUnit = computeBaseUnit(
14070
+ let amountBaseUnit = computeBaseUnit(
14054
14071
  balanceData.balanceBaseUnit,
14055
14072
  parseFloat(amount),
14056
14073
  inputUnit === "crypto" ? balanceCrypto : balanceUsdNum
14057
14074
  );
14058
- const humanAmount = toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
14075
+ let humanAmount = toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
14076
+ if (isHypercoreChain(sourceChainId)) {
14077
+ try {
14078
+ const check = await checkHypercoreActivation(
14079
+ {
14080
+ source_address: senderAddress,
14081
+ recipient_address: depositWallet.address
14082
+ },
14083
+ publishableKey
14084
+ );
14085
+ if (!check.user_exists) {
14086
+ const fee = check.activation_fee;
14087
+ const maxSendable = balanceCrypto - fee;
14088
+ if (maxSendable <= 0) {
14089
+ throw new Error(
14090
+ `Insufficient balance. A ${fee} USDC activation fee is required for the first transfer to this address.`
14091
+ );
14092
+ }
14093
+ const requestedAmount = parseFloat(humanAmount);
14094
+ if (requestedAmount > maxSendable) {
14095
+ humanAmount = toSafeDecimalString(maxSendable, sourceDecimals);
14096
+ amountBaseUnit = computeBaseUnit(
14097
+ balanceData.balanceBaseUnit,
14098
+ maxSendable,
14099
+ balanceCrypto
14100
+ );
14101
+ }
14102
+ }
14103
+ } catch (e) {
14104
+ if (e instanceof Error && e.message.includes("activation fee")) throw e;
14105
+ }
14106
+ }
14059
14107
  const txInfo = {
14060
14108
  sourceChainType,
14061
14109
  sourceChainId,
@@ -14070,43 +14118,67 @@ function WithdrawForm({
14070
14118
  withdrawIntentAddress: depositWallet.address,
14071
14119
  recipientAddress: trimmedAddress
14072
14120
  };
14073
- if (detectedWallet) {
14074
- if (detectedWallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
14075
- await sendHypercoreWithdraw({
14076
- provider: detectedWallet.provider,
14077
- fromAddress: detectedWallet.address,
14078
- depositWalletAddress: depositWallet.address,
14079
- sourceTokenAddress,
14121
+ const wallet = await detectBrowserWallet(sourceChainType, senderAddress);
14122
+ console.log("browser wallet", wallet);
14123
+ if (wallet) {
14124
+ try {
14125
+ if (wallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
14126
+ await sendHypercoreWithdraw({
14127
+ provider: wallet.provider,
14128
+ fromAddress: wallet.address,
14129
+ depositWalletAddress: depositWallet.address,
14130
+ sourceTokenAddress,
14131
+ amount: humanAmount,
14132
+ tokenSymbol,
14133
+ publishableKey
14134
+ });
14135
+ } else if (wallet.chainFamily === "evm") {
14136
+ await sendEvmWithdraw({
14137
+ provider: wallet.provider,
14138
+ fromAddress: wallet.address,
14139
+ depositWalletAddress: depositWallet.address,
14140
+ sourceTokenAddress,
14141
+ sourceChainId,
14142
+ amountBaseUnit
14143
+ });
14144
+ } else if (wallet.chainFamily === "solana") {
14145
+ await sendSolanaWithdraw({
14146
+ provider: wallet.provider,
14147
+ fromAddress: wallet.address,
14148
+ depositWalletAddress: depositWallet.address,
14149
+ sourceTokenAddress,
14150
+ amountBaseUnit,
14151
+ publishableKey
14152
+ });
14153
+ }
14154
+ } catch (walletErr) {
14155
+ console.error("[Unifold] Browser wallet send failed:", walletErr, {
14156
+ wallet: `${wallet.name} (${wallet.chainFamily})`,
14157
+ sourceChainId,
14080
14158
  amount: humanAmount,
14081
- tokenSymbol,
14082
- publishableKey
14159
+ amountBaseUnit,
14160
+ depositWallet: depositWallet.address
14083
14161
  });
14084
- } else if (detectedWallet.chainFamily === "evm") {
14085
- await sendEvmWithdraw({
14086
- provider: detectedWallet.provider,
14087
- fromAddress: detectedWallet.address,
14088
- depositWalletAddress: depositWallet.address,
14089
- sourceTokenAddress,
14162
+ throw walletErr;
14163
+ }
14164
+ } else if (onWithdraw) {
14165
+ try {
14166
+ await onWithdraw(txInfo);
14167
+ } catch (callbackErr) {
14168
+ console.error("[Unifold] onWithdraw callback failed:", callbackErr, {
14090
14169
  sourceChainId,
14091
- amountBaseUnit
14092
- });
14093
- } else if (detectedWallet.chainFamily === "solana") {
14094
- await sendSolanaWithdraw({
14095
- provider: detectedWallet.provider,
14096
- fromAddress: detectedWallet.address,
14097
- depositWalletAddress: depositWallet.address,
14098
- sourceTokenAddress,
14170
+ amount: humanAmount,
14099
14171
  amountBaseUnit,
14100
- publishableKey
14172
+ depositWallet: depositWallet.address
14101
14173
  });
14174
+ throw callbackErr;
14102
14175
  }
14103
- } else if (onWithdraw) {
14104
- await onWithdraw(txInfo);
14105
14176
  } else {
14106
14177
  throw new Error("No withdrawal method available. Please connect a wallet.");
14107
14178
  }
14108
14179
  onWithdrawSubmitted?.(txInfo);
14109
14180
  } catch (err) {
14181
+ console.error("[Unifold] Withdrawal failed:", err);
14110
14182
  const raw = err instanceof Error ? err.message : "Withdrawal failed. Please try again.";
14111
14183
  setSubmitError(raw.length > 120 ? "Withdrawal failed. Please try again." : raw);
14112
14184
  onWithdrawError?.({
@@ -14117,7 +14189,7 @@ function WithdrawForm({
14117
14189
  } finally {
14118
14190
  setIsSubmitting(false);
14119
14191
  }
14120
- }, [selectedToken, selectedChain, isFormValid, cryptoAmountFromInput, sourceDecimals, trimmedAddress, publishableKey, onWithdraw, detectedWallet, sourceTokenAddress, sourceChainId, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, amount, inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
14192
+ }, [selectedToken, selectedChain, isFormValid, cryptoAmountFromInput, sourceDecimals, trimmedAddress, publishableKey, onWithdraw, sourceChainType, senderAddress, sourceTokenAddress, sourceChainId, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, amount, inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
14121
14193
  return /* @__PURE__ */ jsxs47(Fragment11, { children: [
14122
14194
  /* @__PURE__ */ jsxs47("div", { children: [
14123
14195
  /* @__PURE__ */ jsx54(
@@ -14328,23 +14400,12 @@ function WithdrawForm({
14328
14400
  ] })
14329
14401
  ] })
14330
14402
  ] }),
14331
- !canWithdraw && !submitError && /* @__PURE__ */ jsxs47(
14332
- "div",
14333
- {
14334
- className: "uf-flex uf-items-start uf-gap-2.5 uf-p-3 uf-rounded-xl",
14335
- style: { backgroundColor: colors2.card, border: `1px solid ${colors2.border}` },
14336
- children: [
14337
- /* @__PURE__ */ jsx54(Wallet3, { className: "uf-w-4 uf-h-4 uf-flex-shrink-0 uf-mt-0.5", style: { color: colors2.warning } }),
14338
- /* @__PURE__ */ jsx54("div", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No connected wallet detected. Please connect a wallet that matches your account to withdraw." })
14339
- ]
14340
- }
14341
- ),
14342
- isWalletMatch && connectedWalletName ? /* @__PURE__ */ jsx54(
14403
+ /* @__PURE__ */ jsx54(
14343
14404
  "button",
14344
14405
  {
14345
14406
  type: "button",
14346
14407
  onClick: handleWithdraw,
14347
- disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
14408
+ disabled: !isFormValid || isSubmitting || !selectedToken || !selectedChain,
14348
14409
  className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed uf-flex uf-items-center uf-justify-center uf-gap-2",
14349
14410
  style: {
14350
14411
  backgroundColor: colors2.primary,
@@ -14358,29 +14419,9 @@ function WithdrawForm({
14358
14419
  "Processing..."
14359
14420
  ] }) : isOverBalance ? /* @__PURE__ */ jsx54(Fragment11, { children: "Insufficient balance" }) : isBelowMinimum ? /* @__PURE__ */ jsx54(Fragment11, { children: "Minimum amount not met" }) : submitError ? /* @__PURE__ */ jsx54(Fragment11, { children: "Withdrawal failed. Try again" }) : /* @__PURE__ */ jsxs47(Fragment11, { children: [
14360
14421
  /* @__PURE__ */ jsx54(Wallet3, { className: "uf-w-4 uf-h-4" }),
14361
- "Withdraw from ",
14362
- connectedWalletName
14422
+ t8.withdraw
14363
14423
  ] })
14364
14424
  }
14365
- ) : /* @__PURE__ */ jsx54(
14366
- "button",
14367
- {
14368
- type: "button",
14369
- onClick: handleWithdraw,
14370
- disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
14371
- className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
14372
- style: {
14373
- backgroundColor: colors2.primary,
14374
- color: colors2.primaryForeground,
14375
- fontFamily: fonts.medium,
14376
- borderRadius: components.button.borderRadius,
14377
- border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
14378
- },
14379
- children: isSubmitting ? /* @__PURE__ */ jsxs47("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
14380
- /* @__PURE__ */ jsx54(Loader26, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
14381
- "Processing..."
14382
- ] }) : isOverBalance ? "Insufficient balance" : isBelowMinimum ? "Minimum amount not met" : submitError ? "Withdrawal failed. Try again" : t8.withdraw
14383
- }
14384
14425
  ),
14385
14426
  /* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-justify-between uf-text-xs uf-pt-1", children: [
14386
14427
  /* @__PURE__ */ jsx54("div", { children: footerLeft }),
@@ -14779,22 +14820,6 @@ function WithdrawModal({
14779
14820
  });
14780
14821
  const [selectedToken, setSelectedToken] = useState32(null);
14781
14822
  const [selectedChain, setSelectedChain] = useState32(null);
14782
- const [detectedWallet, setDetectedWallet] = useState32(null);
14783
- const connectedWalletName = detectedWallet?.name ?? null;
14784
- const isWalletMatch = !!detectedWallet;
14785
- useEffect27(() => {
14786
- if (!senderAddress || !open) {
14787
- setDetectedWallet(null);
14788
- return;
14789
- }
14790
- let cancelled = false;
14791
- detectBrowserWallet(sourceChainType, senderAddress).then((wallet) => {
14792
- if (!cancelled) setDetectedWallet(wallet);
14793
- });
14794
- return () => {
14795
- cancelled = true;
14796
- };
14797
- }, [senderAddress, sourceChainType, open]);
14798
14823
  const [view, setView] = useState32("form");
14799
14824
  const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState32();
14800
14825
  const [selectedExecution, setSelectedExecution] = useState32(null);
@@ -14887,7 +14912,6 @@ function WithdrawModal({
14887
14912
  if (chain) setSelectedChain(chain);
14888
14913
  }, [selectedToken]);
14889
14914
  const isSourceSupported = sourceValidation?.isSupported ?? null;
14890
- const canWithdraw = !!onWithdraw || isWalletMatch;
14891
14915
  const isAnyLoading = tokensLoading || isCheckingSourceToken;
14892
14916
  const withdrawPoweredByFooter = /* @__PURE__ */ jsx57("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx57(PoweredByUnifold, { color: colors2.foregroundMuted, className: "uf-flex uf-justify-center uf-shrink-0" }) });
14893
14917
  return /* @__PURE__ */ jsx57(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ jsx57(Dialog, { open: hideOverlay || open, onOpenChange: hideOverlay ? void 0 : handleClose, modal: !hideOverlay, children: /* @__PURE__ */ jsx57(
@@ -14918,7 +14942,7 @@ function WithdrawModal({
14918
14942
  /* ---------- Tracker view: execution list ---------- */
14919
14943
  /* @__PURE__ */ jsxs50(Fragment13, { children: [
14920
14944
  /* @__PURE__ */ jsx57(DepositHeader, { title: "Withdrawal History", showBack: true, showClose: !hideOverlay, onBack: () => setView("form"), onClose: handleClose }),
14921
- /* @__PURE__ */ jsx57("div", { className: "uf-flex uf-flex-col uf-gap-2", style: { minHeight: 200 }, children: allWithdrawals.length === 0 ? /* @__PURE__ */ jsx57("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ jsx57("p", { className: "uf-text-sm", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No withdrawals to track yet" }) }) : allWithdrawals.map((ex) => /* @__PURE__ */ jsx57(
14945
+ /* @__PURE__ */ jsx57("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: /* @__PURE__ */ jsx57("div", { className: "uf-flex uf-flex-col uf-gap-2", children: allWithdrawals.length === 0 ? /* @__PURE__ */ jsx57("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ jsx57("p", { className: "uf-text-sm", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No withdrawals to track yet" }) }) : allWithdrawals.map((ex) => /* @__PURE__ */ jsx57(
14922
14946
  WithdrawExecutionItem,
14923
14947
  {
14924
14948
  execution: ex,
@@ -14928,7 +14952,7 @@ function WithdrawModal({
14928
14952
  }
14929
14953
  },
14930
14954
  ex.id
14931
- )) }),
14955
+ )) }) }),
14932
14956
  withdrawPoweredByFooter
14933
14957
  ] })
14934
14958
  ) : (
@@ -14968,12 +14992,9 @@ function WithdrawModal({
14968
14992
  estimatedProcessingTime: sourceValidation?.estimatedProcessingTime ?? null,
14969
14993
  maxSlippagePercent: sourceValidation?.maxSlippagePercent ?? null,
14970
14994
  priceImpactPercent: sourceValidation?.priceImpactPercent ?? null,
14971
- detectedWallet,
14995
+ senderAddress,
14972
14996
  sourceChainId,
14973
14997
  sourceTokenAddress,
14974
- isWalletMatch,
14975
- connectedWalletName,
14976
- canWithdraw,
14977
14998
  onWithdraw,
14978
14999
  onWithdrawError,
14979
15000
  onDepositWalletCreation: handleDepositWalletCreation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifold/ui-react",
3
- "version": "0.1.43",
3
+ "version": "0.1.44",
4
4
  "description": "Unifold UI React - Deposit and onramp components for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -43,7 +43,7 @@
43
43
  "lucide-react": "^0.454.0",
44
44
  "qr-code-styling": "^1.6.0-rc.1",
45
45
  "tailwind-merge": "^2.0.0",
46
- "@unifold/core": "0.1.43"
46
+ "@unifold/core": "0.1.44"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@solana/spl-token": "^0.3.8",