@unifold/ui-web 0.1.45 → 0.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +16 -343
  2. package/dist/index.mjs +16 -343
  3. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -43674,52 +43674,6 @@ async function getDepositQuote(request, publishableKey) {
43674
43674
  const json = await response.json();
43675
43675
  return json.data;
43676
43676
  }
43677
- async function buildHypercoreTransaction(request, publishableKey) {
43678
- const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43679
- validatePublishableKey(pk);
43680
- const response = await fetch(
43681
- `${API_BASE_URL}/v1/public/transactions/hypercore/build`,
43682
- {
43683
- method: "POST",
43684
- headers: {
43685
- accept: "application/json",
43686
- "x-publishable-key": pk,
43687
- "Content-Type": "application/json"
43688
- },
43689
- body: JSON.stringify(request)
43690
- }
43691
- );
43692
- if (!response.ok) {
43693
- const error = await response.json().catch(() => ({ message: response.statusText }));
43694
- throw new Error(
43695
- `Failed to build HyperCore transaction: ${error.message || response.statusText}`
43696
- );
43697
- }
43698
- return response.json();
43699
- }
43700
- async function sendHypercoreTransaction(request, publishableKey) {
43701
- const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43702
- validatePublishableKey(pk);
43703
- const response = await fetch(
43704
- `${API_BASE_URL}/v1/public/transactions/hypercore/send`,
43705
- {
43706
- method: "POST",
43707
- headers: {
43708
- accept: "application/json",
43709
- "x-publishable-key": pk,
43710
- "Content-Type": "application/json"
43711
- },
43712
- body: JSON.stringify(request)
43713
- }
43714
- );
43715
- if (!response.ok) {
43716
- const error = await response.json().catch(() => ({ message: response.statusText }));
43717
- throw new Error(
43718
- `Failed to send HyperCore transaction: ${error.message || response.statusText}`
43719
- );
43720
- }
43721
- return response.json();
43722
- }
43723
43677
  var REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
43724
43678
  var use = React25[" use ".trim().toString()];
43725
43679
  function isPromiseLike(value) {
@@ -57895,10 +57849,11 @@ function BrowserWalletModal({
57895
57849
  const chainType = depositWallet.chain_type;
57896
57850
  const recipientAddress = depositWallet.address;
57897
57851
  const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
57898
- const { executions: depositExecutions, isPolling } = useDepositPolling({
57852
+ const { executions: depositExecutions, isPolling, handleIveDeposited } = useDepositPolling({
57899
57853
  userId,
57900
57854
  publishableKey,
57901
57855
  clientSecret,
57856
+ depositWalletId: depositWallet.id,
57902
57857
  enabled: open && hasSignedTransaction,
57903
57858
  onDepositSuccess,
57904
57859
  onDepositError
@@ -58149,6 +58104,7 @@ function BrowserWalletModal({
58149
58104
  }
58150
58105
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
58151
58106
  setHasSignedTransaction(true);
58107
+ handleIveDeposited();
58152
58108
  setIsConfirming(false);
58153
58109
  setStep("confirming");
58154
58110
  onSuccess?.(txHash);
@@ -60880,249 +60836,10 @@ function useVerifyRecipientAddress(params) {
60880
60836
  refetchOnWindowFocus: false
60881
60837
  });
60882
60838
  }
60883
- async function sendEvmWithdraw(params) {
60884
- const {
60885
- provider,
60886
- fromAddress,
60887
- depositWalletAddress,
60888
- sourceTokenAddress,
60889
- sourceChainId,
60890
- amountBaseUnit
60891
- } = params;
60892
- const currentChainIdHex = await provider.request({
60893
- method: "eth_chainId",
60894
- params: []
60895
- });
60896
- const currentChainId = parseInt(currentChainIdHex, 16).toString();
60897
- if (currentChainId !== sourceChainId) {
60898
- const requiredHex = "0x" + parseInt(sourceChainId).toString(16);
60899
- try {
60900
- await provider.request({
60901
- method: "wallet_switchEthereumChain",
60902
- params: [{ chainId: requiredHex }]
60903
- });
60904
- const newHex = await provider.request({ method: "eth_chainId", params: [] });
60905
- if (parseInt(newHex, 16).toString() !== sourceChainId) {
60906
- throw new Error(`Failed to switch to chain ${sourceChainId}. Please switch manually.`);
60907
- }
60908
- } catch (err) {
60909
- if (err && typeof err === "object" && "code" in err) {
60910
- const e = err;
60911
- if (e.code === 4902) throw new Error(`Chain ${sourceChainId} is not configured in your wallet.`);
60912
- if (e.code === 4001) throw new Error("You must approve the network switch to withdraw.");
60913
- }
60914
- throw err;
60915
- }
60916
- }
60917
- const isNative = sourceTokenAddress === "native" || sourceTokenAddress === "0x0000000000000000000000000000000000000000" || sourceTokenAddress === "";
60918
- const amountBig = BigInt(amountBaseUnit);
60919
- const txParams = isNative ? { from: fromAddress, to: depositWalletAddress, value: "0x" + amountBig.toString(16) } : {
60920
- from: fromAddress,
60921
- to: sourceTokenAddress,
60922
- data: "0xa9059cbb" + depositWalletAddress.slice(2).padStart(64, "0") + amountBig.toString(16).padStart(64, "0")
60923
- };
60924
- let gasEstimate;
60925
- try {
60926
- const hex = await provider.request({ method: "eth_estimateGas", params: [txParams] });
60927
- gasEstimate = BigInt(hex);
60928
- } catch {
60929
- gasEstimate = isNative ? BigInt(21e3) : BigInt(65e3);
60930
- }
60931
- const gasPrice = BigInt(await provider.request({ method: "eth_gasPrice", params: [] }));
60932
- const gasWithBuffer = gasEstimate * BigInt(120) / BigInt(100);
60933
- const gasCost = gasWithBuffer * gasPrice;
60934
- const ethBalance = BigInt(
60935
- await provider.request({ method: "eth_getBalance", params: [fromAddress, "latest"] })
60936
- );
60937
- const totalRequired = isNative ? gasCost + amountBig : gasCost;
60938
- if (ethBalance < totalRequired) {
60939
- const gasFmt = (Number(gasCost) / 1e18).toFixed(6);
60940
- if (isNative) {
60941
- throw new Error(`Insufficient balance. Need ${(Number(totalRequired) / 1e18).toFixed(6)} ETH (amount + ~${gasFmt} gas).`);
60942
- }
60943
- throw new Error(`Insufficient ETH for gas. Need ~${gasFmt} ETH for fees.`);
60944
- }
60945
- const txHash = await provider.request({ method: "eth_sendTransaction", params: [txParams] });
60946
- return txHash;
60947
- }
60948
- async function sendSolanaWithdraw(params) {
60949
- const {
60950
- provider,
60951
- fromAddress,
60952
- depositWalletAddress,
60953
- sourceTokenAddress,
60954
- amountBaseUnit,
60955
- publishableKey
60956
- } = params;
60957
- if (!provider.publicKey) {
60958
- await provider.connect();
60959
- }
60960
- const buildResponse = await buildSolanaTransaction(
60961
- {
60962
- chain_id: "mainnet",
60963
- token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
60964
- source_address: fromAddress,
60965
- destination_address: depositWalletAddress,
60966
- amount: amountBaseUnit
60967
- },
60968
- publishableKey
60969
- );
60970
- const { VersionedTransaction } = await import(
60971
- /* @vite-ignore */
60972
- "@solana/web3.js"
60973
- );
60974
- const binaryString = atob(buildResponse.transaction);
60975
- const bytes = new Uint8Array(binaryString.length);
60976
- for (let i = 0; i < binaryString.length; i++) {
60977
- bytes[i] = binaryString.charCodeAt(i);
60978
- }
60979
- const transaction = VersionedTransaction.deserialize(bytes);
60980
- const signedTransaction = await provider.signTransaction(transaction);
60981
- const serialized = signedTransaction.serialize();
60982
- let binaryStr = "";
60983
- for (let i = 0; i < serialized.length; i++) {
60984
- binaryStr += String.fromCharCode(serialized[i]);
60985
- }
60986
- const sendResponse = await sendSolanaTransaction(
60987
- { chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
60988
- publishableKey
60989
- );
60990
- return sendResponse.signature;
60991
- }
60992
60839
  var HYPERCORE_CHAIN_ID = "1337";
60993
- var HYPERCORE_SPOT_USDC_ADDRESS = "0x6d1e7cde53ba9467b783cb7c530ce054";
60994
60840
  function isHypercoreChain(chainId) {
60995
60841
  return chainId === HYPERCORE_CHAIN_ID;
60996
60842
  }
60997
- async function sendHypercoreWithdraw(params) {
60998
- const {
60999
- provider,
61000
- fromAddress,
61001
- depositWalletAddress,
61002
- sourceTokenAddress,
61003
- amount,
61004
- tokenSymbol,
61005
- publishableKey
61006
- } = params;
61007
- const isSpot = sourceTokenAddress.toLowerCase() === HYPERCORE_SPOT_USDC_ADDRESS;
61008
- const currentChainHex = await provider.request({
61009
- method: "eth_chainId",
61010
- params: []
61011
- });
61012
- const activeChainId = String(parseInt(currentChainHex, 16));
61013
- const buildResult = await buildHypercoreTransaction(
61014
- {
61015
- action_type: isSpot ? "spot_send" : "usd_send",
61016
- signature_chain_type: "ethereum",
61017
- signature_chain_id: activeChainId,
61018
- recipient_address: depositWalletAddress,
61019
- token_address: sourceTokenAddress,
61020
- token_symbol: tokenSymbol || void 0,
61021
- amount
61022
- },
61023
- publishableKey
61024
- );
61025
- const signature = await provider.request({
61026
- method: "eth_signTypedData_v4",
61027
- params: [fromAddress, JSON.stringify(buildResult.typed_data)]
61028
- });
61029
- await sendHypercoreTransaction(
61030
- {
61031
- action_payload: buildResult.action_payload,
61032
- signature,
61033
- nonce: buildResult.nonce
61034
- },
61035
- publishableKey
61036
- );
61037
- }
61038
- async function detectBrowserWallet(chainType, senderAddress) {
61039
- const win = typeof window !== "undefined" ? window : null;
61040
- if (!win || !senderAddress) return null;
61041
- if (getUserDisconnectedWallet()) return null;
61042
- const anyWin = win;
61043
- if (chainType === "solana") {
61044
- const solProviders = [];
61045
- if (win.phantom?.solana) solProviders.push({ provider: win.phantom.solana, name: "Phantom" });
61046
- if (anyWin.solflare) solProviders.push({ provider: anyWin.solflare, name: "Solflare" });
61047
- if (anyWin.backpack) solProviders.push({ provider: anyWin.backpack, name: "Backpack" });
61048
- if (anyWin.trustwallet?.solana) solProviders.push({ provider: anyWin.trustwallet.solana, name: "Trust Wallet" });
61049
- for (const { provider, name } of solProviders) {
61050
- if (!provider) continue;
61051
- try {
61052
- let addr;
61053
- if (provider.isConnected && provider.publicKey) {
61054
- addr = provider.publicKey.toString();
61055
- } else {
61056
- const resp = await provider.connect({ onlyIfTrusted: true });
61057
- if (resp?.publicKey) addr = resp.publicKey.toString();
61058
- }
61059
- if (addr && addr === senderAddress) {
61060
- return { chainFamily: "solana", provider, name, address: addr };
61061
- }
61062
- } catch {
61063
- }
61064
- }
61065
- }
61066
- if (chainType === "ethereum") {
61067
- const evmProviders = [];
61068
- const seen = /* @__PURE__ */ new Set();
61069
- const add = (p, name) => {
61070
- if (p && typeof p.request === "function" && !seen.has(p)) {
61071
- seen.add(p);
61072
- evmProviders.push({ provider: p, name });
61073
- }
61074
- };
61075
- if (!anyWin.__eip6963Providers) {
61076
- anyWin.__eip6963Providers = [];
61077
- }
61078
- const handleAnnouncement = (event) => {
61079
- const { detail } = event;
61080
- if (!detail?.info || !detail?.provider) return;
61081
- const exists = anyWin.__eip6963Providers.some((p) => p.info.uuid === detail.info.uuid);
61082
- if (!exists) anyWin.__eip6963Providers.push(detail);
61083
- };
61084
- win.addEventListener("eip6963:announceProvider", handleAnnouncement);
61085
- win.dispatchEvent(new Event("eip6963:requestProvider"));
61086
- win.removeEventListener("eip6963:announceProvider", handleAnnouncement);
61087
- for (const detail of anyWin.__eip6963Providers) {
61088
- const rdns = detail.info?.rdns || "";
61089
- let name = detail.info?.name || "Wallet";
61090
- if (rdns.includes("metamask")) name = "MetaMask";
61091
- else if (rdns.includes("phantom")) name = "Phantom";
61092
- else if (rdns.includes("coinbase")) name = "Coinbase";
61093
- else if (rdns.includes("rabby")) name = "Rabby";
61094
- else if (rdns.includes("rainbow")) name = "Rainbow";
61095
- else if (rdns.includes("okx")) name = "OKX Wallet";
61096
- else if (rdns.includes("trust")) name = "Trust Wallet";
61097
- add(detail.provider, name);
61098
- }
61099
- if (evmProviders.length === 0) {
61100
- add(anyWin.phantom?.ethereum, "Phantom");
61101
- add(anyWin.coinbaseWalletExtension, "Coinbase");
61102
- add(anyWin.trustwallet?.ethereum, "Trust Wallet");
61103
- add(anyWin.okxwallet, "OKX Wallet");
61104
- if (evmProviders.length === 0 && win.ethereum) {
61105
- const eth = win.ethereum;
61106
- let name = "Wallet";
61107
- if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
61108
- else if (eth.isRabby) name = "Rabby";
61109
- else if (eth.isRainbow) name = "Rainbow";
61110
- else if (eth.isCoinbaseWallet) name = "Coinbase";
61111
- add(eth, name);
61112
- }
61113
- }
61114
- for (const { provider, name } of evmProviders) {
61115
- try {
61116
- const accounts = await provider.request({ method: "eth_accounts" });
61117
- if (accounts?.length > 0 && accounts[0].toLowerCase() === senderAddress.toLowerCase()) {
61118
- return { chainFamily: "evm", provider, name, address: accounts[0] };
61119
- }
61120
- } catch {
61121
- }
61122
- }
61123
- }
61124
- return null;
61125
- }
61126
60843
  var t8 = i18n2.withdrawModal;
61127
60844
  var tCrypto = i18n2.transferCrypto;
61128
60845
  function formatProcessingTime2(seconds) {
@@ -61293,6 +61010,9 @@ function WithdrawForm({
61293
61010
  setIsSubmitting(true);
61294
61011
  setSubmitError(null);
61295
61012
  try {
61013
+ if (!onWithdraw) {
61014
+ throw new Error("No withdrawal method available. Please provide an onWithdraw handler.");
61015
+ }
61296
61016
  const depositWallet = await onDepositWalletCreation({
61297
61017
  destinationChainType: selectedChain.chain_type,
61298
61018
  destinationChainId: selectedChain.chain_id,
@@ -61350,63 +61070,16 @@ function WithdrawForm({
61350
61070
  withdrawIntentAddress: depositWallet.address,
61351
61071
  recipientAddress: trimmedAddress
61352
61072
  };
61353
- const wallet = await detectBrowserWallet(sourceChainType, senderAddress);
61354
- console.log("browser wallet", wallet);
61355
- if (wallet) {
61356
- try {
61357
- if (wallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
61358
- await sendHypercoreWithdraw({
61359
- provider: wallet.provider,
61360
- fromAddress: wallet.address,
61361
- depositWalletAddress: depositWallet.address,
61362
- sourceTokenAddress,
61363
- amount: humanAmount,
61364
- tokenSymbol,
61365
- publishableKey
61366
- });
61367
- } else if (wallet.chainFamily === "evm") {
61368
- await sendEvmWithdraw({
61369
- provider: wallet.provider,
61370
- fromAddress: wallet.address,
61371
- depositWalletAddress: depositWallet.address,
61372
- sourceTokenAddress,
61373
- sourceChainId,
61374
- amountBaseUnit
61375
- });
61376
- } else if (wallet.chainFamily === "solana") {
61377
- await sendSolanaWithdraw({
61378
- provider: wallet.provider,
61379
- fromAddress: wallet.address,
61380
- depositWalletAddress: depositWallet.address,
61381
- sourceTokenAddress,
61382
- amountBaseUnit,
61383
- publishableKey
61384
- });
61385
- }
61386
- } catch (walletErr) {
61387
- console.error("[Unifold] Browser wallet send failed:", walletErr, {
61388
- wallet: `${wallet.name} (${wallet.chainFamily})`,
61389
- sourceChainId,
61390
- amount: humanAmount,
61391
- amountBaseUnit,
61392
- depositWallet: depositWallet.address
61393
- });
61394
- throw walletErr;
61395
- }
61396
- } else if (onWithdraw) {
61397
- try {
61398
- await onWithdraw(txInfo);
61399
- } catch (callbackErr) {
61400
- console.error("[Unifold] onWithdraw callback failed:", callbackErr, {
61401
- sourceChainId,
61402
- amount: humanAmount,
61403
- amountBaseUnit,
61404
- depositWallet: depositWallet.address
61405
- });
61406
- throw callbackErr;
61407
- }
61408
- } else {
61409
- throw new Error("No withdrawal method available. Please connect a wallet.");
61073
+ try {
61074
+ await onWithdraw(txInfo);
61075
+ } catch (callbackErr) {
61076
+ console.error("[Unifold] onWithdraw callback failed:", callbackErr, {
61077
+ sourceChainId,
61078
+ amount: humanAmount,
61079
+ amountBaseUnit,
61080
+ depositWallet: depositWallet.address
61081
+ });
61082
+ throw callbackErr;
61410
61083
  }
61411
61084
  onWithdrawSubmitted?.(txInfo);
61412
61085
  } catch (err) {
package/dist/index.mjs CHANGED
@@ -43661,52 +43661,6 @@ async function getDepositQuote(request, publishableKey) {
43661
43661
  const json = await response.json();
43662
43662
  return json.data;
43663
43663
  }
43664
- async function buildHypercoreTransaction(request, publishableKey) {
43665
- const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43666
- validatePublishableKey(pk);
43667
- const response = await fetch(
43668
- `${API_BASE_URL}/v1/public/transactions/hypercore/build`,
43669
- {
43670
- method: "POST",
43671
- headers: {
43672
- accept: "application/json",
43673
- "x-publishable-key": pk,
43674
- "Content-Type": "application/json"
43675
- },
43676
- body: JSON.stringify(request)
43677
- }
43678
- );
43679
- if (!response.ok) {
43680
- const error = await response.json().catch(() => ({ message: response.statusText }));
43681
- throw new Error(
43682
- `Failed to build HyperCore transaction: ${error.message || response.statusText}`
43683
- );
43684
- }
43685
- return response.json();
43686
- }
43687
- async function sendHypercoreTransaction(request, publishableKey) {
43688
- const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
43689
- validatePublishableKey(pk);
43690
- const response = await fetch(
43691
- `${API_BASE_URL}/v1/public/transactions/hypercore/send`,
43692
- {
43693
- method: "POST",
43694
- headers: {
43695
- accept: "application/json",
43696
- "x-publishable-key": pk,
43697
- "Content-Type": "application/json"
43698
- },
43699
- body: JSON.stringify(request)
43700
- }
43701
- );
43702
- if (!response.ok) {
43703
- const error = await response.json().catch(() => ({ message: response.statusText }));
43704
- throw new Error(
43705
- `Failed to send HyperCore transaction: ${error.message || response.statusText}`
43706
- );
43707
- }
43708
- return response.json();
43709
- }
43710
43664
  var REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
43711
43665
  var use = React25[" use ".trim().toString()];
43712
43666
  function isPromiseLike(value) {
@@ -57882,10 +57836,11 @@ function BrowserWalletModal({
57882
57836
  const chainType = depositWallet.chain_type;
57883
57837
  const recipientAddress = depositWallet.address;
57884
57838
  const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
57885
- const { executions: depositExecutions, isPolling } = useDepositPolling({
57839
+ const { executions: depositExecutions, isPolling, handleIveDeposited } = useDepositPolling({
57886
57840
  userId,
57887
57841
  publishableKey,
57888
57842
  clientSecret,
57843
+ depositWalletId: depositWallet.id,
57889
57844
  enabled: open && hasSignedTransaction,
57890
57845
  onDepositSuccess,
57891
57846
  onDepositError
@@ -58136,6 +58091,7 @@ function BrowserWalletModal({
58136
58091
  }
58137
58092
  setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
58138
58093
  setHasSignedTransaction(true);
58094
+ handleIveDeposited();
58139
58095
  setIsConfirming(false);
58140
58096
  setStep("confirming");
58141
58097
  onSuccess?.(txHash);
@@ -60867,249 +60823,10 @@ function useVerifyRecipientAddress(params) {
60867
60823
  refetchOnWindowFocus: false
60868
60824
  });
60869
60825
  }
60870
- async function sendEvmWithdraw(params) {
60871
- const {
60872
- provider,
60873
- fromAddress,
60874
- depositWalletAddress,
60875
- sourceTokenAddress,
60876
- sourceChainId,
60877
- amountBaseUnit
60878
- } = params;
60879
- const currentChainIdHex = await provider.request({
60880
- method: "eth_chainId",
60881
- params: []
60882
- });
60883
- const currentChainId = parseInt(currentChainIdHex, 16).toString();
60884
- if (currentChainId !== sourceChainId) {
60885
- const requiredHex = "0x" + parseInt(sourceChainId).toString(16);
60886
- try {
60887
- await provider.request({
60888
- method: "wallet_switchEthereumChain",
60889
- params: [{ chainId: requiredHex }]
60890
- });
60891
- const newHex = await provider.request({ method: "eth_chainId", params: [] });
60892
- if (parseInt(newHex, 16).toString() !== sourceChainId) {
60893
- throw new Error(`Failed to switch to chain ${sourceChainId}. Please switch manually.`);
60894
- }
60895
- } catch (err) {
60896
- if (err && typeof err === "object" && "code" in err) {
60897
- const e = err;
60898
- if (e.code === 4902) throw new Error(`Chain ${sourceChainId} is not configured in your wallet.`);
60899
- if (e.code === 4001) throw new Error("You must approve the network switch to withdraw.");
60900
- }
60901
- throw err;
60902
- }
60903
- }
60904
- const isNative = sourceTokenAddress === "native" || sourceTokenAddress === "0x0000000000000000000000000000000000000000" || sourceTokenAddress === "";
60905
- const amountBig = BigInt(amountBaseUnit);
60906
- const txParams = isNative ? { from: fromAddress, to: depositWalletAddress, value: "0x" + amountBig.toString(16) } : {
60907
- from: fromAddress,
60908
- to: sourceTokenAddress,
60909
- data: "0xa9059cbb" + depositWalletAddress.slice(2).padStart(64, "0") + amountBig.toString(16).padStart(64, "0")
60910
- };
60911
- let gasEstimate;
60912
- try {
60913
- const hex = await provider.request({ method: "eth_estimateGas", params: [txParams] });
60914
- gasEstimate = BigInt(hex);
60915
- } catch {
60916
- gasEstimate = isNative ? BigInt(21e3) : BigInt(65e3);
60917
- }
60918
- const gasPrice = BigInt(await provider.request({ method: "eth_gasPrice", params: [] }));
60919
- const gasWithBuffer = gasEstimate * BigInt(120) / BigInt(100);
60920
- const gasCost = gasWithBuffer * gasPrice;
60921
- const ethBalance = BigInt(
60922
- await provider.request({ method: "eth_getBalance", params: [fromAddress, "latest"] })
60923
- );
60924
- const totalRequired = isNative ? gasCost + amountBig : gasCost;
60925
- if (ethBalance < totalRequired) {
60926
- const gasFmt = (Number(gasCost) / 1e18).toFixed(6);
60927
- if (isNative) {
60928
- throw new Error(`Insufficient balance. Need ${(Number(totalRequired) / 1e18).toFixed(6)} ETH (amount + ~${gasFmt} gas).`);
60929
- }
60930
- throw new Error(`Insufficient ETH for gas. Need ~${gasFmt} ETH for fees.`);
60931
- }
60932
- const txHash = await provider.request({ method: "eth_sendTransaction", params: [txParams] });
60933
- return txHash;
60934
- }
60935
- async function sendSolanaWithdraw(params) {
60936
- const {
60937
- provider,
60938
- fromAddress,
60939
- depositWalletAddress,
60940
- sourceTokenAddress,
60941
- amountBaseUnit,
60942
- publishableKey
60943
- } = params;
60944
- if (!provider.publicKey) {
60945
- await provider.connect();
60946
- }
60947
- const buildResponse = await buildSolanaTransaction(
60948
- {
60949
- chain_id: "mainnet",
60950
- token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
60951
- source_address: fromAddress,
60952
- destination_address: depositWalletAddress,
60953
- amount: amountBaseUnit
60954
- },
60955
- publishableKey
60956
- );
60957
- const { VersionedTransaction } = await import(
60958
- /* @vite-ignore */
60959
- "@solana/web3.js"
60960
- );
60961
- const binaryString = atob(buildResponse.transaction);
60962
- const bytes = new Uint8Array(binaryString.length);
60963
- for (let i = 0; i < binaryString.length; i++) {
60964
- bytes[i] = binaryString.charCodeAt(i);
60965
- }
60966
- const transaction = VersionedTransaction.deserialize(bytes);
60967
- const signedTransaction = await provider.signTransaction(transaction);
60968
- const serialized = signedTransaction.serialize();
60969
- let binaryStr = "";
60970
- for (let i = 0; i < serialized.length; i++) {
60971
- binaryStr += String.fromCharCode(serialized[i]);
60972
- }
60973
- const sendResponse = await sendSolanaTransaction(
60974
- { chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
60975
- publishableKey
60976
- );
60977
- return sendResponse.signature;
60978
- }
60979
60826
  var HYPERCORE_CHAIN_ID = "1337";
60980
- var HYPERCORE_SPOT_USDC_ADDRESS = "0x6d1e7cde53ba9467b783cb7c530ce054";
60981
60827
  function isHypercoreChain(chainId) {
60982
60828
  return chainId === HYPERCORE_CHAIN_ID;
60983
60829
  }
60984
- async function sendHypercoreWithdraw(params) {
60985
- const {
60986
- provider,
60987
- fromAddress,
60988
- depositWalletAddress,
60989
- sourceTokenAddress,
60990
- amount,
60991
- tokenSymbol,
60992
- publishableKey
60993
- } = params;
60994
- const isSpot = sourceTokenAddress.toLowerCase() === HYPERCORE_SPOT_USDC_ADDRESS;
60995
- const currentChainHex = await provider.request({
60996
- method: "eth_chainId",
60997
- params: []
60998
- });
60999
- const activeChainId = String(parseInt(currentChainHex, 16));
61000
- const buildResult = await buildHypercoreTransaction(
61001
- {
61002
- action_type: isSpot ? "spot_send" : "usd_send",
61003
- signature_chain_type: "ethereum",
61004
- signature_chain_id: activeChainId,
61005
- recipient_address: depositWalletAddress,
61006
- token_address: sourceTokenAddress,
61007
- token_symbol: tokenSymbol || void 0,
61008
- amount
61009
- },
61010
- publishableKey
61011
- );
61012
- const signature = await provider.request({
61013
- method: "eth_signTypedData_v4",
61014
- params: [fromAddress, JSON.stringify(buildResult.typed_data)]
61015
- });
61016
- await sendHypercoreTransaction(
61017
- {
61018
- action_payload: buildResult.action_payload,
61019
- signature,
61020
- nonce: buildResult.nonce
61021
- },
61022
- publishableKey
61023
- );
61024
- }
61025
- async function detectBrowserWallet(chainType, senderAddress) {
61026
- const win = typeof window !== "undefined" ? window : null;
61027
- if (!win || !senderAddress) return null;
61028
- if (getUserDisconnectedWallet()) return null;
61029
- const anyWin = win;
61030
- if (chainType === "solana") {
61031
- const solProviders = [];
61032
- if (win.phantom?.solana) solProviders.push({ provider: win.phantom.solana, name: "Phantom" });
61033
- if (anyWin.solflare) solProviders.push({ provider: anyWin.solflare, name: "Solflare" });
61034
- if (anyWin.backpack) solProviders.push({ provider: anyWin.backpack, name: "Backpack" });
61035
- if (anyWin.trustwallet?.solana) solProviders.push({ provider: anyWin.trustwallet.solana, name: "Trust Wallet" });
61036
- for (const { provider, name } of solProviders) {
61037
- if (!provider) continue;
61038
- try {
61039
- let addr;
61040
- if (provider.isConnected && provider.publicKey) {
61041
- addr = provider.publicKey.toString();
61042
- } else {
61043
- const resp = await provider.connect({ onlyIfTrusted: true });
61044
- if (resp?.publicKey) addr = resp.publicKey.toString();
61045
- }
61046
- if (addr && addr === senderAddress) {
61047
- return { chainFamily: "solana", provider, name, address: addr };
61048
- }
61049
- } catch {
61050
- }
61051
- }
61052
- }
61053
- if (chainType === "ethereum") {
61054
- const evmProviders = [];
61055
- const seen = /* @__PURE__ */ new Set();
61056
- const add = (p, name) => {
61057
- if (p && typeof p.request === "function" && !seen.has(p)) {
61058
- seen.add(p);
61059
- evmProviders.push({ provider: p, name });
61060
- }
61061
- };
61062
- if (!anyWin.__eip6963Providers) {
61063
- anyWin.__eip6963Providers = [];
61064
- }
61065
- const handleAnnouncement = (event) => {
61066
- const { detail } = event;
61067
- if (!detail?.info || !detail?.provider) return;
61068
- const exists = anyWin.__eip6963Providers.some((p) => p.info.uuid === detail.info.uuid);
61069
- if (!exists) anyWin.__eip6963Providers.push(detail);
61070
- };
61071
- win.addEventListener("eip6963:announceProvider", handleAnnouncement);
61072
- win.dispatchEvent(new Event("eip6963:requestProvider"));
61073
- win.removeEventListener("eip6963:announceProvider", handleAnnouncement);
61074
- for (const detail of anyWin.__eip6963Providers) {
61075
- const rdns = detail.info?.rdns || "";
61076
- let name = detail.info?.name || "Wallet";
61077
- if (rdns.includes("metamask")) name = "MetaMask";
61078
- else if (rdns.includes("phantom")) name = "Phantom";
61079
- else if (rdns.includes("coinbase")) name = "Coinbase";
61080
- else if (rdns.includes("rabby")) name = "Rabby";
61081
- else if (rdns.includes("rainbow")) name = "Rainbow";
61082
- else if (rdns.includes("okx")) name = "OKX Wallet";
61083
- else if (rdns.includes("trust")) name = "Trust Wallet";
61084
- add(detail.provider, name);
61085
- }
61086
- if (evmProviders.length === 0) {
61087
- add(anyWin.phantom?.ethereum, "Phantom");
61088
- add(anyWin.coinbaseWalletExtension, "Coinbase");
61089
- add(anyWin.trustwallet?.ethereum, "Trust Wallet");
61090
- add(anyWin.okxwallet, "OKX Wallet");
61091
- if (evmProviders.length === 0 && win.ethereum) {
61092
- const eth = win.ethereum;
61093
- let name = "Wallet";
61094
- if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
61095
- else if (eth.isRabby) name = "Rabby";
61096
- else if (eth.isRainbow) name = "Rainbow";
61097
- else if (eth.isCoinbaseWallet) name = "Coinbase";
61098
- add(eth, name);
61099
- }
61100
- }
61101
- for (const { provider, name } of evmProviders) {
61102
- try {
61103
- const accounts = await provider.request({ method: "eth_accounts" });
61104
- if (accounts?.length > 0 && accounts[0].toLowerCase() === senderAddress.toLowerCase()) {
61105
- return { chainFamily: "evm", provider, name, address: accounts[0] };
61106
- }
61107
- } catch {
61108
- }
61109
- }
61110
- }
61111
- return null;
61112
- }
61113
60830
  var t8 = i18n2.withdrawModal;
61114
60831
  var tCrypto = i18n2.transferCrypto;
61115
60832
  function formatProcessingTime2(seconds) {
@@ -61280,6 +60997,9 @@ function WithdrawForm({
61280
60997
  setIsSubmitting(true);
61281
60998
  setSubmitError(null);
61282
60999
  try {
61000
+ if (!onWithdraw) {
61001
+ throw new Error("No withdrawal method available. Please provide an onWithdraw handler.");
61002
+ }
61283
61003
  const depositWallet = await onDepositWalletCreation({
61284
61004
  destinationChainType: selectedChain.chain_type,
61285
61005
  destinationChainId: selectedChain.chain_id,
@@ -61337,63 +61057,16 @@ function WithdrawForm({
61337
61057
  withdrawIntentAddress: depositWallet.address,
61338
61058
  recipientAddress: trimmedAddress
61339
61059
  };
61340
- const wallet = await detectBrowserWallet(sourceChainType, senderAddress);
61341
- console.log("browser wallet", wallet);
61342
- if (wallet) {
61343
- try {
61344
- if (wallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
61345
- await sendHypercoreWithdraw({
61346
- provider: wallet.provider,
61347
- fromAddress: wallet.address,
61348
- depositWalletAddress: depositWallet.address,
61349
- sourceTokenAddress,
61350
- amount: humanAmount,
61351
- tokenSymbol,
61352
- publishableKey
61353
- });
61354
- } else if (wallet.chainFamily === "evm") {
61355
- await sendEvmWithdraw({
61356
- provider: wallet.provider,
61357
- fromAddress: wallet.address,
61358
- depositWalletAddress: depositWallet.address,
61359
- sourceTokenAddress,
61360
- sourceChainId,
61361
- amountBaseUnit
61362
- });
61363
- } else if (wallet.chainFamily === "solana") {
61364
- await sendSolanaWithdraw({
61365
- provider: wallet.provider,
61366
- fromAddress: wallet.address,
61367
- depositWalletAddress: depositWallet.address,
61368
- sourceTokenAddress,
61369
- amountBaseUnit,
61370
- publishableKey
61371
- });
61372
- }
61373
- } catch (walletErr) {
61374
- console.error("[Unifold] Browser wallet send failed:", walletErr, {
61375
- wallet: `${wallet.name} (${wallet.chainFamily})`,
61376
- sourceChainId,
61377
- amount: humanAmount,
61378
- amountBaseUnit,
61379
- depositWallet: depositWallet.address
61380
- });
61381
- throw walletErr;
61382
- }
61383
- } else if (onWithdraw) {
61384
- try {
61385
- await onWithdraw(txInfo);
61386
- } catch (callbackErr) {
61387
- console.error("[Unifold] onWithdraw callback failed:", callbackErr, {
61388
- sourceChainId,
61389
- amount: humanAmount,
61390
- amountBaseUnit,
61391
- depositWallet: depositWallet.address
61392
- });
61393
- throw callbackErr;
61394
- }
61395
- } else {
61396
- throw new Error("No withdrawal method available. Please connect a wallet.");
61060
+ try {
61061
+ await onWithdraw(txInfo);
61062
+ } catch (callbackErr) {
61063
+ console.error("[Unifold] onWithdraw callback failed:", callbackErr, {
61064
+ sourceChainId,
61065
+ amount: humanAmount,
61066
+ amountBaseUnit,
61067
+ depositWallet: depositWallet.address
61068
+ });
61069
+ throw callbackErr;
61397
61070
  }
61398
61071
  onWithdrawSubmitted?.(txInfo);
61399
61072
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifold/ui-web",
3
- "version": "0.1.45",
3
+ "version": "0.1.46",
4
4
  "description": "Unifold UI Web - Framework-agnostic deposit widget",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -27,10 +27,10 @@
27
27
  "@types/react-dom": "^19.0.0",
28
28
  "tsup": "^8.0.0",
29
29
  "typescript": "^5.0.0",
30
- "@unifold/connect-react": "0.1.45",
31
- "@unifold/core": "0.1.45",
32
- "@unifold/react-provider": "0.1.45",
33
- "@unifold/ui-react": "0.1.45"
30
+ "@unifold/connect-react": "0.1.46",
31
+ "@unifold/react-provider": "0.1.46",
32
+ "@unifold/core": "0.1.46",
33
+ "@unifold/ui-react": "0.1.46"
34
34
  },
35
35
  "keywords": [
36
36
  "unifold",