@unifold/connect-react 0.1.26 → 0.1.27

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.js CHANGED
@@ -6400,6 +6400,11 @@ async function getIpAddress() {
6400
6400
  }
6401
6401
  return response.json();
6402
6402
  }
6403
+ var IneligibilityReason = /* @__PURE__ */ ((IneligibilityReason2) => {
6404
+ IneligibilityReason2["MINIMUM_NOT_MET"] = "minimum_not_met";
6405
+ IneligibilityReason2["NOT_SUPPORTED_DEPOSIT_FROM"] = "not_supported_deposit_from";
6406
+ return IneligibilityReason2;
6407
+ })(IneligibilityReason || {});
6403
6408
  async function getAddressBalances(address, chainType, publishableKey) {
6404
6409
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
6405
6410
  validatePublishableKey(pk);
@@ -10811,6 +10816,26 @@ function cn(...inputs) {
10811
10816
  return twMerge(clsx(inputs));
10812
10817
  }
10813
10818
  var WALLET_CHAIN_TYPE_STORAGE_KEY = "unifold_last_wallet_type";
10819
+ var WALLET_USER_DISCONNECTED_KEY = "unifold_wallet_user_disconnected";
10820
+ function getUserDisconnectedWallet() {
10821
+ if (typeof window === "undefined") return false;
10822
+ try {
10823
+ return localStorage.getItem(WALLET_USER_DISCONNECTED_KEY) === "true";
10824
+ } catch {
10825
+ return false;
10826
+ }
10827
+ }
10828
+ function setUserDisconnectedWallet(disconnected) {
10829
+ if (typeof window === "undefined") return;
10830
+ try {
10831
+ if (disconnected) {
10832
+ localStorage.setItem(WALLET_USER_DISCONNECTED_KEY, "true");
10833
+ } else {
10834
+ localStorage.removeItem(WALLET_USER_DISCONNECTED_KEY);
10835
+ }
10836
+ } catch {
10837
+ }
10838
+ }
10814
10839
  function getStoredWalletChainType() {
10815
10840
  if (typeof window === "undefined") return void 0;
10816
10841
  try {
@@ -11346,8 +11371,119 @@ function useDepositAddress(params) {
11346
11371
  // 1s, 2s, 4s (max 10s)
11347
11372
  });
11348
11373
  }
11374
+ function getIconUrl2(iconUrl, assetCdnUrl) {
11375
+ if (!iconUrl) return void 0;
11376
+ if (iconUrl.startsWith("http://") || iconUrl.startsWith("https://")) {
11377
+ return iconUrl;
11378
+ }
11379
+ if (assetCdnUrl) {
11380
+ return `${assetCdnUrl}${iconUrl.startsWith("/") ? "" : "/"}${iconUrl}`;
11381
+ }
11382
+ return iconUrl;
11383
+ }
11384
+ function getTokenFromBalance(balance) {
11385
+ if (balance.token) {
11386
+ return balance.token;
11387
+ }
11388
+ const legacyBalance = balance;
11389
+ if (legacyBalance.symbol && legacyBalance.decimals !== void 0) {
11390
+ return {
11391
+ symbol: legacyBalance.symbol,
11392
+ name: legacyBalance.name,
11393
+ icon_url: legacyBalance.icon_url,
11394
+ icon_urls: [],
11395
+ token_address: legacyBalance.token_address,
11396
+ chain_id: legacyBalance.chain_id,
11397
+ chain_name: legacyBalance.chain_name,
11398
+ chain_type: legacyBalance.chain_type,
11399
+ decimals: legacyBalance.decimals,
11400
+ chain_icon_url: legacyBalance.chain_icon_url,
11401
+ chain_icon_urls: [],
11402
+ minimum_deposit_amount_usd: 0
11403
+ };
11404
+ }
11405
+ return null;
11406
+ }
11407
+ function isBalanceEligible(balance) {
11408
+ if (balance.is_eligible !== void 0) {
11409
+ return balance.is_eligible;
11410
+ }
11411
+ const legacyBalance = balance;
11412
+ if (legacyBalance.is_eligible !== void 0) {
11413
+ return legacyBalance.is_eligible;
11414
+ }
11415
+ return true;
11416
+ }
11417
+ function getIneligibilityMessage(balance) {
11418
+ if (isBalanceEligible(balance)) {
11419
+ return null;
11420
+ }
11421
+ switch (balance.ineligibility_reason) {
11422
+ case IneligibilityReason.MINIMUM_NOT_MET:
11423
+ return "Low balance";
11424
+ case IneligibilityReason.NOT_SUPPORTED_DEPOSIT_FROM:
11425
+ return "Not supported";
11426
+ default:
11427
+ return "Not eligible";
11428
+ }
11429
+ }
11430
+ function formatTokenAmount(amount, decimals, symbol) {
11431
+ const value = Number(amount) / 10 ** decimals;
11432
+ const upperSymbol = symbol.toUpperCase();
11433
+ let maxDecimals = 4;
11434
+ if (upperSymbol === "BTC" || upperSymbol === "WBTC") {
11435
+ maxDecimals = 8;
11436
+ } else if (upperSymbol === "ETH" || upperSymbol === "WETH" || upperSymbol === "SOL") {
11437
+ maxDecimals = 6;
11438
+ }
11439
+ if (value >= 1) {
11440
+ return value.toLocaleString(void 0, {
11441
+ minimumFractionDigits: 2,
11442
+ maximumFractionDigits: maxDecimals
11443
+ });
11444
+ } else if (value > 0) {
11445
+ return value.toLocaleString(void 0, {
11446
+ minimumFractionDigits: 2,
11447
+ maximumFractionDigits: maxDecimals,
11448
+ minimumSignificantDigits: 2,
11449
+ maximumSignificantDigits: 6
11450
+ });
11451
+ }
11452
+ return "0.00";
11453
+ }
11454
+ function formatUsdAmount(amountUsd) {
11455
+ if (!amountUsd) return null;
11456
+ const value = parseFloat(amountUsd);
11457
+ if (value <= 0) return null;
11458
+ return value.toLocaleString(void 0, {
11459
+ minimumFractionDigits: 2,
11460
+ maximumFractionDigits: 2
11461
+ });
11462
+ }
11463
+ function truncateAddress2(address) {
11464
+ if (address.length <= 13) return address;
11465
+ return `${address.slice(0, 6)}...${address.slice(-4)}`;
11466
+ }
11467
+ function formatBalanceDisplay(balance, projectName) {
11468
+ return projectName ? `${projectName} Balance: ${balance}` : `Balance: ${balance}`;
11469
+ }
11470
+ function formatProcessingTime(seconds) {
11471
+ if (seconds === null || seconds === 0) {
11472
+ return "< 1 min";
11473
+ }
11474
+ const minutes = Math.floor(seconds / 60);
11475
+ const remainingSeconds = seconds % 60;
11476
+ if (minutes === 0) {
11477
+ return `< ${remainingSeconds} sec`;
11478
+ } else if (remainingSeconds === 0) {
11479
+ return `< ${minutes} min`;
11480
+ } else {
11481
+ return `< ${minutes} min ${remainingSeconds} sec`;
11482
+ }
11483
+ }
11349
11484
  function DepositHeader({
11350
11485
  title,
11486
+ subtitle,
11351
11487
  showBack = false,
11352
11488
  showClose = true,
11353
11489
  onBack,
@@ -11358,19 +11494,41 @@ function DepositHeader({
11358
11494
  balanceChainType,
11359
11495
  balanceChainId,
11360
11496
  balanceTokenAddress,
11497
+ projectName,
11361
11498
  publishableKey
11362
11499
  }) {
11363
11500
  const { colors: colors2, fonts, components } = useTheme();
11364
11501
  const [balance, setBalance] = (0, import_react11.useState)(null);
11365
11502
  const [isLoadingBalance, setIsLoadingBalance] = (0, import_react11.useState)(false);
11503
+ const [showBalanceSkeleton, setShowBalanceSkeleton] = (0, import_react11.useState)(false);
11504
+ const showBalanceBlock = showBalance === true;
11505
+ (0, import_react11.useLayoutEffect)(() => {
11506
+ if (!showBalanceBlock) {
11507
+ setBalance(null);
11508
+ setIsLoadingBalance(false);
11509
+ setShowBalanceSkeleton(false);
11510
+ }
11511
+ }, [showBalanceBlock]);
11366
11512
  (0, import_react11.useEffect)(() => {
11367
11513
  if (!showBalance || !balanceAddress || !balanceChainType || !balanceChainId || !balanceTokenAddress || !publishableKey) {
11368
11514
  setBalance(null);
11369
11515
  setIsLoadingBalance(false);
11516
+ setShowBalanceSkeleton(false);
11517
+ return;
11518
+ }
11519
+ const supportedChainTypes = ["ethereum", "solana", "bitcoin"];
11520
+ if (!supportedChainTypes.includes(balanceChainType)) {
11521
+ setBalance(null);
11522
+ setIsLoadingBalance(false);
11523
+ setShowBalanceSkeleton(false);
11370
11524
  return;
11371
11525
  }
11372
11526
  let cancelled = false;
11373
11527
  setIsLoadingBalance(true);
11528
+ setShowBalanceSkeleton(false);
11529
+ const skeletonTimer = window.setTimeout(() => {
11530
+ if (!cancelled) setShowBalanceSkeleton(true);
11531
+ }, 150);
11374
11532
  getAddressBalance(
11375
11533
  balanceAddress,
11376
11534
  balanceChainType,
@@ -11379,7 +11537,7 @@ function DepositHeader({
11379
11537
  publishableKey
11380
11538
  ).then((response) => {
11381
11539
  if (cancelled) return;
11382
- if (response.balance && response.balance.amount !== "0") {
11540
+ if (response.balance) {
11383
11541
  const token = response.balance.token;
11384
11542
  if (!token) {
11385
11543
  setBalance(null);
@@ -11407,12 +11565,12 @@ function DepositHeader({
11407
11565
  maximumSignificantDigits: 6
11408
11566
  });
11409
11567
  } else {
11410
- formatted = value.toExponential(2);
11568
+ formatted = value === 0 ? "0.00" : value.toExponential(2);
11411
11569
  }
11412
- const balanceText = response.balance.amount_usd ? `Balance: $${response.balance.amount_usd} (${formatted} ${response.balance.token.symbol})` : `Balance: ${formatted} ${response.balance.token.symbol}`;
11413
- setBalance(balanceText);
11570
+ const amountPart = response.balance.amount_usd != null && response.balance.amount_usd !== "" ? `$${response.balance.amount_usd} (${formatted} ${response.balance.token.symbol})` : `${formatted} ${response.balance.token.symbol}`;
11571
+ setBalance(amountPart);
11414
11572
  } else {
11415
- setBalance(null);
11573
+ setBalance("$0.00");
11416
11574
  }
11417
11575
  }).catch((error) => {
11418
11576
  if (cancelled) return;
@@ -11421,9 +11579,11 @@ function DepositHeader({
11421
11579
  }).finally(() => {
11422
11580
  if (cancelled) return;
11423
11581
  setIsLoadingBalance(false);
11582
+ setShowBalanceSkeleton(false);
11424
11583
  });
11425
11584
  return () => {
11426
11585
  cancelled = true;
11586
+ window.clearTimeout(skeletonTimer);
11427
11587
  };
11428
11588
  }, [
11429
11589
  showBalance,
@@ -11479,18 +11639,27 @@ function DepositHeader({
11479
11639
  children: title
11480
11640
  }
11481
11641
  ),
11482
- showBalance && (isLoadingBalance ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-2" }) : balance ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
11642
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
11483
11643
  "div",
11484
11644
  {
11485
- className: "uf-text-xs uf-mt-2",
11645
+ className: "uf-text-xs uf-mt-1",
11486
11646
  style: {
11487
- color: colors2.foreground,
11488
- fontFamily: fonts.regular,
11489
- opacity: 0.7
11647
+ color: colors2.foregroundMuted,
11648
+ fontFamily: fonts.regular
11649
+ },
11650
+ children: subtitle
11651
+ }
11652
+ ) : showBalanceBlock ? isLoadingBalance && showBalanceSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-1" }) : balance ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
11653
+ "div",
11654
+ {
11655
+ className: "uf-text-xs uf-mt-1",
11656
+ style: {
11657
+ color: colors2.foregroundMuted,
11658
+ fontFamily: fonts.regular
11490
11659
  },
11491
- children: balance
11660
+ children: formatBalanceDisplay(balance, projectName)
11492
11661
  }
11493
- ) : null)
11662
+ ) : null : null
11494
11663
  ] }),
11495
11664
  showClose ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
11496
11665
  "button",
@@ -11826,32 +11995,62 @@ function interpolate(template, params) {
11826
11995
  return value !== void 0 ? String(value) : `{{${key}}}`;
11827
11996
  });
11828
11997
  }
11998
+ var DEPOSIT_CONFIRM_DELAY_MS = 1e4;
11999
+ var POLL_INTERVAL_MS = 2500;
12000
+ var POLL_ENDPOINT_INTERVAL_MS = 3e3;
12001
+ var CUTOFF_BUFFER_MS = 6e4;
11829
12002
  function useDepositPolling({
11830
12003
  userId,
11831
12004
  publishableKey,
12005
+ depositConfirmationMode = "auto_ui",
12006
+ depositWalletId,
11832
12007
  enabled = true,
11833
12008
  onDepositSuccess,
11834
12009
  onDepositError
11835
12010
  }) {
11836
12011
  const [executions, setExecutions] = (0, import_react12.useState)([]);
11837
12012
  const [isPolling, setIsPolling] = (0, import_react12.useState)(false);
11838
- const pollingIntervalRef = (0, import_react12.useRef)(
11839
- null
11840
- );
11841
- const [modalOpenedAt] = (0, import_react12.useState)(/* @__PURE__ */ new Date());
11842
- const [trackedExecutions, setTrackedExecutions] = (0, import_react12.useState)(/* @__PURE__ */ new Map());
12013
+ const [pollingEnabled, setPollingEnabled] = (0, import_react12.useState)(false);
12014
+ const [showWaitingUi, setShowWaitingUi] = (0, import_react12.useState)(false);
12015
+ const modalOpenedAtRef = (0, import_react12.useRef)(/* @__PURE__ */ new Date());
12016
+ const trackedExecutionsRef = (0, import_react12.useRef)(/* @__PURE__ */ new Map());
12017
+ const onDepositSuccessRef = (0, import_react12.useRef)(onDepositSuccess);
12018
+ const onDepositErrorRef = (0, import_react12.useRef)(onDepositError);
12019
+ (0, import_react12.useEffect)(() => {
12020
+ onDepositSuccessRef.current = onDepositSuccess;
12021
+ }, [onDepositSuccess]);
12022
+ (0, import_react12.useEffect)(() => {
12023
+ onDepositErrorRef.current = onDepositError;
12024
+ }, [onDepositError]);
12025
+ (0, import_react12.useEffect)(() => {
12026
+ if (depositConfirmationMode === "manual" || !enabled) return;
12027
+ const timeout = setTimeout(() => {
12028
+ setPollingEnabled(true);
12029
+ if (depositConfirmationMode === "auto_ui") {
12030
+ setShowWaitingUi(true);
12031
+ }
12032
+ }, DEPOSIT_CONFIRM_DELAY_MS);
12033
+ return () => clearTimeout(timeout);
12034
+ }, [depositConfirmationMode, enabled]);
11843
12035
  (0, import_react12.useEffect)(() => {
11844
- if (!userId || !modalOpenedAt || !enabled) return;
11845
- const pollInterval = setInterval(async () => {
12036
+ if (!userId || !enabled) return;
12037
+ const modalOpenedAt = modalOpenedAtRef.current;
12038
+ const poll = async () => {
11846
12039
  try {
11847
12040
  const response = await queryExecutions(userId, publishableKey);
12041
+ const cutoff = new Date(modalOpenedAt.getTime() - CUTOFF_BUFFER_MS);
12042
+ const sortedExecutions = [...response.data].sort((a, b) => {
12043
+ const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
12044
+ const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
12045
+ return timeB - timeA;
12046
+ });
11848
12047
  let executionToShow = null;
11849
- for (const execution of response.data) {
12048
+ for (const execution of sortedExecutions) {
11850
12049
  const executionTime = execution.created_at ? new Date(execution.created_at) : null;
11851
- if (!executionTime || executionTime <= modalOpenedAt) {
12050
+ if (!executionTime || executionTime < cutoff) {
11852
12051
  continue;
11853
12052
  }
11854
- const trackedStatus = trackedExecutions.get(execution.id);
12053
+ const trackedStatus = trackedExecutionsRef.current.get(execution.id);
11855
12054
  if (!trackedStatus) {
11856
12055
  executionToShow = execution;
11857
12056
  break;
@@ -11872,35 +12071,30 @@ function useDepositPolling({
11872
12071
  }
11873
12072
  if (executionToShow) {
11874
12073
  const execution = executionToShow;
12074
+ const previousStatus = trackedExecutionsRef.current.get(execution.id);
12075
+ trackedExecutionsRef.current.set(execution.id, execution.status);
11875
12076
  setExecutions((prev) => {
11876
12077
  const existingIndex = prev.findIndex((e) => e.id === execution.id);
11877
12078
  if (existingIndex >= 0) {
11878
12079
  const updated = [...prev];
11879
12080
  updated[existingIndex] = execution;
11880
12081
  return updated;
11881
- } else {
11882
- return [...prev, execution];
11883
12082
  }
11884
- });
11885
- const previousStatus = trackedExecutions.get(execution.id);
11886
- setTrackedExecutions((prev) => {
11887
- const updated = new Map(prev);
11888
- updated.set(execution.id, execution.status);
11889
- return updated;
12083
+ return [...prev, execution];
11890
12084
  });
11891
12085
  const inProgressStatuses = [
11892
12086
  ExecutionStatus.PENDING,
11893
12087
  ExecutionStatus.WAITING,
11894
12088
  ExecutionStatus.DELAYED
11895
12089
  ];
11896
- if (execution.status === ExecutionStatus.SUCCEEDED && onDepositSuccess && (!previousStatus || inProgressStatuses.includes(previousStatus))) {
11897
- onDepositSuccess({
12090
+ if (execution.status === ExecutionStatus.SUCCEEDED && (!previousStatus || inProgressStatuses.includes(previousStatus))) {
12091
+ onDepositSuccessRef.current?.({
11898
12092
  message: "Deposit completed successfully",
11899
12093
  executionId: execution.id,
11900
12094
  transaction: execution
11901
12095
  });
11902
- } else if (execution.status === ExecutionStatus.FAILED && onDepositError && previousStatus !== ExecutionStatus.FAILED) {
11903
- onDepositError({
12096
+ } else if (execution.status === ExecutionStatus.FAILED && previousStatus !== ExecutionStatus.FAILED) {
12097
+ onDepositErrorRef.current?.({
11904
12098
  message: "Deposit failed",
11905
12099
  code: "DEPOSIT_FAILED",
11906
12100
  error: execution
@@ -11909,36 +12103,45 @@ function useDepositPolling({
11909
12103
  }
11910
12104
  } catch (error) {
11911
12105
  console.error("Failed to fetch executions:", error);
11912
- if (onDepositError) {
11913
- onDepositError({
11914
- message: "Failed to fetch deposit status",
11915
- code: "POLLING_ERROR",
11916
- error
11917
- });
11918
- }
12106
+ onDepositErrorRef.current?.({
12107
+ message: "Failed to fetch deposit status",
12108
+ code: "POLLING_ERROR",
12109
+ error
12110
+ });
11919
12111
  }
11920
- }, 3e3);
12112
+ };
12113
+ const pollInterval = setInterval(poll, POLL_INTERVAL_MS);
11921
12114
  setIsPolling(true);
11922
- pollingIntervalRef.current = pollInterval;
11923
12115
  return () => {
11924
- if (pollingIntervalRef.current) {
11925
- clearInterval(pollingIntervalRef.current);
11926
- pollingIntervalRef.current = null;
11927
- }
12116
+ clearInterval(pollInterval);
11928
12117
  setIsPolling(false);
11929
12118
  };
11930
- }, [
11931
- userId,
11932
- publishableKey,
11933
- modalOpenedAt,
11934
- trackedExecutions,
11935
- enabled,
11936
- onDepositSuccess,
11937
- onDepositError
11938
- ]);
12119
+ }, [userId, publishableKey, enabled]);
12120
+ (0, import_react12.useEffect)(() => {
12121
+ if (!pollingEnabled || !depositWalletId) return;
12122
+ const triggerPoll = async () => {
12123
+ try {
12124
+ await pollDirectExecutions(
12125
+ { deposit_wallet_id: depositWalletId },
12126
+ publishableKey
12127
+ );
12128
+ } catch {
12129
+ }
12130
+ };
12131
+ triggerPoll();
12132
+ const interval = setInterval(triggerPoll, POLL_ENDPOINT_INTERVAL_MS);
12133
+ return () => clearInterval(interval);
12134
+ }, [pollingEnabled, depositWalletId, publishableKey]);
12135
+ const handleIveDeposited = () => {
12136
+ setPollingEnabled(true);
12137
+ setShowWaitingUi(true);
12138
+ };
11939
12139
  return {
11940
12140
  executions,
11941
- isPolling
12141
+ isPolling,
12142
+ pollingEnabled,
12143
+ showWaitingUi,
12144
+ handleIveDeposited
11942
12145
  };
11943
12146
  }
11944
12147
  function formatCurrency(currency) {
@@ -15686,10 +15889,48 @@ var WALLET_ICON_COMPONENTS = {
15686
15889
  backpack: BackpackIcon,
15687
15890
  glow: GlowIcon
15688
15891
  };
15689
- function truncateAddress2(address) {
15892
+ function truncateAddress3(address) {
15690
15893
  if (address.length <= 10) return address;
15691
15894
  return `${address.slice(0, 4)}...${address.slice(-4)}`;
15692
15895
  }
15896
+ function identifyEthWallet(provider, _win, hint) {
15897
+ switch (hint) {
15898
+ case "metamask":
15899
+ return { type: "metamask", name: "MetaMask", icon: "metamask" };
15900
+ case "phantom":
15901
+ return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
15902
+ case "coinbase":
15903
+ return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
15904
+ case "okx":
15905
+ return { type: "okx", name: "OKX Wallet", icon: "okx" };
15906
+ case "rabby":
15907
+ return { type: "rabby", name: "Rabby", icon: "rabby" };
15908
+ case "trust":
15909
+ return { type: "trust", name: "Trust Wallet", icon: "trust" };
15910
+ case "rainbow":
15911
+ return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
15912
+ }
15913
+ const anyProvider = provider;
15914
+ if (provider.isPhantom) {
15915
+ return { type: "phantom-ethereum", name: "Phantom", icon: "phantom" };
15916
+ }
15917
+ if (anyProvider.isCoinbaseWallet) {
15918
+ return { type: "coinbase", name: "Coinbase Wallet", icon: "coinbase" };
15919
+ }
15920
+ if (anyProvider.isRabby) {
15921
+ return { type: "rabby", name: "Rabby", icon: "rabby" };
15922
+ }
15923
+ if (anyProvider.isTrust) {
15924
+ return { type: "trust", name: "Trust Wallet", icon: "trust" };
15925
+ }
15926
+ if (anyProvider.isRainbow) {
15927
+ return { type: "rainbow", name: "Rainbow", icon: "rainbow" };
15928
+ }
15929
+ if (provider.isMetaMask && !provider.isPhantom) {
15930
+ return { type: "metamask", name: "MetaMask", icon: "metamask" };
15931
+ }
15932
+ return { type: "metamask", name: "Wallet", icon: "metamask" };
15933
+ }
15693
15934
  function BrowserWalletButton({
15694
15935
  onClick,
15695
15936
  onConnectClick,
@@ -15706,9 +15947,35 @@ function BrowserWalletButton({
15706
15947
  const [balanceText, setBalanceText] = React202.useState(null);
15707
15948
  const [isLoadingBalance, setIsLoadingBalance] = React202.useState(false);
15708
15949
  const iconVariant = mode === "dark" ? "light" : "dark";
15950
+ const onDisconnectRef = React202.useRef(onDisconnect);
15951
+ onDisconnectRef.current = onDisconnect;
15709
15952
  React202.useEffect(() => {
15710
15953
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
15711
15954
  }, []);
15955
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React202.useState(0);
15956
+ React202.useEffect(() => {
15957
+ if (typeof window === "undefined") return;
15958
+ const anyWin = window;
15959
+ if (!anyWin.__eip6963Providers) {
15960
+ anyWin.__eip6963Providers = [];
15961
+ }
15962
+ const handleAnnouncement = (event) => {
15963
+ const { detail } = event;
15964
+ if (!detail?.info || !detail?.provider) return;
15965
+ const exists = anyWin.__eip6963Providers.some(
15966
+ (p) => p.info.uuid === detail.info.uuid
15967
+ );
15968
+ if (!exists) {
15969
+ anyWin.__eip6963Providers.push(detail);
15970
+ setEip6963ProviderCount(anyWin.__eip6963Providers.length);
15971
+ }
15972
+ };
15973
+ window.addEventListener("eip6963:announceProvider", handleAnnouncement);
15974
+ window.dispatchEvent(new Event("eip6963:requestProvider"));
15975
+ return () => {
15976
+ window.removeEventListener("eip6963:announceProvider", handleAnnouncement);
15977
+ };
15978
+ }, []);
15712
15979
  React202.useEffect(() => {
15713
15980
  if (!wallet || !publishableKey) {
15714
15981
  setBalanceText(null);
@@ -15758,166 +16025,85 @@ function BrowserWalletButton({
15758
16025
  try {
15759
16026
  const win = typeof window !== "undefined" ? window : null;
15760
16027
  if (!win) return;
16028
+ if (getUserDisconnectedWallet()) {
16029
+ if (mounted) {
16030
+ setWallet(null);
16031
+ setIsLoading(false);
16032
+ }
16033
+ return;
16034
+ }
15761
16035
  if (!chainType || chainType === "solana") {
15762
- const phantomSolana = win.phantom?.solana;
15763
- if (phantomSolana?.isPhantom) {
15764
- if (phantomSolana.isConnected && phantomSolana.publicKey) {
16036
+ const anyWin2 = win;
16037
+ const trySilentSolana = async (provider, type, name, icon) => {
16038
+ if (!provider) return false;
16039
+ if (provider.isConnected && provider.publicKey) {
15765
16040
  if (mounted) {
15766
- setWallet({
15767
- type: "phantom-solana",
15768
- name: "Phantom",
15769
- address: phantomSolana.publicKey.toString(),
15770
- icon: "phantom"
15771
- });
16041
+ setWallet({ type, name, address: provider.publicKey.toString(), icon });
15772
16042
  setIsLoading(false);
15773
16043
  }
15774
- return;
16044
+ return true;
15775
16045
  }
15776
- }
15777
- const solflare = win.solflare;
15778
- if (solflare?.isConnected && solflare?.publicKey) {
15779
- if (mounted) {
15780
- setWallet({
15781
- type: "solflare",
15782
- name: "Solflare",
15783
- address: solflare.publicKey.toString(),
15784
- icon: "solflare"
15785
- });
15786
- setIsLoading(false);
16046
+ try {
16047
+ const resp = await provider.connect({ onlyIfTrusted: true });
16048
+ if (mounted && resp.publicKey) {
16049
+ setWallet({ type, name, address: resp.publicKey.toString(), icon });
16050
+ setIsLoading(false);
16051
+ return true;
16052
+ }
16053
+ } catch {
15787
16054
  }
15788
- return;
16055
+ return false;
16056
+ };
16057
+ if (await trySilentSolana(win.phantom?.solana, "phantom-solana", "Phantom", "phantom")) return;
16058
+ if (await trySilentSolana(anyWin2.solflare, "solflare", "Solflare", "solflare")) return;
16059
+ if (await trySilentSolana(anyWin2.backpack, "backpack", "Backpack", "backpack")) return;
16060
+ if (await trySilentSolana(anyWin2.glow, "glow", "Glow", "glow")) return;
16061
+ }
16062
+ if (!chainType || chainType === "ethereum") {
16063
+ const anyWin2 = win;
16064
+ const allProviders = [];
16065
+ const eip6963Providers = anyWin2.__eip6963Providers || [];
16066
+ for (const { info, provider } of eip6963Providers) {
16067
+ let walletId = "default";
16068
+ if (info.rdns.includes("metamask")) walletId = "metamask";
16069
+ else if (info.rdns.includes("phantom")) walletId = "phantom";
16070
+ else if (info.rdns.includes("coinbase")) walletId = "coinbase";
16071
+ else if (info.rdns.includes("okx")) walletId = "okx";
16072
+ else if (info.rdns.includes("rabby")) walletId = "rabby";
16073
+ else if (info.rdns.includes("trust")) walletId = "trust";
16074
+ else if (info.rdns.includes("rainbow")) walletId = "rainbow";
16075
+ allProviders.push({ provider, walletId });
15789
16076
  }
15790
- const backpack = win.backpack;
15791
- if (backpack?.isConnected && backpack?.publicKey) {
15792
- if (mounted) {
15793
- setWallet({
15794
- type: "backpack",
15795
- name: "Backpack",
15796
- address: backpack.publicKey.toString(),
15797
- icon: "backpack"
15798
- });
15799
- setIsLoading(false);
16077
+ if (allProviders.length === 0) {
16078
+ if (win.phantom?.ethereum) {
16079
+ allProviders.push({ provider: win.phantom.ethereum, walletId: "phantom" });
15800
16080
  }
15801
- return;
15802
- }
15803
- const glow = win.glow;
15804
- if (glow?.isConnected && glow?.publicKey) {
15805
- if (mounted) {
15806
- setWallet({
15807
- type: "glow",
15808
- name: "Glow",
15809
- address: glow.publicKey.toString(),
15810
- icon: "glow"
15811
- });
15812
- setIsLoading(false);
16081
+ if (anyWin2.okxwallet) {
16082
+ allProviders.push({ provider: anyWin2.okxwallet, walletId: "okx" });
16083
+ }
16084
+ if (anyWin2.coinbaseWalletExtension) {
16085
+ allProviders.push({ provider: anyWin2.coinbaseWalletExtension, walletId: "coinbase" });
16086
+ }
16087
+ if (win.ethereum) {
16088
+ const isDuplicate = allProviders.some((p) => p.provider === win.ethereum);
16089
+ if (!isDuplicate) {
16090
+ allProviders.push({ provider: win.ethereum, walletId: "default" });
16091
+ }
15813
16092
  }
15814
- return;
15815
16093
  }
15816
- }
15817
- if (!chainType || chainType === "ethereum") {
15818
- const ethProvider2 = win.ethereum;
15819
- if (ethProvider2) {
16094
+ for (const { provider, walletId } of allProviders) {
16095
+ if (!provider) continue;
15820
16096
  try {
15821
- const accounts = await ethProvider2.request({ method: "eth_accounts" });
15822
- if (accounts && accounts.length > 0) {
15823
- const address = accounts[0];
15824
- if (ethProvider2.isMetaMask && !ethProvider2.isPhantom) {
15825
- const providers = ethProvider2.providers;
15826
- if (win.okxwallet) {
15827
- if (mounted) {
15828
- setWallet({
15829
- type: "okx",
15830
- name: "OKX Wallet",
15831
- address,
15832
- icon: "okx"
15833
- });
15834
- setIsLoading(false);
15835
- }
15836
- return;
15837
- }
15838
- if (ethProvider2.isRabby) {
15839
- if (mounted) {
15840
- setWallet({
15841
- type: "rabby",
15842
- name: "Rabby",
15843
- address,
15844
- icon: "rabby"
15845
- });
15846
- setIsLoading(false);
15847
- }
15848
- return;
15849
- }
15850
- if (ethProvider2.isTrust || win.trustwallet) {
15851
- if (mounted) {
15852
- setWallet({
15853
- type: "trust",
15854
- name: "Trust Wallet",
15855
- address,
15856
- icon: "trust"
15857
- });
15858
- setIsLoading(false);
15859
- }
15860
- return;
15861
- }
15862
- if (ethProvider2.isRainbow) {
15863
- if (mounted) {
15864
- setWallet({
15865
- type: "rainbow",
15866
- name: "Rainbow",
15867
- address,
15868
- icon: "rainbow"
15869
- });
15870
- setIsLoading(false);
15871
- }
15872
- return;
15873
- }
15874
- if (mounted) {
15875
- setWallet({
15876
- type: "metamask",
15877
- name: "MetaMask",
15878
- address,
15879
- icon: "metamask"
15880
- });
15881
- setIsLoading(false);
15882
- }
15883
- return;
15884
- }
15885
- if (ethProvider2.isPhantom) {
15886
- if (mounted) {
15887
- setWallet({
15888
- type: "phantom-ethereum",
15889
- name: "Phantom",
15890
- address,
15891
- icon: "phantom"
15892
- });
15893
- setIsLoading(false);
15894
- }
15895
- return;
15896
- }
15897
- if (ethProvider2.isCoinbaseWallet) {
15898
- if (mounted) {
15899
- setWallet({
15900
- type: "coinbase",
15901
- name: "Coinbase Wallet",
15902
- address,
15903
- icon: "coinbase"
15904
- });
15905
- setIsLoading(false);
15906
- }
15907
- return;
15908
- }
15909
- if (mounted) {
15910
- setWallet({
15911
- type: "metamask",
15912
- name: "Wallet",
15913
- address,
15914
- icon: "metamask"
15915
- });
15916
- setIsLoading(false);
15917
- }
15918
- return;
16097
+ const accounts = await provider.request({ method: "eth_accounts" });
16098
+ if (!accounts || accounts.length === 0) continue;
16099
+ const address = accounts[0];
16100
+ const resolved = identifyEthWallet(provider, anyWin2, walletId);
16101
+ if (mounted) {
16102
+ setWallet({ ...resolved, address });
16103
+ setIsLoading(false);
15919
16104
  }
15920
- } catch (ethError) {
16105
+ return;
16106
+ } catch {
15921
16107
  }
15922
16108
  }
15923
16109
  }
@@ -15938,12 +16124,12 @@ function BrowserWalletButton({
15938
16124
  detectWallet();
15939
16125
  };
15940
16126
  const handleDisconnect = () => {
15941
- onDisconnect?.();
16127
+ onDisconnectRef.current?.();
15942
16128
  detectWallet();
15943
16129
  };
15944
16130
  const handleEthAccountsChanged = (accounts) => {
15945
16131
  if (Array.isArray(accounts) && accounts.length === 0) {
15946
- onDisconnect?.();
16132
+ onDisconnectRef.current?.();
15947
16133
  }
15948
16134
  detectWallet();
15949
16135
  };
@@ -15953,10 +16139,24 @@ function BrowserWalletButton({
15953
16139
  solanaProvider.on("disconnect", handleDisconnect);
15954
16140
  solanaProvider.on("accountChanged", handleAccountsChanged);
15955
16141
  }
15956
- const ethProvider = window.phantom?.ethereum || window.ethereum;
15957
- if (ethProvider) {
15958
- ethProvider.on("accountsChanged", handleEthAccountsChanged);
15959
- ethProvider.on("chainChanged", handleAccountsChanged);
16142
+ const anyWin = window;
16143
+ const ethProviders = [];
16144
+ if (anyWin.__eip6963Providers) {
16145
+ for (const { provider } of anyWin.__eip6963Providers) {
16146
+ if (provider && !ethProviders.includes(provider)) {
16147
+ ethProviders.push(provider);
16148
+ }
16149
+ }
16150
+ }
16151
+ if (window.ethereum && !ethProviders.includes(window.ethereum)) {
16152
+ ethProviders.push(window.ethereum);
16153
+ }
16154
+ if (window.phantom?.ethereum && !ethProviders.includes(window.phantom.ethereum)) {
16155
+ ethProviders.push(window.phantom.ethereum);
16156
+ }
16157
+ for (const provider of ethProviders) {
16158
+ provider.on("accountsChanged", handleEthAccountsChanged);
16159
+ provider.on("chainChanged", handleAccountsChanged);
15960
16160
  }
15961
16161
  return () => {
15962
16162
  mounted = false;
@@ -15965,12 +16165,12 @@ function BrowserWalletButton({
15965
16165
  solanaProvider.off("disconnect", handleDisconnect);
15966
16166
  solanaProvider.off("accountChanged", handleAccountsChanged);
15967
16167
  }
15968
- if (ethProvider) {
15969
- ethProvider.removeListener("accountsChanged", handleEthAccountsChanged);
15970
- ethProvider.removeListener("chainChanged", handleAccountsChanged);
16168
+ for (const provider of ethProviders) {
16169
+ provider.removeListener("accountsChanged", handleEthAccountsChanged);
16170
+ provider.removeListener("chainChanged", handleAccountsChanged);
15971
16171
  }
15972
16172
  };
15973
- }, [chainType]);
16173
+ }, [chainType, eip6963ProviderCount]);
15974
16174
  const handleConnect = async () => {
15975
16175
  if (wallet) {
15976
16176
  onClick(wallet);
@@ -15986,6 +16186,7 @@ function BrowserWalletButton({
15986
16186
  const solanaProvider = window.phantom?.solana || window.solana;
15987
16187
  if (solanaProvider?.isPhantom) {
15988
16188
  const { publicKey } = await solanaProvider.connect();
16189
+ setUserDisconnectedWallet(false);
15989
16190
  setWallet({
15990
16191
  type: "phantom-solana",
15991
16192
  name: "Phantom",
@@ -16003,6 +16204,7 @@ function BrowserWalletButton({
16003
16204
  method: "eth_requestAccounts"
16004
16205
  });
16005
16206
  if (accounts && accounts.length > 0) {
16207
+ setUserDisconnectedWallet(false);
16006
16208
  const isPhantom = ethProvider.isPhantom;
16007
16209
  setWallet({
16008
16210
  type: isPhantom ? "phantom-ethereum" : "metamask",
@@ -16014,7 +16216,10 @@ function BrowserWalletButton({
16014
16216
  }
16015
16217
  }
16016
16218
  } catch (error) {
16017
- console.error("Error connecting wallet:", error);
16219
+ if (error && typeof error === "object" && "code" in error && error.code === 4001) {
16220
+ } else {
16221
+ console.error("Error connecting wallet:", error);
16222
+ }
16018
16223
  } finally {
16019
16224
  setIsConnecting(false);
16020
16225
  }
@@ -16060,7 +16265,7 @@ function BrowserWalletButton({
16060
16265
  color: components.card.titleColor,
16061
16266
  fontFamily: fonts.regular
16062
16267
  },
16063
- children: wallet ? `${wallet.name} (${truncateAddress2(wallet.address)})` : "Connect Wallet"
16268
+ children: wallet ? `${wallet.name} (${truncateAddress3(wallet.address)})` : "Connect Wallet"
16064
16269
  }
16065
16270
  ),
16066
16271
  isLoadingBalance ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "uf-h-3 uf-w-24 uf-bg-muted uf-rounded uf-animate-pulse" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
@@ -16232,11 +16437,6 @@ function useSupportedDepositTokens(publishableKey, options) {
16232
16437
  refetchOnWindowFocus: false
16233
16438
  });
16234
16439
  }
16235
- var qrCache = /* @__PURE__ */ new Map();
16236
- var imageCache = /* @__PURE__ */ new Map();
16237
- function getCacheKey(value, size4, imageUrl, darkMode) {
16238
- return `${value}|${size4}|${imageUrl || ""}|${darkMode}`;
16239
- }
16240
16440
  function createQRConfig(value, size4, imageUrl, imageSize, darkMode) {
16241
16441
  return {
16242
16442
  type: "svg",
@@ -16273,72 +16473,6 @@ function createQRConfig(value, size4, imageUrl, imageSize, darkMode) {
16273
16473
  }
16274
16474
  };
16275
16475
  }
16276
- async function preloadImageAsync(url) {
16277
- if (!url || imageCache.has(url)) return;
16278
- return new Promise((resolve) => {
16279
- const img = new Image();
16280
- img.crossOrigin = "anonymous";
16281
- img.onload = () => {
16282
- imageCache.set(url, true);
16283
- resolve();
16284
- };
16285
- img.onerror = () => {
16286
- imageCache.set(url, false);
16287
- resolve();
16288
- };
16289
- img.src = url;
16290
- });
16291
- }
16292
- function waitForStyledQR(container, maxAttempts = 20) {
16293
- return new Promise((resolve) => {
16294
- let attempts = 0;
16295
- const check = () => {
16296
- const svg = container.querySelector("svg");
16297
- if (!svg) {
16298
- if (attempts++ < maxAttempts) {
16299
- requestAnimationFrame(check);
16300
- } else {
16301
- resolve(null);
16302
- }
16303
- return;
16304
- }
16305
- const hasCircles = svg.querySelectorAll("circle").length > 0;
16306
- const hasPaths = svg.querySelectorAll("path").length > 0;
16307
- if (hasCircles || hasPaths) {
16308
- resolve(svg.outerHTML);
16309
- } else if (attempts++ < maxAttempts) {
16310
- requestAnimationFrame(check);
16311
- } else {
16312
- resolve(svg.outerHTML);
16313
- }
16314
- };
16315
- requestAnimationFrame(check);
16316
- });
16317
- }
16318
- async function preloadQRCode(value, size4 = 180, imageUrl, imageSize = 45, darkMode = false) {
16319
- if (!value) return;
16320
- const cacheKey = getCacheKey(value, size4, imageUrl, darkMode);
16321
- if (qrCache.has(cacheKey)) return;
16322
- if (imageUrl) {
16323
- await preloadImageAsync(imageUrl);
16324
- }
16325
- const tempContainer = document.createElement("div");
16326
- tempContainer.style.position = "absolute";
16327
- tempContainer.style.left = "-9999px";
16328
- tempContainer.style.top = "-9999px";
16329
- document.body.appendChild(tempContainer);
16330
- try {
16331
- const config = createQRConfig(value, size4, imageUrl, imageSize, darkMode);
16332
- const qrInstance = new import_qr_code_styling.default(config);
16333
- qrInstance.append(tempContainer);
16334
- const svgString = await waitForStyledQR(tempContainer);
16335
- if (svgString) {
16336
- qrCache.set(cacheKey, { svgString });
16337
- }
16338
- } finally {
16339
- document.body.removeChild(tempContainer);
16340
- }
16341
- }
16342
16476
  function StyledQRCode({
16343
16477
  value,
16344
16478
  size: size4 = 180,
@@ -16347,107 +16481,28 @@ function StyledQRCode({
16347
16481
  darkMode = false
16348
16482
  }) {
16349
16483
  const containerRef = (0, import_react19.useRef)(null);
16350
- const [isReady, setIsReady] = (0, import_react19.useState)(false);
16351
- const currentKeyRef = (0, import_react19.useRef)("");
16352
- const cacheKey = getCacheKey(value, size4, imageUrl, darkMode);
16353
- const cachedEntry = qrCache.get(cacheKey);
16354
- const renderQR = (0, import_react19.useCallback)(async () => {
16484
+ const qrRef = (0, import_react19.useRef)(null);
16485
+ (0, import_react19.useEffect)(() => {
16355
16486
  if (!containerRef.current || !value) return;
16356
- const key = getCacheKey(value, size4, imageUrl, darkMode);
16357
- if (currentKeyRef.current === key) {
16358
- setIsReady(true);
16359
- return;
16360
- }
16361
- currentKeyRef.current = key;
16362
- containerRef.current.innerHTML = "";
16363
- const cached = qrCache.get(key);
16364
- if (cached?.svgString) {
16365
- containerRef.current.innerHTML = cached.svgString;
16366
- setIsReady(true);
16367
- return;
16368
- }
16369
- if (imageUrl) {
16370
- await preloadImageAsync(imageUrl);
16371
- }
16372
16487
  const config = createQRConfig(value, size4, imageUrl, imageSize, darkMode);
16373
- const qrInstance = new import_qr_code_styling.default(config);
16374
- qrInstance.append(containerRef.current);
16375
- const svgString = await waitForStyledQR(containerRef.current);
16376
- if (svgString) {
16377
- qrCache.set(key, { svgString });
16488
+ if (!qrRef.current) {
16489
+ qrRef.current = new import_qr_code_styling.default(config);
16490
+ qrRef.current.append(containerRef.current);
16491
+ } else {
16492
+ qrRef.current.update(config);
16378
16493
  }
16379
- setIsReady(true);
16380
16494
  }, [value, size4, imageUrl, imageSize, darkMode]);
16381
- (0, import_react19.useEffect)(() => {
16382
- let mounted = true;
16383
- const init = async () => {
16384
- if (!mounted) return;
16385
- await renderQR();
16386
- };
16387
- setIsReady(false);
16388
- init();
16389
- return () => {
16390
- mounted = false;
16391
- };
16392
- }, [renderQR]);
16393
- const showSkeleton = !isReady && !cachedEntry?.svgString;
16394
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
16495
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
16395
16496
  "div",
16396
16497
  {
16498
+ ref: containerRef,
16397
16499
  style: {
16398
16500
  width: size4,
16399
16501
  height: size4,
16400
16502
  display: "flex",
16401
16503
  alignItems: "center",
16402
- justifyContent: "center",
16403
- position: "relative"
16404
- },
16405
- children: [
16406
- showSkeleton && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
16407
- "div",
16408
- {
16409
- style: {
16410
- position: "absolute",
16411
- inset: 0,
16412
- display: "flex",
16413
- alignItems: "center",
16414
- justifyContent: "center",
16415
- background: darkMode ? "linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%)" : "linear-gradient(135deg, #f0f0f0 0%, #e0e0e0 100%)",
16416
- borderRadius: 8,
16417
- animation: "uf-qr-pulse 1.5s ease-in-out infinite"
16418
- },
16419
- children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
16420
- "div",
16421
- {
16422
- style: {
16423
- width: size4 * 0.6,
16424
- height: size4 * 0.6,
16425
- background: darkMode ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.05)",
16426
- borderRadius: 4
16427
- }
16428
- }
16429
- )
16430
- }
16431
- ),
16432
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
16433
- "div",
16434
- {
16435
- ref: containerRef,
16436
- style: {
16437
- width: size4,
16438
- height: size4,
16439
- opacity: isReady ? 1 : 0,
16440
- transition: "opacity 0.15s ease-out"
16441
- }
16442
- }
16443
- ),
16444
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("style", { children: `
16445
- @keyframes uf-qr-pulse {
16446
- 0%, 100% { opacity: 1; }
16447
- 50% { opacity: 0.6; }
16448
- }
16449
- ` })
16450
- ]
16504
+ justifyContent: "center"
16505
+ }
16451
16506
  }
16452
16507
  );
16453
16508
  }
@@ -16459,7 +16514,8 @@ var COMMON_TOKENS = [
16459
16514
  { symbol: "USDC", chainType: "solana", chainId: "mainnet" },
16460
16515
  { symbol: "POL", chainType: "ethereum", chainId: "137" },
16461
16516
  { symbol: "BNB", chainType: "ethereum", chainId: "56" },
16462
- { symbol: "BTC", chainType: "bitcoin", chainId: "mainnet" }
16517
+ { symbol: "BTC", chainType: "bitcoin", chainId: "mainnet" },
16518
+ { symbol: "XRP", chainType: "xrpl", chainId: "mainnet" }
16463
16519
  ];
16464
16520
  function getRecentTokens() {
16465
16521
  if (typeof window === "undefined") return [];
@@ -16907,47 +16963,32 @@ function TokenSelectorSheet({
16907
16963
  }
16908
16964
  );
16909
16965
  }
16910
- function PollCooldownButton({
16911
- currentWalletId,
16912
- pollCooldown,
16913
- publishableKey,
16914
- onCooldownChange,
16915
- cooldownRef,
16916
- buttonText = "Check again"
16966
+ function DepositPollingUi({
16967
+ depositConfirmationMode,
16968
+ showWaitingUi,
16969
+ hasExecution,
16970
+ onIveDeposited
16917
16971
  }) {
16918
- const handleClick = async () => {
16919
- if (!currentWalletId || pollCooldown > 0) return;
16920
- try {
16921
- await pollDirectExecutions(
16922
- { deposit_wallet_id: currentWalletId },
16923
- publishableKey
16924
- );
16925
- const cooldownSeconds = 5;
16926
- onCooldownChange(cooldownSeconds);
16927
- if (cooldownRef.current) clearInterval(cooldownRef.current);
16928
- cooldownRef.current = setInterval(() => {
16929
- onCooldownChange((prev) => {
16930
- if (prev <= 1) {
16931
- if (cooldownRef.current) clearInterval(cooldownRef.current);
16932
- cooldownRef.current = null;
16933
- return 0;
16934
- }
16935
- return prev - 1;
16936
- });
16937
- }, 1e3);
16938
- } catch (error) {
16939
- console.error("Failed to start poll workflow:", error);
16940
- }
16941
- };
16942
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
16943
- "button",
16944
- {
16945
- onClick: handleClick,
16946
- disabled: !currentWalletId || pollCooldown > 0,
16947
- className: "uf-w-full uf-rounded-xl uf-py-2.5 uf-px-2 uf-flex uf-items-center uf-gap-3 uf-justify-center uf-text-center uf-text-sm uf-bg-primary hover:uf-bg-primary/80 uf-transition-colors uf-text-left disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
16948
- children: pollCooldown > 0 ? `${buttonText} in ${pollCooldown}s` : "I've made the deposit"
16949
- }
16950
- ) });
16972
+ if (depositConfirmationMode === "manual" && !showWaitingUi) {
16973
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
16974
+ "button",
16975
+ {
16976
+ onClick: onIveDeposited,
16977
+ className: "uf-w-full uf-rounded-xl uf-py-2.5 uf-px-2 uf-flex uf-items-center uf-justify-center uf-text-sm uf-bg-primary hover:uf-bg-primary/80 uf-transition-colors",
16978
+ children: "I've made the deposit"
16979
+ }
16980
+ );
16981
+ }
16982
+ if (showWaitingUi && !hasExecution) {
16983
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "uf-bg-secondary uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-gap-3 uf-animate-in uf-fade-in uf-duration-500", children: [
16984
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uf-flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uf-w-9 uf-h-9 uf-rounded-full uf-border-2 uf-border-t-primary uf-border-primary/20 uf-animate-spin" }) }),
16985
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { children: [
16986
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: "Processing deposit transactions" }),
16987
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uf-text-xs uf-text-muted-foreground", children: "We're checking if your deposit has landed." })
16988
+ ] })
16989
+ ] });
16990
+ }
16991
+ return null;
16951
16992
  }
16952
16993
  function DepositFooterLinks({ onGlossaryClick }) {
16953
16994
  return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "uf-flex uf-justify-end uf-items-center uf-gap-2 uf-text-xs uf-text-muted-foreground", children: [
@@ -17106,6 +17147,7 @@ function TransferCryptoSingleInput({
17106
17147
  destinationChainType,
17107
17148
  destinationChainId,
17108
17149
  destinationTokenAddress,
17150
+ depositConfirmationMode = "auto_ui",
17109
17151
  onExecutionsChange,
17110
17152
  onDepositSuccess,
17111
17153
  onDepositError,
@@ -17118,20 +17160,10 @@ function TransferCryptoSingleInput({
17118
17160
  const [copied, setCopied] = (0, import_react18.useState)(false);
17119
17161
  const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
17120
17162
  const [glossaryOpen, setGlossaryOpen] = (0, import_react18.useState)(false);
17121
- const [pollCooldown, setPollCooldown] = (0, import_react18.useState)(0);
17122
- const cooldownRef = (0, import_react18.useRef)(null);
17123
17163
  const [detailsExpanded, setDetailsExpanded] = (0, import_react18.useState)(false);
17124
17164
  const [depositsModalOpen, setDepositsModalOpen] = (0, import_react18.useState)(false);
17125
17165
  const [tokenSelectorOpen, setTokenSelectorOpen] = (0, import_react18.useState)(false);
17126
17166
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react18.useState)(false);
17127
- (0, import_react18.useEffect)(() => {
17128
- return () => {
17129
- if (cooldownRef.current) {
17130
- clearInterval(cooldownRef.current);
17131
- cooldownRef.current = null;
17132
- }
17133
- };
17134
- }, []);
17135
17167
  const {
17136
17168
  data: tokensResponse,
17137
17169
  isLoading: tokensLoading
@@ -17158,13 +17190,6 @@ function TransferCryptoSingleInput({
17158
17190
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
17159
17191
  const loading = externalWallets?.length ? false : walletsLoading;
17160
17192
  const error = walletsError?.message ?? null;
17161
- const { executions: depositExecutions, isPolling } = useDepositPolling({
17162
- userId,
17163
- publishableKey,
17164
- enabled: true,
17165
- onDepositSuccess,
17166
- onDepositError
17167
- });
17168
17193
  const allAvailableChains = (0, import_react18.useMemo)(() => {
17169
17194
  const chainsMap = /* @__PURE__ */ new Map();
17170
17195
  supportedTokens.forEach((t6) => {
@@ -17184,6 +17209,15 @@ function TransferCryptoSingleInput({
17184
17209
  const currentChainType = currentChainData?.chain_type || "ethereum";
17185
17210
  const currentWallet = getWalletByChainType(wallets, currentChainType);
17186
17211
  const depositAddress = currentWallet?.address || "";
17212
+ const { executions: depositExecutions, isPolling, showWaitingUi, handleIveDeposited } = useDepositPolling({
17213
+ userId,
17214
+ publishableKey,
17215
+ depositConfirmationMode,
17216
+ depositWalletId: currentWallet?.id,
17217
+ enabled: true,
17218
+ onDepositSuccess,
17219
+ onDepositError
17220
+ });
17187
17221
  (0, import_react18.useEffect)(() => {
17188
17222
  if (!supportedTokens.length || initialSelectionDone) return;
17189
17223
  let selectedTokenData;
@@ -17233,28 +17267,6 @@ function TransferCryptoSingleInput({
17233
17267
  onExecutionsChange(depositExecutions);
17234
17268
  }
17235
17269
  }, [depositExecutions, onExecutionsChange]);
17236
- (0, import_react18.useEffect)(() => {
17237
- if (!wallets.length || !allAvailableChains.length) return;
17238
- const preloadAllQRCodes = async () => {
17239
- for (const wallet of wallets) {
17240
- if (!wallet.address) continue;
17241
- const chainData = allAvailableChains.find(
17242
- (c) => c.chain_type === wallet.chain_type
17243
- );
17244
- const chainIconUrl = chainData?.icon_url;
17245
- await preloadQRCode(
17246
- wallet.address,
17247
- 180,
17248
- // size
17249
- chainIconUrl,
17250
- 45,
17251
- // imageSize
17252
- isDarkMode
17253
- );
17254
- }
17255
- };
17256
- preloadAllQRCodes();
17257
- }, [wallets, allAvailableChains, isDarkMode]);
17258
17270
  (0, import_react18.useEffect)(() => {
17259
17271
  if (!supportedTokens.length) return;
17260
17272
  const currentToken = supportedTokens.find((t6) => t6.symbol === token);
@@ -17527,14 +17539,12 @@ function TransferCryptoSingleInput({
17527
17539
  ] })
17528
17540
  ] }),
17529
17541
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
17530
- PollCooldownButton,
17542
+ DepositPollingUi,
17531
17543
  {
17532
- currentWalletId: currentWallet?.id,
17533
- pollCooldown,
17534
- publishableKey,
17535
- onCooldownChange: setPollCooldown,
17536
- cooldownRef,
17537
- buttonText: "Try again"
17544
+ depositConfirmationMode,
17545
+ showWaitingUi,
17546
+ hasExecution: depositExecutions.length > 0,
17547
+ onIveDeposited: handleIveDeposited
17538
17548
  }
17539
17549
  ),
17540
17550
  /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DepositFooterLinks, { onGlossaryClick: () => setGlossaryOpen(true) }),
@@ -17712,6 +17722,7 @@ function TransferCryptoDoubleInput({
17712
17722
  destinationChainType,
17713
17723
  destinationChainId,
17714
17724
  destinationTokenAddress,
17725
+ depositConfirmationMode = "auto_ui",
17715
17726
  onExecutionsChange,
17716
17727
  onDepositSuccess,
17717
17728
  onDepositError,
@@ -17724,19 +17735,9 @@ function TransferCryptoDoubleInput({
17724
17735
  const [copied, setCopied] = (0, import_react22.useState)(false);
17725
17736
  const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
17726
17737
  const [glossaryOpen, setGlossaryOpen] = (0, import_react22.useState)(false);
17727
- const [pollCooldown, setPollCooldown] = (0, import_react22.useState)(0);
17728
- const cooldownRef = (0, import_react22.useRef)(null);
17729
17738
  const [detailsExpanded, setDetailsExpanded] = (0, import_react22.useState)(false);
17730
17739
  const [depositsModalOpen, setDepositsModalOpen] = (0, import_react22.useState)(false);
17731
17740
  const [initialSelectionDone, setInitialSelectionDone] = (0, import_react22.useState)(false);
17732
- (0, import_react22.useEffect)(() => {
17733
- return () => {
17734
- if (cooldownRef.current) {
17735
- clearInterval(cooldownRef.current);
17736
- cooldownRef.current = null;
17737
- }
17738
- };
17739
- }, []);
17740
17741
  const {
17741
17742
  data: tokensResponse,
17742
17743
  isLoading: tokensLoading
@@ -17763,13 +17764,6 @@ function TransferCryptoDoubleInput({
17763
17764
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
17764
17765
  const loading = externalWallets?.length ? false : walletsLoading;
17765
17766
  const error = walletsError?.message ?? null;
17766
- const { executions: depositExecutions, isPolling } = useDepositPolling({
17767
- userId,
17768
- publishableKey,
17769
- enabled: true,
17770
- onDepositSuccess,
17771
- onDepositError
17772
- });
17773
17767
  const allAvailableChains = (0, import_react22.useMemo)(() => {
17774
17768
  const chainsMap = /* @__PURE__ */ new Map();
17775
17769
  supportedTokens.forEach((t6) => {
@@ -17789,6 +17783,15 @@ function TransferCryptoDoubleInput({
17789
17783
  const currentChainType = currentChainData?.chain_type || "ethereum";
17790
17784
  const currentWallet = getWalletByChainType(wallets, currentChainType);
17791
17785
  const depositAddress = currentWallet?.address || "";
17786
+ const { executions: depositExecutions, isPolling, showWaitingUi, handleIveDeposited } = useDepositPolling({
17787
+ userId,
17788
+ publishableKey,
17789
+ depositConfirmationMode,
17790
+ depositWalletId: currentWallet?.id,
17791
+ enabled: true,
17792
+ onDepositSuccess,
17793
+ onDepositError
17794
+ });
17792
17795
  (0, import_react22.useEffect)(() => {
17793
17796
  if (!supportedTokens.length || initialSelectionDone) return;
17794
17797
  const allChains = /* @__PURE__ */ new Set();
@@ -17811,28 +17814,6 @@ function TransferCryptoDoubleInput({
17811
17814
  onExecutionsChange(depositExecutions);
17812
17815
  }
17813
17816
  }, [depositExecutions, onExecutionsChange]);
17814
- (0, import_react22.useEffect)(() => {
17815
- if (!wallets.length || !allAvailableChains.length) return;
17816
- const preloadAllQRCodes = async () => {
17817
- for (const wallet of wallets) {
17818
- if (!wallet.address) continue;
17819
- const chainData = allAvailableChains.find(
17820
- (c) => c.chain_type === wallet.chain_type
17821
- );
17822
- const chainIconUrl = chainData?.icon_url;
17823
- await preloadQRCode(
17824
- wallet.address,
17825
- 180,
17826
- // size
17827
- chainIconUrl,
17828
- 45,
17829
- // imageSize
17830
- isDarkMode
17831
- );
17832
- }
17833
- };
17834
- preloadAllQRCodes();
17835
- }, [wallets, allAvailableChains, isDarkMode]);
17836
17817
  (0, import_react22.useEffect)(() => {
17837
17818
  if (!supportedTokens.length) return;
17838
17819
  const currentToken = supportedTokens.find((t6) => t6.symbol === token);
@@ -18139,14 +18120,12 @@ function TransferCryptoDoubleInput({
18139
18120
  ] })
18140
18121
  ] }),
18141
18122
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
18142
- PollCooldownButton,
18123
+ DepositPollingUi,
18143
18124
  {
18144
- currentWalletId: currentWallet?.id,
18145
- pollCooldown,
18146
- publishableKey,
18147
- onCooldownChange: setPollCooldown,
18148
- cooldownRef,
18149
- buttonText: "Check again"
18125
+ depositConfirmationMode,
18126
+ showWaitingUi,
18127
+ hasExecution: depositExecutions.length > 0,
18128
+ onIveDeposited: handleIveDeposited
18150
18129
  }
18151
18130
  ),
18152
18131
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(DepositFooterLinks, { onGlossaryClick: () => setGlossaryOpen(true) }),
@@ -18195,105 +18174,7 @@ function TransferCryptoDoubleInput({
18195
18174
  }
18196
18175
  ) });
18197
18176
  }
18198
- function getIconUrl4(iconUrl, assetCdnUrl) {
18199
- if (!iconUrl) return void 0;
18200
- if (iconUrl.startsWith("http://") || iconUrl.startsWith("https://")) {
18201
- return iconUrl;
18202
- }
18203
- if (assetCdnUrl) {
18204
- return `${assetCdnUrl}${iconUrl.startsWith("/") ? "" : "/"}${iconUrl}`;
18205
- }
18206
- return iconUrl;
18207
- }
18208
- function getTokenFromBalance(balance) {
18209
- if (balance.token) {
18210
- return balance.token;
18211
- }
18212
- const legacyBalance = balance;
18213
- if (legacyBalance.symbol && legacyBalance.decimals !== void 0) {
18214
- return {
18215
- symbol: legacyBalance.symbol,
18216
- name: legacyBalance.name,
18217
- icon_url: legacyBalance.icon_url,
18218
- icon_urls: [],
18219
- token_address: legacyBalance.token_address,
18220
- chain_id: legacyBalance.chain_id,
18221
- chain_name: legacyBalance.chain_name,
18222
- chain_type: legacyBalance.chain_type,
18223
- decimals: legacyBalance.decimals,
18224
- chain_icon_url: legacyBalance.chain_icon_url,
18225
- chain_icon_urls: [],
18226
- minimum_deposit_amount_usd: 0
18227
- };
18228
- }
18229
- return null;
18230
- }
18231
- function isBalanceEligible(balance) {
18232
- if (balance.is_eligible !== void 0) {
18233
- return balance.is_eligible;
18234
- }
18235
- const legacyBalance = balance;
18236
- if (legacyBalance.is_eligible !== void 0) {
18237
- return legacyBalance.is_eligible;
18238
- }
18239
- return true;
18240
- }
18241
- function formatTokenAmount(amount, decimals, symbol) {
18242
- const value = Number(amount) / 10 ** decimals;
18243
- const upperSymbol = symbol.toUpperCase();
18244
- let maxDecimals = 4;
18245
- if (upperSymbol === "BTC" || upperSymbol === "WBTC") {
18246
- maxDecimals = 8;
18247
- } else if (upperSymbol === "ETH" || upperSymbol === "WETH" || upperSymbol === "SOL") {
18248
- maxDecimals = 6;
18249
- }
18250
- if (value >= 1) {
18251
- return value.toLocaleString(void 0, {
18252
- minimumFractionDigits: 2,
18253
- maximumFractionDigits: maxDecimals
18254
- });
18255
- } else if (value > 0) {
18256
- return value.toLocaleString(void 0, {
18257
- minimumFractionDigits: 2,
18258
- maximumFractionDigits: maxDecimals,
18259
- minimumSignificantDigits: 2,
18260
- maximumSignificantDigits: 6
18261
- });
18262
- }
18263
- return "0.00";
18264
- }
18265
- function formatUsdAmount(amountUsd) {
18266
- if (!amountUsd) return null;
18267
- const value = parseFloat(amountUsd);
18268
- if (value <= 0) return null;
18269
- return value.toLocaleString(void 0, {
18270
- minimumFractionDigits: 2,
18271
- maximumFractionDigits: 2
18272
- });
18273
- }
18274
- function truncateAddress3(address) {
18275
- if (address.length <= 13) return address;
18276
- return `${address.slice(0, 6)}...${address.slice(-4)}`;
18277
- }
18278
- function formatBalanceDisplay(balance, projectName) {
18279
- return projectName ? `${projectName} Balance: ${balance}` : `Balance: ${balance}`;
18280
- }
18281
- function formatProcessingTime(seconds) {
18282
- if (seconds === null || seconds === 0) {
18283
- return "< 1 min";
18284
- }
18285
- const minutes = Math.floor(seconds / 60);
18286
- const remainingSeconds = seconds % 60;
18287
- if (minutes === 0) {
18288
- return `< ${remainingSeconds} sec`;
18289
- } else if (remainingSeconds === 0) {
18290
- return `< ${minutes} min`;
18291
- } else {
18292
- return `< ${minutes} min ${remainingSeconds} sec`;
18293
- }
18294
- }
18295
18177
  function SelectTokenView({
18296
- walletInfo,
18297
18178
  projectName,
18298
18179
  assetCdnUrl,
18299
18180
  balances,
@@ -18312,27 +18193,12 @@ function SelectTokenView({
18312
18193
  DepositHeader,
18313
18194
  {
18314
18195
  title: "Select Token",
18196
+ subtitle: formatBalanceDisplay(`$${totalBalanceUsd || "0.00"}`, projectName),
18315
18197
  showBack: true,
18316
18198
  onBack,
18317
18199
  onClose
18318
18200
  }
18319
18201
  ),
18320
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18321
- "div",
18322
- {
18323
- className: "uf-flex uf-flex-col uf-w-full uf-items-center uf-pb-3",
18324
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18325
- children: [
18326
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uf-text-xs", children: [
18327
- walletInfo.name,
18328
- " (",
18329
- truncateAddress3(walletInfo.address),
18330
- ")"
18331
- ] }),
18332
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-text-xs", children: formatBalanceDisplay(`$${totalBalanceUsd || "0.00"}`, projectName) })
18333
- ]
18334
- }
18335
- ),
18336
18202
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-h-[300px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-space-y-2", children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-12", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18337
18203
  LoaderCircle,
18338
18204
  {
@@ -18343,6 +18209,7 @@ function SelectTokenView({
18343
18209
  const token = getTokenFromBalance(balance);
18344
18210
  if (!token) return null;
18345
18211
  const isEligible = isBalanceEligible(balance);
18212
+ const ineligibilityMessage = getIneligibilityMessage(balance);
18346
18213
  const isSelected = selectedBalance && getTokenFromBalance(selectedBalance)?.token_address === token.token_address && getTokenFromBalance(selectedBalance)?.chain_id === token.chain_id;
18347
18214
  const formattedAmount = formatTokenAmount(balance.amount, token.decimals, token.symbol);
18348
18215
  const formattedUsd = formatUsdAmount(balance.amount_usd);
@@ -18360,10 +18227,10 @@ function SelectTokenView({
18360
18227
  children: [
18361
18228
  /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
18362
18229
  /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uf-relative uf-w-9 uf-h-9", children: [
18363
- getIconUrl4(token.icon_url, assetCdnUrl) ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18230
+ getIconUrl2(token.icon_url, assetCdnUrl) ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18364
18231
  "img",
18365
18232
  {
18366
- src: getIconUrl4(token.icon_url, assetCdnUrl),
18233
+ src: getIconUrl2(token.icon_url, assetCdnUrl),
18367
18234
  alt: token.symbol,
18368
18235
  width: 36,
18369
18236
  height: 36,
@@ -18378,10 +18245,10 @@ function SelectTokenView({
18378
18245
  children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uf-text-xs uf-font-medium", style: { color: colors2.foreground }, children: token.symbol.slice(0, 2) })
18379
18246
  }
18380
18247
  ),
18381
- getIconUrl4(token.chain_icon_url, assetCdnUrl) && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18248
+ getIconUrl2(token.chain_icon_url, assetCdnUrl) && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18382
18249
  "img",
18383
18250
  {
18384
- src: getIconUrl4(token.chain_icon_url, assetCdnUrl),
18251
+ src: getIconUrl2(token.chain_icon_url, assetCdnUrl),
18385
18252
  alt: token.chain_name,
18386
18253
  width: 16,
18387
18254
  height: 16,
@@ -18412,7 +18279,7 @@ function SelectTokenView({
18412
18279
  style: { color: components.card.subtitleColor, fontFamily: fonts.regular },
18413
18280
  children: [
18414
18281
  token.chain_name,
18415
- !isEligible && " \u2022 Minimum not met"
18282
+ ineligibilityMessage && ` \u2022 ${ineligibilityMessage}`
18416
18283
  ]
18417
18284
  }
18418
18285
  )
@@ -18468,8 +18335,6 @@ function SelectTokenView({
18468
18335
  ] });
18469
18336
  }
18470
18337
  function EnterAmountView({
18471
- walletInfo,
18472
- projectName,
18473
18338
  selectedBalance,
18474
18339
  selectedToken,
18475
18340
  amountUsd,
@@ -18486,54 +18351,20 @@ function EnterAmountView({
18486
18351
  onClose
18487
18352
  }) {
18488
18353
  const { colors: colors2, fonts, components } = useTheme();
18489
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-flex uf-flex-col uf-h-[420px]", children: [
18354
+ const balanceSubtitle = selectedBalance?.amount_usd ? `Balance: $${parseFloat(selectedBalance.amount_usd).toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} (${formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol)} ${selectedToken.symbol})` : `Balance: ${formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol)} ${selectedToken.symbol}`;
18355
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
18490
18356
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18491
18357
  DepositHeader,
18492
18358
  {
18493
18359
  title: "Enter Amount",
18360
+ subtitle: balanceSubtitle,
18494
18361
  showBack: true,
18495
18362
  onBack,
18496
18363
  onClose
18497
18364
  }
18498
18365
  ),
18499
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-text-center uf-pb-2", children: [
18500
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18501
- "div",
18502
- {
18503
- className: "uf-text-xs",
18504
- style: { color: colors2.foreground, fontFamily: fonts.regular },
18505
- children: [
18506
- walletInfo.name,
18507
- " (",
18508
- truncateAddress3(walletInfo.address),
18509
- ")"
18510
- ]
18511
- }
18512
- ),
18513
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18514
- "div",
18515
- {
18516
- className: "uf-text-sm uf-mt-1",
18517
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18518
- children: selectedBalance?.amount_usd ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
18519
- "Balance: $",
18520
- parseFloat(selectedBalance.amount_usd).toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
18521
- " (",
18522
- formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol),
18523
- " ",
18524
- selectedToken.symbol,
18525
- ")"
18526
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
18527
- "Balance: ",
18528
- formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol),
18529
- " ",
18530
- selectedToken.symbol
18531
- ] })
18532
- }
18533
- )
18534
- ] }),
18535
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-flex-1 uf-overflow-y-auto", children: [
18536
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-text-center uf-h-[100px] uf-flex uf-flex-col uf-justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-center", children: [
18366
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-text-center uf-py-6", children: [
18367
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-center", children: [
18537
18368
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18538
18369
  "span",
18539
18370
  {
@@ -18569,60 +18400,57 @@ function EnterAmountView({
18569
18400
  }
18570
18401
  }
18571
18402
  )
18572
- ] }) }),
18573
- formattedTokenAmount && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-text-sm uf-text-center", style: { color: colors2.foregroundMuted }, children: [
18403
+ ] }),
18404
+ formattedTokenAmount && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-text-sm uf-mt-2", style: { color: colors2.foregroundMuted }, children: [
18574
18405
  "\u2248 ",
18575
18406
  formattedTokenAmount
18576
- ] }),
18577
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-flex uf-gap-2 uf-mt-4 uf-mb-4", children: [
18578
- [25, 50, 100, 500].map((quickAmount) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18579
- "button",
18580
- {
18581
- onClick: () => onAmountChange(quickAmount.toString()),
18582
- className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
18583
- style: {
18584
- backgroundColor: components.card.backgroundColor,
18585
- color: colors2.foreground,
18586
- fontFamily: fonts.medium
18587
- },
18588
- children: [
18589
- "$",
18590
- quickAmount
18591
- ]
18592
- },
18593
- quickAmount
18594
- )),
18595
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18596
- "button",
18597
- {
18598
- onClick: onMaxClick,
18599
- className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
18600
- style: {
18601
- backgroundColor: colors2.primary + "20",
18602
- color: colors2.primary,
18603
- fontFamily: fonts.medium
18604
- },
18605
- children: "MAX"
18606
- }
18607
- )
18608
- ] }),
18609
- tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18610
- "div",
18407
+ ] })
18408
+ ] }),
18409
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uf-flex uf-gap-2 uf-mb-4", children: [
18410
+ [25, 50, 100, 500].map((quickAmount) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18411
+ "button",
18611
18412
  {
18612
- className: "uf-text-center uf-text-xs uf-mb-2",
18413
+ onClick: () => onAmountChange(quickAmount.toString()),
18414
+ className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
18613
18415
  style: {
18614
- color: colors2.warning,
18615
- fontFamily: fonts.regular
18416
+ backgroundColor: components.card.backgroundColor,
18417
+ color: colors2.foreground,
18418
+ fontFamily: fonts.medium
18616
18419
  },
18617
18420
  children: [
18618
- "Minimum deposit: $",
18619
- tokenChainDetails.minimum_deposit_amount_usd.toFixed(2)
18421
+ "$",
18422
+ quickAmount
18620
18423
  ]
18424
+ },
18425
+ quickAmount
18426
+ )),
18427
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18428
+ "button",
18429
+ {
18430
+ onClick: onMaxClick,
18431
+ className: "uf-flex-1 uf-py-2 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80",
18432
+ style: {
18433
+ backgroundColor: colors2.primary + "20",
18434
+ color: colors2.primary,
18435
+ fontFamily: fonts.medium
18436
+ },
18437
+ children: "MAX"
18621
18438
  }
18622
- ),
18623
- inputUsdNum > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_jsx_runtime58.Fragment, { children: inputUsdNum > maxUsdAmount ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-text-center uf-text-sm uf-mb-2", style: { color: colors2.error }, children: "Insufficient balance" }) : error && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-text-center uf-text-sm uf-mb-2 uf-px-2", style: { color: colors2.error }, children: error }) })
18439
+ )
18624
18440
  ] }),
18625
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-pt-4", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18441
+ tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18442
+ "div",
18443
+ {
18444
+ className: "uf-text-center uf-text-xs uf-mb-3",
18445
+ style: { color: colors2.warning, fontFamily: fonts.regular },
18446
+ children: [
18447
+ "Minimum deposit: $",
18448
+ tokenChainDetails.minimum_deposit_amount_usd.toFixed(2)
18449
+ ]
18450
+ }
18451
+ ),
18452
+ inputUsdNum > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_jsx_runtime58.Fragment, { children: inputUsdNum > maxUsdAmount ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-text-center uf-text-sm uf-mb-3", style: { color: colors2.error }, children: "Insufficient balance" }) : error && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uf-text-center uf-text-sm uf-mb-3 uf-px-2", style: { color: colors2.error }, children: error }) }),
18453
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18626
18454
  "button",
18627
18455
  {
18628
18456
  onClick: onReview,
@@ -18635,7 +18463,7 @@ function EnterAmountView({
18635
18463
  },
18636
18464
  children: "Review"
18637
18465
  }
18638
- ) })
18466
+ )
18639
18467
  ] });
18640
18468
  }
18641
18469
  function ReviewView({
@@ -18699,10 +18527,10 @@ function ReviewView({
18699
18527
  }
18700
18528
  ),
18701
18529
  /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
18702
- getIconUrl4(selectedToken.icon_url, assetCdnUrl) && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
18530
+ getIconUrl2(selectedToken.icon_url, assetCdnUrl) && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
18703
18531
  "img",
18704
18532
  {
18705
- src: getIconUrl4(selectedToken.icon_url, assetCdnUrl),
18533
+ src: getIconUrl2(selectedToken.icon_url, assetCdnUrl),
18706
18534
  alt: selectedToken.symbol,
18707
18535
  className: "uf-w-5 uf-h-5 uf-rounded-full"
18708
18536
  }
@@ -18715,7 +18543,7 @@ function ReviewView({
18715
18543
  children: [
18716
18544
  walletInfo.name,
18717
18545
  " (",
18718
- truncateAddress3(walletInfo.address),
18546
+ truncateAddress2(walletInfo.address),
18719
18547
  ")"
18720
18548
  ]
18721
18549
  }
@@ -18736,7 +18564,7 @@ function ReviewView({
18736
18564
  {
18737
18565
  className: "uf-text-sm uf-font-medium",
18738
18566
  style: { color: colors2.foreground, fontFamily: fonts.medium },
18739
- children: truncateAddress3(recipientAddress)
18567
+ children: truncateAddress2(recipientAddress)
18740
18568
  }
18741
18569
  )
18742
18570
  ] }),
@@ -18932,7 +18760,7 @@ function BrowserWalletModal({
18932
18760
  const themeClass = theme === "dark" ? "uf-dark" : "";
18933
18761
  const chainType = depositWallet.chain_type;
18934
18762
  const recipientAddress = depositWallet.address;
18935
- const supportedChainType = chainType === "algorand" ? "ethereum" : chainType;
18763
+ const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
18936
18764
  const { executions: depositExecutions, isPolling } = useDepositPolling({
18937
18765
  userId,
18938
18766
  publishableKey,
@@ -19343,20 +19171,6 @@ function BrowserWalletModal({
19343
19171
  if (tokenAmount === 0 || !selectedToken) return null;
19344
19172
  return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(/\.?0+$/, "");
19345
19173
  }, [tokenAmount, selectedToken]);
19346
- const getTitle = () => {
19347
- switch (step) {
19348
- case "select-token":
19349
- return "Select Token";
19350
- case "input-amount":
19351
- return "Enter Amount";
19352
- case "review":
19353
- return "Review";
19354
- case "confirming":
19355
- return "Confirming...";
19356
- default:
19357
- return "Browser Wallet";
19358
- }
19359
- };
19360
19174
  return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_jsx_runtime61.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
19361
19175
  Dialog2,
19362
19176
  {
@@ -19378,7 +19192,6 @@ function BrowserWalletModal({
19378
19192
  step === "select-token" && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
19379
19193
  SelectTokenView,
19380
19194
  {
19381
- walletInfo,
19382
19195
  projectName,
19383
19196
  assetCdnUrl,
19384
19197
  balances,
@@ -19395,8 +19208,6 @@ function BrowserWalletModal({
19395
19208
  step === "input-amount" && selectedToken && selectedBalance && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
19396
19209
  EnterAmountView,
19397
19210
  {
19398
- walletInfo,
19399
- projectName,
19400
19211
  selectedBalance,
19401
19212
  selectedToken,
19402
19213
  amountUsd,
@@ -19743,6 +19554,7 @@ function WalletSelectionModal({
19743
19554
  if (!accounts || accounts.length === 0) {
19744
19555
  throw new Error("No accounts returned from wallet");
19745
19556
  }
19557
+ setUserDisconnectedWallet(false);
19746
19558
  const address = accounts[0];
19747
19559
  const walletType = wallet.id === "phantom" ? "phantom-ethereum" : wallet.id === "coinbase" ? "coinbase" : "metamask";
19748
19560
  onWalletConnected({
@@ -19782,6 +19594,7 @@ function WalletSelectionModal({
19782
19594
  }
19783
19595
  const response = await provider.connect();
19784
19596
  const address = response.publicKey.toString();
19597
+ setUserDisconnectedWallet(false);
19785
19598
  const walletType = wallet.id === "solflare" ? "solflare" : wallet.id === "backpack" ? "backpack" : wallet.id === "glow" ? "glow" : "phantom-solana";
19786
19599
  onWalletConnected({
19787
19600
  type: walletType,
@@ -20086,6 +19899,7 @@ function DepositModal({
20086
19899
  hideDepositTracker = false,
20087
19900
  showBalanceHeader = false,
20088
19901
  transferInputVariant = "double_input",
19902
+ depositConfirmationMode = "auto_ui",
20089
19903
  enableConnectWallet = false,
20090
19904
  onDepositSuccess,
20091
19905
  onDepositError,
@@ -20177,6 +19991,7 @@ function DepositModal({
20177
19991
  };
20178
19992
  const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
20179
19993
  const handleWalletDisconnect = () => {
19994
+ setUserDisconnectedWallet(true);
20180
19995
  clearStoredWalletChainType();
20181
19996
  setBrowserWalletChainType(void 0);
20182
19997
  setBrowserWalletInfo(null);
@@ -20268,6 +20083,7 @@ function DepositModal({
20268
20083
  balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
20269
20084
  balanceChainId: destinationChainId,
20270
20085
  balanceTokenAddress: destinationTokenAddress,
20086
+ projectName: projectConfig?.project_name,
20271
20087
  publishableKey
20272
20088
  }
20273
20089
  ),
@@ -20348,7 +20164,14 @@ function DepositModal({
20348
20164
  title: t5.transferCrypto.title,
20349
20165
  showBack: true,
20350
20166
  onBack: handleBack,
20351
- onClose: handleClose
20167
+ onClose: handleClose,
20168
+ showBalance: showBalanceHeader,
20169
+ balanceAddress: recipientAddress,
20170
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
20171
+ balanceChainId: destinationChainId,
20172
+ balanceTokenAddress: destinationTokenAddress,
20173
+ projectName: projectConfig?.project_name,
20174
+ publishableKey
20352
20175
  }
20353
20176
  ),
20354
20177
  transferInputVariant === "single_input" ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
@@ -20360,6 +20183,7 @@ function DepositModal({
20360
20183
  destinationChainType,
20361
20184
  destinationChainId,
20362
20185
  destinationTokenAddress,
20186
+ depositConfirmationMode,
20363
20187
  onExecutionsChange: setDepositExecutions,
20364
20188
  onDepositSuccess,
20365
20189
  onDepositError,
@@ -20374,6 +20198,7 @@ function DepositModal({
20374
20198
  destinationChainType,
20375
20199
  destinationChainId,
20376
20200
  destinationTokenAddress,
20201
+ depositConfirmationMode,
20377
20202
  onExecutionsChange: setDepositExecutions,
20378
20203
  onDepositSuccess,
20379
20204
  onDepositError,
@@ -20388,7 +20213,14 @@ function DepositModal({
20388
20213
  showBack: true,
20389
20214
  onBack: handleBack,
20390
20215
  onClose: handleClose,
20391
- badge: cardView === "quotes" ? { count: quotesCount } : void 0
20216
+ badge: cardView === "quotes" ? { count: quotesCount } : void 0,
20217
+ showBalance: showBalanceHeader,
20218
+ balanceAddress: recipientAddress,
20219
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
20220
+ balanceChainId: destinationChainId,
20221
+ balanceTokenAddress: destinationTokenAddress,
20222
+ projectName: projectConfig?.project_name,
20223
+ publishableKey
20392
20224
  }
20393
20225
  ),
20394
20226
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
@@ -20638,6 +20470,7 @@ function UnifoldProvider2({
20638
20470
  destinationChainType: depositConfig.destinationChainType,
20639
20471
  destinationChainId: depositConfig.destinationChainId,
20640
20472
  destinationTokenAddress: depositConfig.destinationTokenAddress,
20473
+ depositConfirmationMode: depositConfig.depositConfirmationMode ?? "auto_ui",
20641
20474
  hideDepositTracker: config?.hideDepositTracker,
20642
20475
  showBalanceHeader: config?.showBalanceHeader,
20643
20476
  transferInputVariant: config?.transferInputVariant,